随笔 - 192,  文章 - 0,  评论 - 2,  阅读 - 25万
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

 


在linux下, 串口也被当做一个文件来使用, 所以串口传输数据实际上也就是对文件进行read/write操作.

UART串口基本知识:

一般, 串口至少有三根线:

地线GND, 接收线RX和发送线TX. 有的开发板还可能把控制线CTS/RTS也引出来.


串口查看方式:

在PC端, 如果用USB口连接, 一般显示为/dev/ttyUSBx, 其中x为0, 1, 2...

在开发板上,一般显示为/dev/ttySx, 其中x为0, 1, 2...


在电脑上可以使用下面的方法查看或者设置串口属性:

查看串口所有属性: sudo stty -F /dev/ttyUSB1 -a
设置串口波特率: sudo stty -F /dev/ttyUSB1 ispeed 1152000 ospeed 1152000

串口常用参数:

波特率: 每秒钟传送的bit数. --> 通信速度.
数据位: 每字节中实际所占的bit数, 取决于通信协议的选取. 比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。
停止位: 单个数据包的最后一位. 典型值为1, 1.5和2位..
奇偶校验位: 有四种检错方式, 偶、奇、高和低。可以没有校验位.
比特率: 数字信号的传输速率,单位时间内传输的二进制代码的有效位(bit)数,其单位为bit/s(bps)、Kbps或Mbps (此处K和M分别为1000和1000000)。

串口编程流程:

打开串口 --> 设置串口参数 --> 读写数据 --> 关闭串口
其中设置串口属性是比较重要的环节.
下面代码的功能: 给串口发送一个启动命令, 然后进入循环---从串口接收数据(数据头和数据分开传输), 并发送命令消息, 直到遇到终端信号或程序出错.
第一个是C语言实现,第二个是python实现。

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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
  
#define UART_NAME "/dev/ttyS0"
  
static int g_quit;
static int g_speed;
  
static void handle_signal(int sig)
{
    if (SIGINT == sig || SIGTERM == sig)
        g_quit = 1;
}
  
static struct sigaction sigact = {
    .sa_handler = handle_signal,
};
  
static struct option longopts[] = {
    {"help", no_argument, NULL, 'h'},
    {"baudrate", required_argument, NULL, 'r'},
    {0, 0, 0, 0},
};
  
  
static void print_usage(void)
{
    fprintf(stdout, "usage:\n");
    fprintf(stdout, "\t-r | --baudrate  the serial baud rate\n");
    fprintf(stdout, "\t-h | --help      show this help and exit\n");
}
  
  
static int parse_arg(int argc, char **argv)
{
    int ret = 0;
    char c = '0';
  
    while (
        (c = getopt_long(argc, argv, "-:r:h", longopts, NULL))
        != -1) {
        switch (c) {
        case 'r':
            g_speed = atoi(optarg);
            break;
        case 'h':
            ret = -1;
            break;
        case ':':
            fprintf(stdout, "%c require argument\n", optopt);
            ret = -1;
            break;
        case '?':
            fprintf(stdout, "%c invalid argument\n", optopt);
            ret = -1;
            break;
        default:
            break;
        }
    }
  
    return ret;
}
  
static int uart_open(char *filename)
{
    int fd;
  
    //fd = open(filename, O_RDWR);
    fd = open(filename, O_RDWR|O_NOCTTY|O_NDELAY);
    if (fd < 0) {
        printf("%s %d: failed to open output file\n",
                __FILE__, __LINE__);
        return -1;
    }
  
    //nonblock
    if (fcntl(fd, F_SETFL, 0) < 0) {
        printf("fcntl failed\n");
        close(fd);
        return -1;
    }
    return fd;
}
  
