linux 串口特别是接收
来源:互联网 发布:淘宝热销产品 编辑:程序博客网 时间:2024/06/05 02:58
串口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); } else printf("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); } else printf("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); } else printf("open ttyS2 .....\n"); } if(fcntl(fd, F_SETFL, 0)<0) printf("fcntl failed!\n"); else printf("fcntl=%d\n",fcntl(fd, F_SETFL,0)); if(isatty(STDIN_FILENO)==0) printf("standard input is not a terminal device\n"); else printf("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); } else printf("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##Speed TestSpeed(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); } else TtySpeed = 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; } else EscKeyCount = 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;
}
{
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;
}
{
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 串口特别是接收
- linux 串口接收
- Linux 串口接收数据
- Linux串口驱动程序(5)-串口接收分析
- arm-linux串口接收出错
- Linux串口编程之接收
- linux下串口接收范例
- Linux系统串口接收数据编程
- Linux系统串口接收数据编程
- 串口发送接收+mini2440 linux
- linux串口接收不到0x11解决
- Linux系统串口接收数据编程
- Linux系统串口接收数据编程
- linux 串口接收不到0x11
- Linux系统串口接收数据编程
- linux加快串口速度的方法。linux读写不卡机的方法,linux串口接收注意事项,串口窍门,串口加速方法,
- linux多线程下打开串口发送和接收数据
- Linux串口select发送接收位不对齐问题
- C#中自定义属性的例子
- 四极管:U-Boot主要目录结构
- 菜鸟DBA的初认识
- 使用PHP将超链接的相对地址转换为绝对地址
- Flex中显示web页面
- linux 串口特别是接收
- 如何用脚本更改Iframe的src并刷新
- android 学习收藏
- 本世纪最热门的五大行业之一Data Mining:发现数据应用之美
- Spring学习之使用关闭钩子销毁bean
- Highcharts选项配置详细说明文档
- SD:MWST and MWSI的区别
- 如何判断单链表里面是否有环?
- matchbox编译