本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!