日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 串口特别是接收

發布時間:2024/9/5 linux 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 串口特别是接收 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

串口open之后就是設置了。設置后就可以進行read,write等類似操作了。
今天寫串口程序,寫很好寫,但是不能讀,最找到了讀的方法

#include <stdio.h> #include <string.h> #include <sys/types.h> #include <errno.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <termios.h> #include <stdlib.h> int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop) { /* 五個參量 fd打開文件 speed設置波特率 bit數據位設置 neent奇偶校驗位 stop停止位 */struct termios newtio,oldtio;if ( tcgetattr( fd,&oldtio) != 0) {perror("SetupSerial 1");return -1;}bzero( &newtio, sizeof( newtio ) );newtio.c_cflag |= CLOCAL | CREAD;newtio.c_cflag &= ~CSIZE;switch( nBits ){case 7:newtio.c_cflag |= CS7;break;case 8:newtio.c_cflag |= CS8;break;}switch( nEvent ){case 'O':newtio.c_cflag |= PARENB;newtio.c_cflag |= PARODD;newtio.c_iflag |= (INPCK | ISTRIP);break;case 'E':newtio.c_iflag |= (INPCK | ISTRIP);newtio.c_cflag |= PARENB;newtio.c_cflag &= ~PARODD;break;case 'N':newtio.c_cflag &= ~PARENB;break;} switch( nSpeed ){case 2400:cfsetispeed(&newtio, B2400);cfsetospeed(&newtio, B2400);break;case 4800:cfsetispeed(&newtio, B4800);cfsetospeed(&newtio, B4800);break;case 9600:cfsetispeed(&newtio, B9600);cfsetospeed(&newtio, B9600);break;case 115200:cfsetispeed(&newtio, B115200);cfsetospeed(&newtio, B115200);break;default:cfsetispeed(&newtio, B9600);cfsetospeed(&newtio, B9600);break;}if( nStop == 1 )newtio.c_cflag &= ~CSTOPB;else if ( nStop == 2 )newtio.c_cflag |= CSTOPB;newtio.c_cc[VTIME] = 0;newtio.c_cc[VMIN] = 0;tcflush(fd,TCIFLUSH);if((tcsetattr(fd,TCSANOW,&newtio))!=0){perror("com set error");return -1;}printf("set done!\n");return 0; } int open_port(int fd,int comport) { /* fd 打開串口 comport表示第幾個串口 */char *dev[]={"/dev/ttyUSB0","/dev/ttyS1","/dev/ttyS2"};long vdisable;if (comport==1){ fd = open( "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NDELAY);if (-1 == fd){perror("Can't Open Serial Port");return(-1);}elseprintf("open ttyS0 .....\n");}else if(comport==2){ fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);if (-1 == fd){perror("Can't Open Serial Port");return(-1);}elseprintf("open ttyS1 .....\n");}else if (comport==3){fd = open( "/dev/ttyS2", O_RDWR|O_NOCTTY|O_NDELAY);if (-1 == fd){perror("Can't Open Serial Port");return(-1);}elseprintf("open ttyS2 .....\n");}if(fcntl(fd, F_SETFL, 0)<0)printf("fcntl failed!\n");elseprintf("fcntl=%d\n",fcntl(fd, F_SETFL,0));if(isatty(STDIN_FILENO)==0)printf("standard input is not a terminal device\n");elseprintf("isatty success!\n");printf("fd-open=%d\n",fd);return fd; } int main(void) {int fd;int nread,i;char buff[]="Hello\n";fd = open( "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NDELAY);if (-1 == fd){perror("Can't Open Serial Port");return(-1);}elseprintf("open ttyUSB0 .....\n");if((i=set_opt(fd,9600,8,'N',1))<0){perror("set_opt error");return -1;}printf("fd=%d\n",fd); // fd=3;char bbb[]="abde";char buf[10];// tcflush(fd, TCIOFLUSH); //清空緩沖區while(1){sleep(1);memset(buf, 0, 10);nread=read(fd,buf,8);printf("nread=%d,%s\n",nread,buf);}close(fd);return 0;}


下面是個很有名的程序:

先說下使用方法吧:

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 read_datas_tty(int fd,char *rcv_buf,int sec,int usec)
{
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 串口特别是接收的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。