我是靠谱客的博主 强健飞机,最近开发中收集的这篇文章主要介绍Linux串口编程一次读取全部输入的数据(输入数据不定长),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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

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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <asm/ioctls.h>
#include <time.h>
#include <pthread.h>
#include "GPRS.h"
#define DATA_LEN
0xFF
#define BUFSIZE
512
char read_buf[256] = {''};
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 = %dn", len);
}
//粘连的字符串最后保存在*p指向的地址所在的内存中
static int mystrcat(char *p,char *q)
{
int ret = -1;
char *pp = p;
ret = (p != NULL) && (q != NULL);
if(ret)
{
while(*pp != '')
{
pp++;
}
while(*q != '')
{
*(pp++) = *(q++);
}
*(pp) = '';
}
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] = '';
mystrcat(read_buf,read_nBytes);
}
if(readnum > 0 && readnum < 8)
{
read_nBytes[readnum] = '';
mystrcat(read_buf,read_nBytes);
printf("read_buf:%dn", len);
printf("read_buf:%sn", 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;  
}


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

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


下面是运行效果图:




最后

以上就是强健飞机为你收集整理的Linux串口编程一次读取全部输入的数据(输入数据不定长)的全部内容,希望文章能够帮你解决Linux串口编程一次读取全部输入的数据(输入数据不定长)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(75)

评论列表共有 0 条评论

立即
投稿
返回
顶部