linux 串口特别是接收
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                linux 串口特别是接收
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                串口open之后就是設置了。設置后就可以進行read,write等類似操作了。
 今天寫串口程序,寫很好寫,但是不能讀,最找到了讀的方法
 
 
先說下使用方法吧:
comtest -d /dev/ttyUSB0 -o ?打開串口USB0
# include <stdio.h> # include <stdlib.h> # include <termio.h> # include <unistd.h> # include <fcntl.h> # include <getopt.h> # include <time.h> # include <errno.h> # include <string.h> static void Error(const char *Msg) {fprintf (stderr, "%s\n", Msg);fprintf (stderr, "strerror() is %s\n", strerror(errno));exit(1); } static void Warning(const char *Msg) {fprintf (stderr, "Warning: %s\n", Msg); }static int SerialSpeed(const char *SpeedString) {int SpeedNumber = atoi(SpeedString); # define TestSpeed(Speed) if (SpeedNumber == Speed) return B##SpeedTestSpeed(1200);TestSpeed(2400);TestSpeed(4800);TestSpeed(9600);TestSpeed(19200);TestSpeed(38400);TestSpeed(57600);TestSpeed(115200);TestSpeed(230400);Error("Bad speed");return -1; }static void PrintUsage(void) {fprintf(stderr, "comtest - interactive program of comm port\n");fprintf(stderr, "press [ESC] 3 times to quit\n\n");fprintf(stderr, "Usage: comtest [-d device] [-t tty] [-s speed] [-7] [-c] [-x] [-o] [-h]\n");fprintf(stderr, " -7 7 bit\n");fprintf(stderr, " -x hex mode\n");fprintf(stderr, " -o output to stdout too\n");fprintf(stderr, " -c stdout output use color\n");fprintf(stderr, " -h print this help\n");exit(-1); }static inline void WaitFdWriteable(int Fd) {fd_set WriteSetFD;FD_ZERO(&WriteSetFD);FD_SET(Fd, &WriteSetFD);if (select(Fd + 1, NULL, &WriteSetFD, NULL, NULL) < 0) {Error(strerror(errno));}}int main(int argc, char **argv) {int CommFd, TtyFd;struct termios TtyAttr;struct termios BackupTtyAttr;int DeviceSpeed = B9600;int TtySpeed = B9600;int ByteBits = CS8;const char *DeviceName = "/dev/ttySAC0";const char *TtyName = "/dev/tty";int OutputHex = 0;int OutputToStdout = 0;int UseColor = 0;opterr = 0;for (;;) {int c = getopt(argc, argv, "d:s:t:7xoch");if (c == -1)break;switch(c) {case 'd':DeviceName = optarg;break;case 't':TtyName = optarg;break;case 's':if (optarg[0] == 'd') {DeviceSpeed = SerialSpeed(optarg + 1);} else if (optarg[0] == 't') {TtySpeed = SerialSpeed(optarg + 1);} elseTtySpeed = DeviceSpeed = SerialSpeed(optarg);break;case 'o':OutputToStdout = 1;break;case '7':ByteBits = CS7;break;case 'x':OutputHex = 1;break;case 'c':UseColor = 1;break;case '?':case 'h':default:PrintUsage();}}if (optind != argc)PrintUsage();CommFd = open(DeviceName, O_RDWR, 0);if (CommFd < 0)Error("Unable to open device");if (fcntl(CommFd, F_SETFL, O_NONBLOCK) < 0)Error("Unable set to NONBLOCK mode");memset(&TtyAttr, 0, sizeof(struct termios));TtyAttr.c_iflag = IGNPAR;TtyAttr.c_cflag = DeviceSpeed | HUPCL | ByteBits | CREAD | CLOCAL;TtyAttr.c_cc[VMIN] = 1;if (tcsetattr(CommFd, TCSANOW, &TtyAttr) < 0)Warning("Unable to set comm port");TtyFd = open(TtyName, O_RDWR | O_NDELAY, 0);if (TtyFd < 0)Error("Unable to open tty");TtyAttr.c_cflag = TtySpeed | HUPCL | ByteBits | CREAD | CLOCAL;if (tcgetattr(TtyFd, &BackupTtyAttr) < 0)Error("Unable to get tty");if (tcsetattr(TtyFd, TCSANOW, &TtyAttr) < 0)Error("Unable to set tty");for (;;) {unsigned char Char = 0;fd_set ReadSetFD;void OutputStdChar(FILE *File) {char Buffer[10];int Len = sprintf(Buffer, OutputHex ? "%.2X " : "%c", Char);fwrite(Buffer, 1, Len, File);}FD_ZERO(&ReadSetFD);FD_SET(CommFd, &ReadSetFD);FD_SET( TtyFd, &ReadSetFD); # define max(x,y) ( ((x) >= (y)) ? (x) : (y) )if (select(max(CommFd, TtyFd) + 1, &ReadSetFD, NULL, NULL, NULL) < 0) {Error(strerror(errno));} # undef maxif (FD_ISSET(CommFd, &ReadSetFD)) {while (read(CommFd, &Char, 1) == 1) {WaitFdWriteable(TtyFd);if (write(TtyFd, &Char, 1) < 0) {Error(strerror(errno));}if (OutputToStdout) {if (UseColor)fwrite("\x1b[01;34m", 1, 8, stdout);OutputStdChar(stdout);if (UseColor)fwrite("\x1b[00m", 1, 8, stdout);fflush(stdout);}}}if (FD_ISSET(TtyFd, &ReadSetFD)) {while (read(TtyFd, &Char, 1) == 1) {static int EscKeyCount = 0;WaitFdWriteable(CommFd);if (write(CommFd, &Char, 1) < 0) {Error(strerror(errno));}if (OutputToStdout) {if (UseColor)fwrite("\x1b[01;31m", 1, 8, stderr);OutputStdChar(stderr);if (UseColor)fwrite("\x1b[00m", 1, 8, stderr);fflush(stderr);}if (Char == '\x1b') {EscKeyCount ++;if (EscKeyCount >= 3)goto ExitLabel;} elseEscKeyCount = 0;} }}ExitLabel:if (tcsetattr(TtyFd, TCSANOW, &BackupTtyAttr) < 0)Error("Unable to set tty");return 0; }
 