static int uart_set(int fd, int speed, int flow_ctrl,
        int databits, int parity, int stopbits)
{
    struct termios options;
    int ret = 0;
  
    if (tcgetattr(fd, &options) != 0) {
        printf("Setup serial fialed!\n");
        return -1;
    }
  
    int i;
    int speed_arr[] = {B1500000, B1152000, B1000000, B921600,
        B576000, B500000, B460800, B230400, B115200, B57600,
        B38400, B19200, B9600, B4800, B2400, B1800, B1200,
        B600, B300, B200, B150, B134, B110, B75, B50, B0};
    int name_arr[] = {1500000, 1152000, 1000000, 921600,
        576000, 500000, 460800, 230400, 115200, 57600,
        38400, 19200, 9600, 4800, 2400, 1800, 1200,
        600, 300, 200, 150, 134, 110, 75, 50, 0};
  
    if (tcgetattr(fd, &options) != 0) {
        printf("Setup serial fialed!\n");
        return -1;
    }
  
    printf("speed = %d\n", speed);
    for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {
        if (speed == name_arr[i]) {
            ret = cfsetispeed(&options, speed_arr[i]);
            if (ret) {
                perror("cfsetispeed");
                printf("set in speed failed\n");
            }
  
            ret = cfsetospeed(&options, speed_arr[i]);
            if (ret) {
                perror("cfsetispeed");
                printf("set out speed failed\n");
            }
            break;
        }
    }
  
    options.c_cflag |= CLOCAL;
    options.c_cflag |= CREAD;
  
    switch (flow_ctrl) {
    case 0: // no flow control
        options.c_cflag &= ~CRTSCTS;
        break;
    case 1: // hardware flow control
        options.c_cflag |= CRTSCTS;
        break;
    case 2: //software flow control
        options.c_cflag |= IXON|IXOFF|IXANY;
        break;
    default:
        printf("Unsupported flow control\n");
        return -1;
    }
  
    options.c_cflag &= ~CSIZE;
    switch (databits) {
    case 5:
        options.c_cflag |= CS5;
        break;
    case 6:
        options.c_cflag |= CS6;
        break;
    case 7:
        options.c_cflag |= CS7;
        break;
    case 8:
        options.c_cflag |= CS8;
        break;
    default:
        printf("Unsupported databits!\n");
        return -1;
    }
  
    switch (parity) {
    case 'n': //no parity
    case 'N':
        options.c_cflag &= ~PARENB;
        options.c_iflag &= ~INPCK;
        break;
    case 'o': //odd parity
    case 'O':
        options.c_cflag |= (PARODD | PARENB);
        options.c_iflag &= INPCK;
        break;
    case 'e': //even parity
    case 'E':
        options.c_cflag |= PARENB;
        options.c_cflag &= ~PARODD;
        options.c_iflag |= INPCK;
        break;
    case 's': //blank
    case 'S':
        options.c_cflag &= ~PARENB;
        options.c_iflag &= ~CSTOPB;
        break;
    default:
        printf("Unsupported parity\n");
        return -1;
    }
  
    switch (stopbits) {
    case 1:
        options.c_cflag &= ~CSTOPB;
        break;
    case 2:
        options.c_cflag |= CSTOPB;
        break;
    default:
        printf("Unsupported stop bits\n");
        return -1;
    }
  
    //mode
    options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/
    options.c_oflag  &= ~OPOST;   /*Output*/
  
    //wait_time: 0.1s; min char to read:1
    options.c_cc[VTIME] = 1;
    options.c_cc[VMIN] = 1;
  
    //if data overflow, receive data, but not read
    tcflush(fd, TCIFLUSH);
  
    //save configuration
    if (tcsetattr(fd, TCSANOW, &options) != 0) {
        printf("set serial error!\n");
        return -1;
    }
    return 0;
}
  
