1、Linux串口通信编程/*串口设备无论是在工控领域,还是在嵌入式设备领域,应用都非常广泛。而串口编程也就显得必不可少。偶然的一次机会,需要使用串口,而且操作系统还要求是Linux,因此,趁着这次机会,综合别人的代码,进行了一次整理和封装。具体的封装格式为C代码,这样做是为了很好的移植性,使它可以在C和C+环境下,都可以编译和使用。代码的头文件如下: */filename:stty.h#ifndef_STTY_H_#define_STTY_H_/包含头文件#include#include#include#include#include#include#include#include#includ
2、e/ 串口设备信息结构typedefstructtty_info_tintfd;/ 串口设备IDpthread_mutex_tmt;/ 线程同步互斥对象charname24;/ 串口设备名称,例:/dev/ttyS0structtermios ntm;/ 新的串口设备选项structtermios otm;/ 旧的串口设备选项TTY_INFO;/ 串口操作函数TTY_INFO*readyTTY(intid);intsetTTYSpeed(TTY_INFO*ptty,intspeed);intsetTTYParity(TTY_INFO*ptty,intdatabits,intparity,int
3、stopbits);intcleanTTY(TTY_INFO*ptty);intsendnTTY(TTY_INFO*ptty,char*pbuf,intsize);intrecvnTTY(TTY_INFO*ptty,char*pbuf,intsize);intlockTTY(TTY_INFO*ptty);intunlockTTY(TTY_INFO*ptty);#endif/*从头文件中的函数定义不难看出,函数的功能,使用过程如下:(1) 打开串口设备,调用函数setTTYSpeed();(2) 设置串口读写的波特率,调用函数setTTYSpeed();(3) 设置串口的属性,包括停止位、校验位
4、、数据位等,调用函数setTTYParity();(4) 向串口写入数据,调用函数sendnTTY();(5) 从串口读出数据,调用函数recvnTTY();(6) 操作完成后,需要调用函数cleanTTY()来释放申请的串口信息接口;其中,lockTTY()和unlockTTY()是为了能够在多线程中使用。在读写操作的前后,需要锁定和释放串口资源。具体的使用方法,在代码实现的原文件中,main()函数中进行了演示。下面就是源代码文件: */stty.c#include#include#includestty.h/ 初始化串口设备并进行原有设置的保存TTY_INFO*readyTTY(inti
5、d)TTY_INFO*ptty;ptty=(TTY_INFO*)malloc(sizeof(TTY_INFO);if(ptty=NULL)returnNULL;memset(ptty,0,sizeof(TTY_INFO);pthread_mutex_init(&ptty-mt,NULL);sprintf(ptty-name,/dev/ttyS%d,id);/ 打开并且设置串口ptty-fd=open(ptty-name,O_RDWR|O_NOCTTY|O_NDELAY);if(ptty-fdfd,&ptty-otm);returnptty;/ 清理串口设备资源intcleanTTY(TTY_I
6、NFO*ptty)/ 关闭打开的串口设备if(ptty-fd0)tcsetattr(ptty-fd,TCSANOW,&ptty-otm);close(ptty-fd);ptty-fd=-1;free(ptty);ptty=NULL;return0;/ 设置串口通信速率/ ptty 参数类型(TTY_INFO *),已经初始化的串口设备信息结构指针/ speed 参数类型(int),用来设置串口的波特率/ return 返回值类型(int),函数执行成功返回零值,否则返回大于零的值/intsetTTYSpeed(TTY_INFO*ptty,intspeed)inti;/ 进行新的串口设置,数据位
7、为8位bzero(&ptty-ntm,sizeof(ptty-ntm);tcgetattr(ptty-fd,&ptty-ntm);ptty-ntm.c_cflag=/*CS8 |*/CLOCAL|CREAD;switch(speed)case300:ptty-ntm.c_cflag|=B300;break;case1200:ptty-ntm.c_cflag|=B1200;break;case2400:ptty-ntm.c_cflag|=B2400;break;case4800:ptty-ntm.c_cflag|=B4800;break;case9600:ptty-ntm.c_cflag|=B9
8、600;break;case19200:ptty-ntm.c_cflag|=B19200;break;case38400:ptty-ntm.c_cflag|=B38400;break;case115200:ptty-ntm.c_cflag|=B115200;break;ptty-ntm.c_iflag=IGNPAR;ptty-ntm.c_oflag=0;/tcflush(ptty-fd,TCIFLUSH);tcsetattr(ptty-fd,TCSANOW,&ptty-ntm);/return0;/ 设置串口数据位,停止位和效验位/ ptty 参数类型(TTY_INFO *),已经初始化的串口
9、设备信息结构指针/ databits 参数类型(int), 数据位,取值为7或者8/ stopbits 参数类型(int),停止位,取值为1或者2/ parity 参数类型(int),效验类型 取值为N,E,O,S/ return 返回值类型(int),函数执行成功返回零值,否则返回大于零的值/intsetTTYParity(TTY_INFO*ptty,intdatabits,intparity,intstopbits)/ 取得串口设置if(tcgetattr(ptty-fd,&ptty-ntm)!=0)printf(SetupSerial %sn,ptty-name);return1;bze
10、ro(&ptty-ntm,sizeof(ptty-ntm);ptty-ntm.c_cflag=CS8|CLOCAL|CREAD;ptty-ntm.c_iflag=IGNPAR;ptty-ntm.c_oflag=0;/ 设置串口的各种参数ptty-ntm.c_cflag&=CSIZE;switch(databits)/设置数据位数case7:ptty-ntm.c_cflag|=CS7;break;case8:ptty-ntm.c_cflag|=CS8;break;default:printf(Unsupported data sizen);return5;/switch(parity)/ 设置奇
11、偶校验位数casen:caseN:ptty-ntm.c_cflag&=PARENB;/* Clear parity enable */ptty-ntm.c_iflag&=INPCK;/* Enable parity checking */break;caseo:caseO:ptty-ntm.c_cflag|=(PARODD|PARENB);/* 设置为奇效验*/ptty-ntm.c_iflag|=INPCK;/* Disnable parity checking */break;casee:caseE:ptty-ntm.c_cflag|=PARENB;/* Enable parity */pt
12、ty-ntm.c_cflag&=PARODD;/* 转换为偶效验*/ptty-ntm.c_iflag|=INPCK;/* Disnable parity checking */break;caseS:cases:/*as no parity*/ptty-ntm.c_cflag&=PARENB;ptty-ntm.c_cflag&=CSTOPB;break;default:printf(Unsupported parityn);return2;/ 设置停止位switch(stopbits)case1:ptty-ntm.c_cflag&=CSTOPB;break;case2:ptty-ntm.c_c
13、flag|=CSTOPB;break;default:printf(Unsupported stop bitsn);return3;/ptty-ntm.c_lflag=0;ptty-ntm.c_ccVTIME=0;/ inter-character timer unusedptty-ntm.c_ccVMIN=1;/ blocking read until 1 chars receivedtcflush(ptty-fd,TCIFLUSH);if(tcsetattr(ptty-fd,TCSANOW,&ptty-ntm)!=0)printf(SetupSerial n);return4;return
14、0;intrecvnTTY(TTY_INFO*ptty,char*pbuf,intsize)intret,left,bytes;left=size;while(left0)ret=0;bytes=0;pthread_mutex_lock(&ptty-mt);ioctl(ptty-fd,FIONREAD,&bytes);if(bytes0)ret=read(ptty-fd,pbuf,left);pthread_mutex_unlock(&ptty-mt);if(ret0)left-=ret;pbuf+=ret;usleep(100);returnsize-left;intsendnTTY(TTY
15、_INFO*ptty,char*pbuf,intsize)intret,nleft;char*ptmp;ret=0;nleft=size;ptmp=pbuf;while(nleft0)pthread_mutex_lock(&ptty-mt);ret=write(ptty-fd,ptmp,nleft);pthread_mutex_unlock(&ptty-mt);if(ret0)nleft-=ret;ptmp+=ret;/usleep(100);returnsize-nleft;intlockTTY(TTY_INFO*ptty)if(ptty-fdfd,LOCK_EX);intunlockTTY
16、(TTY_INFO*ptty)if(ptty-fdfd,LOCK_UN);#ifdefLEAF_TTY_TEST/ 接口测试intmain(intargc,char*argv)TTY_INFO*ptty;intnbyte,idx;unsignedcharcc16;ptty=readyTTY(0);if(ptty=NULL)printf(readyTTY(0) errorn);return1;/lockTTY(ptty);if(setTTYSpeed(ptty,9600)0)printf(setTTYSpeed() errorn);return-1;if(setTTYParity(ptty,8,N,1)0)printf(setTTYParity() errorn);return-1;/idx=0;while(1)cc0=0xFA;sendnTTY(ptty,&cc0,1);nbyte=recvnTTY(ptty,cc,1);printf(%d:%02Xn,idx+,cc0);cleanTTY(ptty);#endif