linux 串口 循环读取数据库,Linux串口编程一次读取全部输入的数据(输入数据不定长)...
发布日期:2022-02-18 13:19:56 浏览次数:11 分类:技术文章

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

编程背景:板子是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;

}

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

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

下面是运行效果图:

转载地址:https://blog.csdn.net/weixin_28926205/article/details/116690830 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:linux 分析内存占用,Linux 内存占用分析
下一篇:linux群晖系统密码忘记,【系统篇】猫盘群晖重置密码、重装、重置、升级与降级等...

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年09月20日 05时40分38秒