Ubuntu读取开发板串口数据

我的stm32l431开发板使用的是CH340 USB转串口芯片,Linux默认有这个驱动程序,将设备插到电脑上后在/dev目录下会多一个ttyUSB0设备,用dmesg查看驱动内核log:

1
2
3
4
5
6
$ dmesg
...
[91912.510126] usbcore: registered new interface driver ch341
[91912.510142] usbserial: USB Serial support registered for ch341-uart
[91912.510157] ch341 3-3.1:1.0: ch341-uart converter detected
[91912.524719] usb 3-3.1: ch341-uart converter now attached to ttyUSB0

下面就编写读取串口数据的程序:

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
#include <stdio.h>      /*标准输入输出定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix标准函数定义*/
#include <sys/types.h> /**/
#include <sys/stat.h> /**/
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX终端控制定义*/
#include <errno.h> /*错误号定义*/
#include <string.h>

#define TRUE 1
#define FALSE 0

/***@brief 设置串口通信速率
*@param fd 类型 int 打开串口的文件句柄
*@param speed 类型 int 串口速度
*@return void*/

void set_speed(int fd, int speed) {
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed);
cfsetospeed(&Opt, speed);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
perror("tcsetattr fd1");
return;
}
/**
*@brief 设置串口数据位,停止位和效验位
*@param fd 类型 int 打开的串口文件句柄*
*@param databits 类型 int 数据位 取值 为 7 或者8*
*@param stopbits 类型 int 停止位 取值为 1 或者2*
*@param parity 类型 int 效验类型 取值为N,E,O,,S
*/
int set_Parity(int fd, int databits, int stopbits, int parity) {
struct termios options;
if (tcgetattr(fd, &options) != 0) {
perror("SetupSerial 1");
return (FALSE);
}
options.c_cflag &= ~CSIZE;
switch (databits) /*设置数据位数*/
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr, "Unsupported data size\n");
return (FALSE);
}
switch (parity) {
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr, "Unsupported parity\n");
return (FALSE);
}
/* 设置停止位*/
switch (stopbits) {
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr, "Unsupported stop bits\n");
return (FALSE);
}
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK;
options.c_cc[VTIME] = 150; // 15 seconds
options.c_cc[VMIN] = 0;

tcflush(fd, TCIFLUSH); /* Update the options and do it NOW */
if (tcsetattr(fd, TCSANOW, &options) != 0) {
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
/**
*@brief 打开串口
*/
int OpenDev(char *Dev) {
int fd = open(Dev, O_RDWR); //| O_NOCTTY | O_NDELAY
if (-1 == fd) { /*设置数据位数*/
perror("Can't Open Serial Port");
return -1;
} else
return fd;
}
/**
*@brief main()
*/
int main(int argc, char **argv) {
int fd;
int nread;
char prev[512], buf[512];
char *dev = "/dev/ttyUSB0";
FILE *fp;

fd = OpenDev(dev);
if (fd > 0)
set_speed(fd, B115200);
else {
printf("Can't Open Serial Port!\n");
exit(0);
}
if (set_Parity(fd, 8, 1, 'N') == FALSE) {
printf("Set Parity Error\n");
exit(1);
}
while ((nread = read(fd, buf, 512)) > 0) {
buf[nread + 1] = '\0';
printf("buf: %s\n", buf);
}
close(fd);
return 0;
}

主要就是打开设备,设置一些通信速率等参数,然后像普通程序一样编译即可。这时还不能读设备的数据,需要先修改设备权限:

1
2
$ cd /dev
$ sudo chmod 666 ttyUSB0

然后再运行程序即可:

1
2
3
4
5
6
7
8
9
10
$ ./read_ch340                
buf: Welcome to IoT-Club, This is EVB-M1 Board.

buf:
e
buf: LOS_TaskCreate: 0
b
buf: input:
k
buf: recv: W