static int recv_data(int fd, int fdtest)
{
    int inflg = 0;
    int ret, size;
    int *data = NULL;
  
    do {
        if (g_quit)
            break;
  
        inflg = 0;
        ret = 0;
        size = 0;
        int hsize = read(fd, &size, 4);
  
        if (hsize < 0) {
            printf("read header size error\n");
            ret = -1;
            break;
        }
  
        if (size <= 0)
            continue;
  
        printf("size = %d\n", size);
        if (data) {
            free(data);
            data = NULL;
        }
        data = calloc(1, size);
        if (!data) {
            printf("calloc failed\n");
            ret = -1;
            break;
        }
  
        int len = 0;
        int left_size = size - len;
  
        do {
            len = read(fd, data, left_size);
            if (len < 0) {
                printf("read fd error\n");
                ret = -1;
                break;
            }
            //printf("real read size = %d\n", len);
            int n = write(fdtest, data, len);
  
            if (n < 0) {
                printf("write error!\n");
                ret = -1;
                break;
            }
            left_size = left_size - len;
        } while (left_size > 0);
  
        inflg = 1;
    } while (!inflg);
  
    if (data) {
        free(data);
        data = NULL;
    }
    return ret;
}
  
int main(int argc, char **argv)
{
    int ret = 0;
    int fd, fdtest;
    char send[1] = {'a'};
  
    ret = sigaction(SIGINT, &sigact, NULL);
    ret |= sigaction(SIGTERM, &sigact, NULL);
    if (ret) {
        printf("%s line%d: %s\n",
            __FILE__, __LINE__, strerror(errno));
        return -1;
    }
  
    g_speed = 9600;
  
    ret = parse_arg(argc, argv);
    if (ret) {
        print_usage();
        return -1;
    }
  
    fd = uart_open("/dev/ttyS0");
    if (fd < 0)
        return -1;
  
    int speed = g_speed;
    int flow_ctrl = 0;
    int databits = 8;
    int stopbits = 1;
    int parity = 'O';
  
    ret = uart_set(fd, speed, flow_ctrl, databits, parity, stopbits);
    if (ret) {
        printf("uart_set failed\n");
        goto out;
    }
  
    fdtest = open("/mnt/recv.h264", O_RDWR|O_SYNC);
    if (fdtest < 0) {
        printf("open fdtest failed\n");
        goto out;
    }
  
    int n = write(fd, send, 1);
  
    if (n <= 0) {
        printf("send a failed\n");
        close(fdtest);
        goto out;
    }
  
    do {
        if (g_quit)
            break;
  
        ret = recv_data(fd, fdtest);
  
        usleep(1000*10);
        send[0] = 'b';
  
        int res = write(fd, send, 1);
  
        if (res < 0)
            break;
        /* printf("%s: %s: %d\n", __FILE__, __func__, __LINE__); */
    } while (!ret);
    close(fdtest);
out:
    close(fd);
    return ret;
}

python

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
#!/usr/bin/python
import serial
import time
import struct
  
def w():
    baud = 115200
    fd = open("/home/sarah/2newh264/test15.h264", "w+")
    ser = serial.Serial('/dev/ttyUSB1', baud, timeout=8)
    print "baud: ", baud
    cmd0 = 'a'
    cmd1 = 'b'
    ser.write(cmd0)
    print "send \""+cmd0+"\" to remotes"
    while (1):
        print "send \""+cmd1+"\" to remotes"
        h = ser.read(4)
        if not h:
            continue
        size = struct.unpack("i", h)
        print "size: ", size[0]
        input = ser.read(size[0])
        fd.write(input)
        print "\n"
        ser.write(cmd1)
    ser.close()
    close(fd)
  
w()

参考文档:

linux串口通信编程_不积跬步无以至千里-CSDN博客_linux串口通信编程
串口通信程序比较完整的一个! http://blog.csdn.net/w282529350/article/details/7378388
LInux下串口设置详解 http://www.linuxidc.com/Linux/2011-04/33976.htm
cfsetispeed 中文man页面 http://os.51cto.com/art/201108/286606.htm

python serial 介绍 http://blog.csdn.net/u011577439/article/details/51762041

Linux串口编程_WuYujun's blog-CSDN博客_linux 串口编程

  

posted on   Malphite  阅读(2430)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
历史上的今天:
2020-07-29 linux shell命令编写技巧
点击右上角即可分享
微信分享提示