1、Linux 串口编程Linux 下的串口编程, 在嵌入式开发中占据着重要的地位, 因为很多的嵌入式设备都是通过串口交换数据的。在没有操作系统的我们可以使用 UART 的中断来出来数据的接受和发送,而在 Linux 操作系统下,我们也可以使用软中断的方式来处理数据的接受和发送,这里主要使用的是信号 SIGIO,也就是异步 I/O。这里也可以使用 select 实现异步形式的通知。这里可以参考UNIX 环境高级编程中的第 14 章 高级I/O 和第 18 章的 I/O 终端,这两章描述了串口的编程和异步 I/O 方面的内容。还有一本书linux serialprogramming how-to ,
2、 Serial Programming Guide for POSIX Operating Systems 。这都是串口编程的必读和经典书籍。串口参数的设置一般包括波特率、起始位数量、数据位、停止位和流控协议。在接收端和发送端要配置成一样的参数设置。在 Linux 中,所有的设备文件一般都位于“/dev”下,其中串口一、串口二对应的设备名依次为 “/dev/ttyS0” 、 /dev/ttyS1。 这可以通过查看/dev下的文件加以确认。 串口的参数设置为 115200,8, N ,1。也就是波特率是 115200,8 位数据位,无奇偶校验位,1 位停止位。串口编程中有一个最重要的结构体:st
3、ruct termiostcflag_t c_iflag; /* 输入选项标志 */tcflag_t c_oflag; /* 输出选项标志 */tcflag_t c_cflag; /* 控制选项标志 */tcflag_t c_lflag; /* 本地选项标志 */unsigned char c_line /*线控制*/cc_t c_ccNCCS; /* 控制特性 */;这个结构中最重要的是 c_cflag。通过对它的赋值,用户可以设置波特率、字符大小、数据位、停止位、奇偶校验位和硬件流控等。其中的参数在网上和很多的书籍上都介绍的很详细。在 c_lflag 中有这么一个参数 ICANON,如若设
4、置,则按规范模式工作,这使下列字符起作用:EOF、EOL EOL2、 ERASE、 KILL、 REPRINT 、STATUS、WERASE。输入字符被装配成行。如果不以规范模式工作,则读请求直接从输入队列取字符。在至少接收到 MIN 个字节或已超过 TIME 值之前,read 将不返回。在规范模式很容易:系统每次返回一行。但在非规范模式下,系统怎样才能知道在什么时候将数据返回给我们呢?如果它一次返回一个字节,那么系统开销就很大。解决方法是:当已读了指定量的数据后,或者已经过了给定的时间后,即通知系统返回。这种技术使用了 termios 结构中 c_cc 数组的两个变量:MIN和 TIME。C
5、_cc 数据中的这两个元素的下标名为 VMIN 和 VTIME。MIN 说明一个 read 返回前的最小字节数。TIME 说明等待数据到达的分秒数。需要包括的头文件是:#include #include #include #include #include #include #include #include #include #include Set_Uart.c其中的“Set_Uart.c”是设置串口的模式和打开串口的文件。模式的设置就是按上面说的进行设置。下面是发送数据,写串口的程序int main(void)int fd;int nwrite,i;char buff = Hello w
6、orld!n;fd = 0;/*打开串口*/if(fd = open_port(fd,0) 0) /在我的 Set_Uart.c 文件中定义。perror(open_port error!n);return (-1);/*设置串口*/if(i = set_opt(fd,115200,8,N,1) 0) /在 Set_Uart.c 文件中定义perror(set_opt error!n);return (-1);printf(fd =%dn,fd);/*向串口写入字符串*/sleep(10);nwrite = write(fd,buff,strlen(buff);sleep(10);printf
7、(nwrite = %dn,nwrite);close(fd);return (1);把该文件进行交叉编译后下载到开发板,进行运行./Write_Uart。软中断读取数据的 main 函数。Read_Uart_IRQ.c 当使用中断方式的读取数据时,要先运行开发板上的Write_Uart.c 文件, 然后, 立即关闭, 再在 PC 上运行读取数据的 Read_Uart_IRQ.c 文件。 所以, 在 Write_Uart.c中,在使用 write()函数向 UART 写数据之间加入一小段的延时。这样便于关闭 minicom,如果在两台 PC上进行测试的话,应该不存在此问题。int main(v
8、oid)int fd,res,i;struct sigaction saio; /*definition of signal axtion */char buf255;fd_set rd;fd = 0;/*打开串口*/if(fd = open_port(fd,1)0)perror(open_port error!n);return (-1);/* install the signal handle before making the device asynchronous*/saio.sa_handler = signal_handler_IO;sigemptyset(&saio.sa_mas
9、k);/saio.sa_mask = 0; 必须用 sigemptyset 函数初始话 act 结构的 sa_mask 成员saio.sa_flags = 0;saio.sa_restorer = NULL;sigaction(SIGIO,&saio,NULL);/* allow the process to recevie SIGIO*/fcntl(fd,F_SETOWN,getpid();/* Make the file descriptor asynchronous*/fcntl(fd,F_SETFL,FASYNC);/*设置串口*/if(i= set_opt(fd,115200,8,N
10、,1)0)perror(set_opt error!n);return (-1);/* loop while waiting for input,normally we would do something useful here*/while(STOP = FALSE)usleep(100000);/* after receving SIGIO ,wait_flag = FALSE,input is availabe and can be read*/if(wait_flag = FALSE)memset(buf,0,255);res = read(fd,buf,255);printf(nr
11、ead=%d,%sn,res,buf);if(res = 1)STOP = TRUE; /*stop loop if only a CR was input */wait_flag = TRUE; /*wait for new input*/close(fd);return 0;/*信号处理函数,设备 wait_flag=FASLE*/void signal_handler_IO(int status)printf(received SIGIO signale.n);wait_flag = FALSE;下面是 select 方式的读取数据的 main 函数。Read_Uart.cint mai
12、n(void)int fd;int nread,nwrite,i;char buff8;fd_set rd;fd = 0;/*打开串口*/if(fd = open_port(fd,1) 0)perror(open_port error!n);return ;/*设置串口*/if(i= set_opt(fd,115200,8,N,1) 0)perror(set_opt error!n);return (-1);/*利用 select 函数来实现多个串口的读写*/while(1)FD_ZERO(&rd);FD_SET(fd,&rd);while(FD_ISSET(fd,&rd)if(select(
13、fd+1,&rd,NULL,NULL,NULL) 0)printf(nread = %d,%sn,nread,buff);printf(nread = %d,%sn,nread,buff);close(fd);return ;下面是运行的结果,PC 机收到的开发板发送过来的数据。./Read_Uart_IRQfcntl = 0isatty success !fd-open=3setreceived SIGIO signale.nread=13,Hello其中串口中的一些重要的设备如下;/*设置等待时间它最小接收字符*/newtio.c_ccVTIME = 1;newtio.c_ccVMIN = 0;newtio.c_lflag &= ( ECHO | ECHOE | ISIG);newtio.c_lflag |=ICANON; /关闭 ICANON 标志就使终端处于非规范模式 现在处于打开 处于规范模式下newtio.c_oflag &= OPOST; /执行输出处理 现在就关闭状态newtio.c_iflag |= (IGNPAR | ICRNL); /忽略奇偶校验错误 将 CR 映射成 NL
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。