Linux下串口编程
Linux 系统下,诸如串口、触摸屏、GPIO、ADC 等等各种设备的操作,都是
通过访问其对应的设备节点进行控制。相应地,串口通过访问/dev/ttyS0、
/dev/ttyS1、/dev/ttyS2...对其进行配置与控制。
串口配置的参数包括:波特率,数据位,校验位,停止位与流控。
串口的配置主要是通过配置struct termios 结构体,其原型如下:
#include<termios.h>
struct termio
{
unsigned short c_iflag; /*输入模式标志*/
unsigned short c_oflag; /*输出模式标志*/
unsigned short c_cflag; /*控制模式标志*/
unsigned short c_lfag; /*本地模式标志*/
unsigned short c_line; /*line discipline*/
unsigned short c_cc[NCC]; /*control characters*/
};
其中,通过对c_cflag 与c_iflag 的赋值,可以设置波特率、数据位、奇偶校验位、
停止位、流控。
1、波特率配置
串口通过函数cfsetispeed 和cfsetospeed 设置端口的输入/输出波特率:
int cfsetispeed(struct termios *termios_p, speed_t speed);
int cfsetospeed(struct termios *termios_p, speed_t speed);
其中termios_p 为串口接头体termios 指针变量;speed 为需要设置的串口传输速
率,取值与波特率对应关系见表:
宏定
义
波特率(单位:bit/s) 宏定
义
波特率(单位:bit/s)
B0 0 B1800 1800
B50 50 B2400 2400
B75 75 B4800 4800
B110 110 B9600 9600
B134 134 B19200 19200
B150 150 B38400 38400
B200 200 B57600 57600
B300 300 B115200 115200
B600 600 B230400 230400
B1200 1200
2、数据位配置
串口数据位的配置通过修改termios 结构体成员c_cflag 实现,CS5、CS6、CS7
和CS8分别表示数据位为5、6、7和8。在设置数据位前,先使用CSIZE 做位屏
蔽:
termios_p.c_cflag &= ~CSIZE;
termios_p.c_cflag |= CS5; /*配置为5数据位*/
3、校验位配置
校验位包括:无校验、奇校验、偶校验、空格等:
无校验:
termios_p.c_cflag &= ~PARENB;
termios_p.c_iflag &= ~INPCK;
奇校验:
termios_p.c_cflag &= (PARODD | PARENB);
termios_p.c_iflag &= INPCK;
偶校验:
termios_p.c_cflag |= PARENB;
termios_p.c_cflag ~PARODD;
termios_p.c_iflag & |= INPCK;
空格:
termios_p.c_cflag &= ~PARENB;
termios_p.c_cflag &= ~CSTOPB;
termios_p.c_iflag |= INPCK;
4、停止位配置
串口停止位通过激活c_cflag 的CSTOPB 控制,具体方法如下:
1个停止位:
termios_p.c_cflag &= ~CSTOPB;
2个停止位:
termios_p.c_cflag |= CSTOPB;
5、流控配置
流控用于标识数据的开始与结束,流控的种类包括硬件流、软件流与不使用流控。
不使用流控:
termios_p.c_cflag &= ~CRTSCTS;
硬件流:
termios_p.c_cflag |= CRTSCTS;
软件流:
termios_p.c_cfalg |= IXON | IXOFF | IXANY;
例子程序:
程序实现了配置串口0参数与向串口0输出数据
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <asm/ioctl.h>
void Set_uart(int fd, int databits, int stopbit, char parity, char datastream)
{
int ret;
struct termios termios_opt;
if(tcgetattr(fd, &termios_opt))
{
perror("tcgetattr error\n");
return;
}
/*flush memory*/
tcflush(fd,TCIOFLUSH);
/*Set i/o speed*/
cfsetispeed(&termios_opt, B115200);
cfsetospeed(&termios_opt, B115200);
/*active options*/
termios_opt.c_cflag |= CLOCAL | CREAD;
/*set databits,default is 8 databits*/
termios_opt.c_cflag &= ~CSIZE;
switch (databits)
{
case 5:
termios_opt.c_cflag |= CS5;
break;
case 6:
termios_opt.c_cflag |= CS6;
break;
case 7:
termios_opt.c_cflag |= CS7;
break;
case 8:
termios_opt.c_cflag |= CS8;
break;
default:
termios_opt.c_cflag |= CS8;
break;
}
/*Set Parity, default is no vertify*/
switch (parity)
{
case 'N': /*no vertify*/
termios_opt.c_cflag &= ~PARENB;
termios_opt.c_iflag &= ~INPCK;
break;
case 'O': /*odd vertify*/
termios_opt.c_cflag |= (PARODD | PARENB);
termios_opt.c_iflag |= INPCK;
break;
case 'E': /*even vertify*/
termios_opt.c_cflag |= PARENB;
termios_opt.c_cflag &= ~PARODD;
termios_opt.c_iflag |= INPCK;
break;
case 'S': /*space vertify*/
termios_opt.c_cflag &= ~PARENB;
termios_opt.c_cflag &= ~CSTOPB;
termios_opt.c_iflag |= INPCK;
break;
default:
termios_opt.c_cflag &= ~PARENB;
termios_opt.c_iflag &= ~INPCK;
break;
}
/*Set stop bits, default is 1 stopbit*/
switch (stopbit)
{
case 1:
termios_opt.c_cflag &= ~CSTOPB;
break;
case 2:
termios_opt.c_cflag |= CSTOPB;
break;
default:
termios_opt.c_cflag &= ~CSTOPB;
break;
}
/*set data stream,default is no data stream control*/
switch (datastream)
{
case 'N': /*no data stream control*/
termios_opt.c_cflag &= ~CRTSCTS;
break;
case 'H': /*hardware data stream control*/
termios_opt.c_cflag |= CRTSCTS;
break;
case 'S': /*software data stream control*/
termios_opt.c_cflag |= IXON | IXOFF | IXANY;
break;
default:
termios_opt.c_cflag &= ~CRTSCTS;
break;
}
/*oput modle,initial data output*/
termios_opt.c_oflag &= ~OPOST;
/*set waiting time and recv min character*/
termios_opt.c_cc[VTIME] = 0;
termios_opt.c_cc[VMIN] = 0;
/*flush memory*/
tcflush(fd,TCIFLUSH);
/*start using new options*/
if((tcsetattr(fd,TCSANOW,&termios_opt)) != 0)
{
perror("serial setup error\n");
return;
}
printf("set serial done!\n");
return ;
}
int main(void)
{
int serial_fd;
unsigned char data[14] = {0};
memset(data,'a',sizeof(data));
printf("open UART..\n");
serial_fd = open("/dev/ttyS0",O_RDWR | O_NOCTTY | O_NONBLOCK);
if (serial_fd == -1)
{
perror("Serial open error!\n");
return -1;
}
/*Set uart*/
Set_uart(serial_fd, 8, 1, 'N', 'N'); //8 databits, 1 stopbit, No vertify, No data stream control
while(1)
{
write(serial_fd, data, sizeof(data));
tcdrain(serial_fd);
sleep(2);
}
close(serial_fd);
return 0;
}