经过验证是准确无误的,配置以后可以通过以下指令查看
stty -F /dev/ttyUSB0 -a //查看/dev/ttyUSB0的串口配置
stty -F /dev/ttyUSB0 ispeed 115200 ospeed 115200 cs8 //配置/dev/ttyUSB0的输入输出波特率和数据位
/*******************************************************************
*名称: UART_Open
*功能: 打开串口并返回串口设备文件描述
*入口参数: fd 文件描述符
port 串口号(ttyS0,ttyS1,ttyS2)
*出口参数:正确返回为文件描述符,错误返回为-1
*******************************************************************/
int UART_Open(int fd, const char *port) {
printf("UART_OPEN start\n");
int flags = 0;
fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0) {
fprintf(stderr, "fd = %d can not open %s\n", fd, port);
return (FALSE);
}
//获取原来的状态
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) {
perror("fcntl");
return -1;
}
// 设置串口为非阻塞状态 具体情况具体对待
flags |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) < 0) {
fprintf(stderr, "fd = %d fcntl failed \n", fd);
return (FALSE);
} else {
printf("fcntl=%d\n", fcntl(fd, F_SETFL, 0));
}
//测试是否为终端设备
if (0 == isatty(STDIN_FILENO)) { //如果不是终端设备
// isatty,函数名。主要功能是检查设备类型 , 判断文件描述词是否是为终端机。
// 用 法: int isatty(int desc);
// 返回值:如果参数desc所代表的文件描述词为一终端机则返回1,否则返回0。
printf("standard input is not a terminal device\n");
return (FALSE);
}
printf("UART_OPEN end\n");
return fd;
}
/*******************************************************************
*名称: UART_Close
*功能: 关闭串口并返回串口设备文件描述
*入口参数: fd 文件描述符
port 串口号(ttyS0,ttyS1,ttyS2,ttyUSB0等)
*出口参数:void
*******************************************************************/
void UART_Close(int fd) { close(fd); }
/*******************************************************************
* 名称: UART_Recv
* 功能: 接收串口数据
* 入口参数: fd 文件描述符
* rcv_buf 接收串口中数据存入rcv_buf缓冲区中
* data_len 一帧数据的长度
* 出口参数: 正确返回为1,错误返回为0
*******************************************************************/
int UART_Recv(int fd, char *rcv_buf, int data_len) {
return read(
fd, rcv_buf,
data_len); //底层只负责读操作,结果返回给上层,以便上层根据需求来操作
}
/********************************************************************
* 名称: UART_Send
* 功能: 发送数据
* 入口参数: fd 文件描述符
* send_buf 存放串口发送数据
* data_len 一帧数据的个数
* 出口参数: 正确返回为发送的长度,错误返回为0
*******************************************************************/
int UART_Send(int fd, char *send_buf, int data_len) {
printf("fd = %d UART_Send_DATA : %s\n", fd, send_buf);
return write(
fd, send_buf,
data_len); //底层只负责写,写的结果返回给上层,以便上层根据具体情况具体解决
}
/*******************************************************************
*名称: set_opt
*功能: 设置串口数据位,停止位和效验位
*入口参数: fd 串口文件描述符
* baudrate 串口速度
* flow_ctrl 数据流控制
* databits 数据位 取值为 7 或者8
* stopbits 停止位 取值为 1 或者2
* parity 效验类型 取值为N,E,O,,S
*出口参数:正确返回为0,错误返回为-1
*******************************************************************/
static int set_opt(int fd, int baudrate, int flow_ctrl, int databits,
int stopbits, int parity) {
struct termios new_uart_options;
struct termios old_uart_options;
// termios
// 函数族提供了一个常规的终端接口,用于控制非同步通信端口。
// 这个结构包含了至少下列成员:
// tcflag_t c_iflag; /* 输入模式 */
// tcflag_t c_oflag; /* 输出模式 */
// tcflag_t c_cflag; /* 控制模式 */
// tcflag_t c_lflag; /* 本地模式 */
// cc_t c_cc[NCCS]; /* 控制字符 */
// struct termios
// {unsigned short c_iflag; /* 输入模式标志*/
// unsigned short c_oflag; /* 输出模式标志*/
// unsigned short c_cflag; /* 控制模式标志*/
// unsigned short c_lflag; /*区域模式标志或本地模式标志或局部模式*/
// unsigned char c_line; /*行控制line discipline */
// unsigned char c_cc[NCC]; /* 控制字符特性*/
if (tcgetattr(fd, &old_uart_options) !=
0) { /* tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将它们保存于options,该函数还可以测试配置是否正确,
该串口是否可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1. */
fprintf(stderr, "fd = %d SetupSerial err:%s\n", fd, strerror(errno));
return FALSE;
}
bzero(&new_uart_options, sizeof(new_uart_options)); //清零new_uart_options
new_uart_options.c_cflag |= CLOCAL; //修改控制模式,保证程序不会占用串口
new_uart_options.c_cflag |=
CREAD; //修改控制模式,使得能够从串口中读取输入数据
new_uart_options.c_cflag &= ~CSIZE; //设置数据位字节
//设置数据位
switch (databits) { //默认8位数据位
case 7:
new_uart_options.c_cflag |= CS7;
break;
case 8:
new_uart_options.c_cflag |= CS8;
break;
default:
fprintf(stderr, "fd = %d unsupported databits\n", fd);
return FALSE;
break;
}
//设置波特率
switch (baudrate) {
case 9600:
cfsetispeed(&new_uart_options, B9600);
cfsetospeed(&new_uart_options, B9600);
break;
case 19200:
cfsetispeed(&new_uart_options, B19200);
cfsetospeed(&new_uart_options, B19200);
break;
case 38400:
cfsetispeed(&new_uart_options, B38400);
cfsetospeed(&new_uart_options, B38400);
break;
case 57600:
cfsetispeed(&new_uart_options, B57600);
cfsetospeed(&new_uart_options, B57600);
break;
case 115200:
cfsetispeed(&new_uart_options, B115200);
cfsetospeed(&new_uart_options, B115200);
break;
default:
fprintf(stderr, "fd = %d unsupported baudrate\n", fd);
return FALSE;
break;
}
switch (flow_ctrl) { //默认无流控
case 0: //不使用流控
new_uart_options.c_cflag &= ~CRTSCTS;
break;
case 1: //使用硬件流控
new_uart_options.c_cflag |= CRTSCTS;
break;
case 2: //使用软件流控
new_uart_options.c_cflag |= IXON | IXOFF | IXANY;
break;
default:
fprintf(stderr, "fd = %d unsupported flow_ctrl\n", fd);
return FALSE;
break;
}
//设置校验位
switch (parity) {
case 'N': //无奇偶校验
new_uart_options.c_cflag &= ~PARENB;
// new_uart_options.c_cflag &= ~INPCK;
break;
case 'O': //设置为奇校验
new_uart_options.c_cflag |= PARENB;
new_uart_options.c_cflag |= PARODD;
new_uart_options.c_cflag |= (INPCK | ISTRIP);
break;
case 'E': //设置为偶校验
new_uart_options.c_cflag |= (INPCK | ISTRIP);
new_uart_options.c_cflag |= PARENB;
new_uart_options.c_cflag &= ~PARODD;
break;
default:
fprintf(stderr, "fd = %d unsupported parity\n", fd);
return FALSE;
break;
}
// 设置停止位
switch (stopbits) {
case 1:
new_uart_options.c_cflag &= ~CSTOPB;
break;
case 2:
new_uart_options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr, "fd = %d unsupported stopbits\n", fd);
return FALSE;
break;
}
// //修改输出模式,原始数据输出
new_uart_options.c_oflag &= ~OPOST;
new_uart_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
// new_uart_options.c_lflag &= ~(ISIG | ICANON);
//设置等待时间和最小接收字符
new_uart_options.c_cc[VTIME] = 0; /* 读取一个字符等待1*(1/10)s */
new_uart_options.c_cc[VMIN] = 0; /* 读取字符的最少个数为1 */
//如果发生数据溢出,接收数据,但是不再读取 刷新收到的数据但是不读
tcflush(fd, TCIFLUSH);
// int tcflush(int fd, int queue_selector);
//
// fd // 终端I/O打开的句柄
//
// queue_selector // 控制tcflush的操作,取值为下面三个常数中的一个:
//
// TCIFLUSH // 清除正收到的数据,且不会读取出来。
//
// TCOFLUSH // 清除正写入的数据,且不会发送至终端。
//
// TCIOFLUSH // 清除所有正在发生的I/O数据。
// 返回值说明:
//
// 0 // 成功
//
// -1 // 失败,并且为 errno 置值来指示错误
//激活配置 (将修改后的termios数据设置到串口中)
if (tcsetattr(fd, TCSANOW, &new_uart_options) !=
0) { // tcsetattr函数用于设置终端参数。函数在成功的时候返回0,失败的时候返回-1,并设置errno的值。
// perror("com set error!\n");
fprintf(stderr, "fd = %d com set err! errstring = %s\n", fd,
strerror(errno));
return FALSE;
}
return TRUE;
}
/*******************************************************************
*名称: UART_Init()
*功能: 串口初始化
*入口参数: fd 文件描述符
* baudrate 串口速度
* flow_ctrl 数据流控制
* databits 数据位 取值为 7 或者8
* stopbits 停止位 取值为 1 或者2
* parity 效验类型 取值为N,E,O,,S
*
*出口参数:正确返回为1,错误返回为0
*******************************************************************/
int UART_Init(int fd, int baudrate, int flow_ctrl, int databits, int stopbits,
int parity) {
printf("UART_Init\n");
return set_opt(fd, baudrate, flow_ctrl, databits, stopbits, parity);
}