博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux串口编程一次读取全部输入的数据(输入数据不定长)
阅读量:2442 次
发布时间:2019-05-10

本文共 3024 字,大约阅读时间需要 10 分钟。

    编程背景:板子是linux 2.6.39系统,人机交互接口是板子上的一个串口。输入命令时,当长度大于8时,发现read读取到的数据是分多次得到的(串口用非阻塞模式读取数据),比如输入的字符长度为25(循环读取,下面贴代码):第一次读取8个,并发生串口中断(发生中断后中间会有一小会读不到数据,实测),然后又读取8个、8个、1个(‘\0’不占位),查了下原因,好多网友也遇到了这个问题,看了几个帖子都没直接说出解决办法。原来这个和串口设备的缓冲有关,常见的缓冲大小是8bytes,既然能收到数据,那就自己撸代码来一次一次的接收,然后放到缓存里面去,直到接收满足预定的为止

编程目的:串口接收输入任意长度的字符串(有上限),放入缓存字符数组中

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "GPRS.h"#define DATA_LEN 0xFF#define BUFSIZE 512 char read_buf[256] = {'\0'};char read_nBytes[10] = {0}; int openSerial_GPRS(char *cSerialName, unsigned int Baud){ int iFd; struct termios opt; iFd = open(cSerialName, O_RDWR|O_NOCTTY|O_NONBLOCK|O_NDELAY);//|O_NONBLOCK 特别注意这里的串口打开属性设置 if(iFd < 0) { perror(cSerialName); return -1; } tcgetattr(iFd, &opt); switch(Baud) { case 115200: cfsetispeed(&opt, B115200);cfsetospeed(&opt, B115200);break; case 57600: cfsetispeed(&opt, B57600);cfsetospeed(&opt, B57600);break; case 38400: cfsetispeed(&opt, B38400);cfsetospeed(&opt, B38400);break; case 19200: cfsetispeed(&opt, B19200);cfsetospeed(&opt, B19200);break; case 9600: cfsetispeed(&opt, B9600) ;cfsetospeed(&opt, B9600);break; case 4800: cfsetispeed(&opt, B4800) ;cfsetospeed(&opt, B4800);break; case 2400: cfsetispeed(&opt, B2400) ;cfsetospeed(&opt, B2400);break; default: break; } /* * raw mode */ opt.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); opt.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); opt.c_oflag &= ~(OPOST); opt.c_cflag &= ~(CSIZE | PARENB); opt.c_cflag |= CS8; /* * 'DATA_LEN' bytes can be read by serial */ opt.c_cc[VMIN] = DATA_LEN; opt.c_cc[VTIME] = 150; if (tcsetattr(iFd, TCSANOW, &opt)<0) { return -1; } return iFd;}void gprs_send_test(int fd){ char tmp[1024]; int len; int i; for(i = 0; i < 16; i++) tmp[i] = i%0xFF; len = write(fd, tmp, 16); printf("len = %d\n", len); }//粘连的字符串最后保存在*p指向的地址所在的内存中static int mystrcat(char *p,char *q){ int ret = -1; char *pp = p; ret = (p != NULL) && (q != NULL); if(ret) { while(*pp != '\0') { pp++; } while(*q != '\0') { *(pp++) = *(q++); } *(pp) = '\0'; } return ret;}void gprs_recieve_test1(int fd){ int i = 0; static int len = 0; int readnum = 0; //bzero(read_buf,sizeof(read_buf)); bzero(read_nBytes,sizeof(read_nBytes)); while((readnum = read(fd,read_nBytes,8))>0) { len += readnum; if(readnum == 8) { read_nBytes[readnum] = '\0'; mystrcat(read_buf,read_nBytes); } if(readnum > 0 && readnum < 8) { read_nBytes[readnum] = '\0'; mystrcat(read_buf,read_nBytes); printf("read_buf:%d\n", len); printf("read_buf:%s\n", read_buf); len = 0; //bzero(read_buf,sizeof(read_buf)); bzero(read_buf,sizeof(read_buf)); } }}
(测试代码我是放在一个线程的while循环里面测试的)

void *thread_func(void *arg)

{

       /* 这里定义了一个指向argument类型结构体的指针arg_thread1 */

       //struct argument *arg_thread1;
       //arg_thread1=(struct argument *)arg;
   
       while(1)
       {
             gprs_recieve_test1(fd);
             usleep(200);
       }
   
       return (void *)123;  
}

此处发送的回车换行符也存储在字符数组中,所以发送的字符比接收到字符少两个

串口设置部分这里就不啰嗦了 网上很全

下面是运行效果图:

 

你可能感兴趣的文章
graph api_与Facebook Graph API集成
查看>>
mysql删除事件的使用_使用MySQL事件
查看>>
PHP会话
查看>>
mongodb简介_MongoDB简介
查看>>
本地应用程序_本地化PHP应用程序的“正确方法”,第4部分
查看>>
创业基础网络课答案_创业挑战网络基础设施巨头
查看>>
php使用正则表达式_使用PHP正则表达式
查看>>
用PHP上传文件
查看>>
mfc单文档绘制世界坐标系_文档使世界运转
查看>>
防止跨站请求伪造(CSRF)
查看>>
科创板 云计算业务公司_云计算对您的业务意味着什么
查看>>
SitePoint播客#80:与澳大利亚团队的FullCodePress
查看>>
可以给视图加复合主键_灵活视图处理的模式,第1部分–使用复合材料
查看>>
SitePoint播客#83:与Adam Broadway重新思考您的工作
查看>>
SitePoint播客#117:与Paul Boag返回Boagworld
查看>>
支付宝沙箱设置_从零到云:设置EC2沙箱,第1部分
查看>>
bcrypt强哈希_为什么应该使用Bcrypt哈希存储的密码
查看>>
数据库存储集合_处理集合根的集合-存储库模式
查看>>
SitePoint播客#76:邪恶的WordPress主题
查看>>
BigCommerce和Volusion:比较设置和移动
查看>>