编程背景:板子是linux 2.6.39系统,人机交互接口是板子上的一个串口。输入命令时,当长度大于8时,发现read读取到的数据是分多次得到的(串口用非阻塞模式读取数据),比如输入的字符长度为25(循环读取,下面贴代码):第一次读取8个,并发生串口中断(发生中断后中间会有一小会读不到数据,实测),然后又读取8个、8个、1个(‘’不占位),查了下原因,好多网友也遇到了这个问题,看了几个帖子都没直接说出解决办法。原来这个和串口设备的缓冲有关,常见的缓冲大小是8bytes,既然能收到数据,那就自己撸代码来一次一次的接收,然后放到缓存里面去,直到接收满足预定的为止
编程目的:串口接收输入任意长度的字符串(有上限),放入缓存字符数组中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159#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;
}
此处发送的回车换行符也存储在字符数组中,所以发送的字符比接收到字符少两个
串口设置部分这里就不啰嗦了 网上很全
下面是运行效果图:
1
最后
以上就是强健飞机最近收集整理的关于Linux串口编程一次读取全部输入的数据(输入数据不定长)的全部内容,更多相关Linux串口编程一次读取全部输入内容请搜索靠谱客的其他文章。
发表评论 取消回复