前面介紹了串口的簡單讀寫
今天研究了下串口的select讀,跟大家分享如下
 select讀主要實現的功能是,在一定時間內不停地看串口有沒有數據,有數據則進行讀,當時間過去后還沒有數據,則返回超時錯誤。
 具體的函數如下;
 
 
{
int retval;
unsigned char tempchar2;
fd_set rfds;
struct timeval tv;
int ret,pos;
tv.tv_sec = sec;//set the rcv wait time
tv.tv_usec = usec;//100000us = 0.1s
while(1){
?? FD_ZERO(&rfds);
?? FD_SET(fd,&rfds);
?? retval = select(fd+1,&rfds,NULL,NULL,&tv);
?? if(retval ==-1)
?? {
????perror("select()");
????break;
?? }
?? else if(retval)
?? {
????ret= read(fd,rcv_buf,1);
tempchar2 = rcv_buf;
printf("rcv_buf is %s\n",rcv_buf);
?????????
?? }
?? else
?? {
????break;
?? }
}
return 1;??
}
在前面的普通讀寫里面加上這個函數就可以了
它的調用方式為:
read_datas_tty(fd,buff,10,10);
這就表示等待時間為10S+10us
????Linux下直接用read讀串口可能會造成堵塞,或數據讀出錯誤。然而用select先查詢com口,再用read去讀就可以避免,并且當com口延時時,程序可以退出,這樣就不至于由于com口堵塞,程序就死了。我的代碼如下:
bool ReadDevice( int hComm, unsigned long uLen, char* pData )
{??
????int??????nread = 0;
?? char?? inbuf[uLen];
?? char??buff[uLen];
?? memset( inbuff,??'\0', uLen );
?? memset( buff, '\0', uLen );
?? fd_set readset;
?? struct timeval tv;
?? int MaxFd = 0;
?? int c = 0;
?? int z;
?? do
?? {
?????? FD_ZERO( &readset );
?????? if( hComm >= 0 )
?????? FD_SET( hComm, &readset );
?????? MaxFd = hComm + 1;
?????? tv.tv_sec = 0;
?????? tv.tv_usec = 500000;
??????do
??????{
?????????? z = select( MaxFd, &readset, 0, 0, &tv);
??????}while( z==-1 && errno==EINTR );?
??????if( z == -1 )
?????????? printf("select(2)\n");
??????if( z == 0 )
??????{
??????????hComm = -1;
??????}
??
??????if( hComm>=0 && FD_ISSET(hComm, &readset) )
??????{
?????????? z = read( hComm, buff, uLen - c );
?????????? c += z;
?????????? if( z == -1 )
?????????? {
?????????????? hComm = -1;
?????????? }
?????????? if( z > 0 )
??????????{
????????????????buff[ z + 1 ] = '\0';
????????????????strcat( inbuff, buff );
????????????????memset( buff, 0x00, uLen );
?????????? }
?????????? else
??????????{
?????????????? hComm = -1;
??????????}
??????}
?? }while( hComm >= 0 );
?? memcpy( pData, inbuff, c );
?? return true;
}
來源:http://www.moon-soft.com/doc/51500.htm
參考:http://hi.baidu.com/tc22/blog/item/6c82b51259bbc8c3c3fd7882.html
???????? http://blog.sina.com.cn/s/blog_6b0cfdeb0100n3k1.html
???????? http://blog.chinaunix.net/space.php?uid=20788636&do=blog&id=1841319
???????? http://www.ibm.com/developerworks/cn/linux/l-serials/
???????? http://hi.baidu.com/xdyang1986/blog/item/c863c125436bb621d4074290.html
總結
以上是生活随笔為你收集整理的linux 串口特别是接收的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: MMS发送的无线网络连接协议分析
- 下一篇: qt 手动设置控件的位置
