跳转到主内容
思享编程网:思考分享,玩转编程世界!

linux 中的串口驱动

1.流程描述 打开串口设备:首先需要打开串口设备文件,通常是/dev/ttyX(如/dev/ttyUSB0,/dev/ttyS0等)。

可以使用open()系统调用打开串口设备文件,获取一个文件描述符。

配置串口属性:打开串口后,需要配置串口的属性,例如波特率、数据位、奇偶校验、停止位等。

可以使用termios库来设置串口属性。

读写数据:串口配置完成后,可以使用read()和write()系统调用来进行串口数据的读取和写入。

此外,还可以通过select()或poll()等系统调用进行多路复用,实现同时监听串口和其他文件描述符上的事件 2.open函数标志位的含义 在打开串口设备时,可以使用一些标志位(flags)来设置打开模式和行为。

下面是常见的一些标志位及其含义:

O_RDWR

:以读写模式打开设备。

允许读取和写入设备数据。

O_NOCTTY

:如果设备是终端设备(例如串口),不将它作为进程的控制终端。

这通常用于防止串口设备接管终端特性(如终端窗口)。

一般在打开串口设备时使用这个标志位。

O_NDELAY

(也叫

O_NONBLOCK

):将文件描述符设置为非阻塞模式。

在非阻塞模式下,读取和写入文件描述符将立即返回。

如果没有数据可读取,读取操作将返回-1,并将

errno

设置为

EAGAIN

如果写入操作无法立即完成,将返回-1,并将

errno

设置为

EAGAIN

不建议在打开串口时使用此标志位,因为在阻塞式读取串口数据时,我们希望等待数据的到达。

O_RDONLY

:以只读模式打开设备。

只允许读取设备数据。

O_WRONLY

:以只写模式打开设备。

只允许写入设备数据。

O_CREAT

:如果设备不存在,创建设备。

在使用此标志位时,需要提供另外的参数,如文件权限。

O_EXCL

:与

O_CREAT

一起使用,确保创建新设备而不是打开现有设备。

O_APPEND

:以追加模式打开设备。

每次写入操作都将数据追加到文件末尾。

O_TRUNC

:打开设备之前,先将其内容截断为零长度。

3.实现

/**

****************************************************************************** * @file bsp_uart.c * @author cj * @version V1.0 * @date 2019/4 * @brief ****************************************************************************** * @attention

****************************************************************************** */

#include "bsp_uart.h" #include "typedef.h" #include #include #include #include #include #include #include #include #include

static UartStatus initComm(const char *ttyDir, const int stop, const unsigned speed) { UartStatus uartStatus;

uartStatus.fd = -1; uartStatus.isEnabled = false;

int retry = 60;

uartStatus.fd = open(ttyDir, O_RDWR | O_NOCTTY /*| O_NDELAY*/); if (uartStatus.fd < 0) { CJdebug("can not open this driver\n"); return uartStatus; }

while (lockf(uartStatus.fd, F_TLOCK, 0) < 0) { sleep(1); retry--; if (retry <= 0) { CJdebug("Devcie %s locked.\n", ttyDir); close(uartStatus.fd); return uartStatus; } }

unsigned currentSpeed = B9600;

switch (speed) { case 9600: currentSpeed = B9600; break; case 38400: currentSpeed = B38400; break; case 57600: currentSpeed = B57600; break; case 115200: currentSpeed = B115200; break; default: CJdebug("speed error\n"); return uartStatus; }

struct termios Opt; tcgetattr(uartStatus.fd, &Opt); cfsetispeed(&Opt, currentSpeed); cfsetospeed(&Opt, currentSpeed); tcsetattr(uartStatus.fd, TCSANOW, &Opt); tcflush(uartStatus.fd, TCIOFLUSH);

tcgetattr(uartStatus.fd, &Opt);

/* Set data bit 8bit */ Opt.c_cflag &= ~CSIZE; Opt.c_cflag |= CS8;

Opt.c_cflag |= IXON | IXOFF | IXANY; /* Set parity bit: None parity bit */ Opt.c_cflag &= ~PARENB;

/* stop bit */ switch (stop) { case 1: Opt.c_cflag &= ~CSTOPB; break; case 2: Opt.c_cflag |= CSTOPB; break; default: Opt.c_cflag &= ~CSTOPB; break; }

Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); Opt.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); Opt.c_oflag &= ~OPOST;

/* set timeout in deciseconds for non-canonical read */ Opt.c_cc[VTIME] = 150; //over time Opt.c_cc[VMIN] = 0; //DATA_LEN;

if (tcsetattr(uartStatus.fd, TCSANOW, &Opt) < 0) { perror(ttyDir); close(uartStatus.fd); return uartStatus; }

tcflush(uartStatus.fd, TCIOFLUSH);

uartStatus.isEnabled = true;

return uartStatus; }

/** * @brief Uart_init * @param speed * @param stop * @param name * @return */ UartStatus uartInit(const unsigned speed, const int stop, const char *name) { char dev[64] = {0}; memset(dev, 0, sizeof(dev)); sprintf(dev, "/dev/%s", name); UartStatus status = initComm(dev, stop, speed);

return status; }

int uart_readComm(UartStatus *uart, char *data, int dataLen) { return read(uart->fd, data, dataLen); }

bool uart_writeComm(UartStatus *uart, unsigned char *data, int dataLen) { if(write(uart->fd, data, dataLen) < dataLen) { CJdebug("uartComm write error !\n"); return false; }

return true; }

#ifndef BSP_UART_H

#define BSP_UART_H

#ifdef __cplusplus extern "C" { #endif

#include "typedef.h"

typedef struct _UartStatus { int fd; bool isEnabled; } UartStatus;

UartStatus uartInit(const unsigned speed, const int stop, const char *name); bool uart_writeComm(UartStatus *uart, unsigned char *data, int dataLen); int uart_readComm(UartStatus *uart, char *data, int dataLen);

#ifdef __cplusplus } #endif

#endif

相关文章