ARM Linux 串口编程指南

在嵌入式系统中,串口(Serial Port)是一种常用的通信接口,用于设备之间的数据传输,本文将详细介绍在 ARM Linux 环境下如何进行串口编程,包括配置串口、编写串口通信程序以及常见问题的解决方法。
1. 串口基础
1 串口
串口类型:常见的串口包括 UART(通用异步收发传输器)、RS232、RS485 等。
工作模式:全双工或半双工,异步通信。
波特率:通信速率,如 9600、115200 等。
数据位:通常为 8 位。
停止位:通常为 1 位或 2 位。
校验位:无校验、奇校验、偶校验等。
2 串口在 Linux 中的表示
在 Linux 系统中,串口设备通常以/dev/ttyS 或/dev/serial 的形式存在。
| 设备名称 | 描述 |
| /dev/ttyS0 | 第一个串口设备 |
| /dev/ttyS1 | 第二个串口设备 |
| /dev/serial0 | 某些系统中的串口设备 |
2. 串口配置
在进行串口通信前,需要正确配置串口参数,包括波特率、数据位、停止位和校验位等,可以使用stty 命令或编程方式进行配置。
1 使用 `stty` 配置串口
设置波特率为115200,8数据位,无校验,1停止位 stty -F /dev/ttyS0 115200 cs8 -cstopb -parenb -icanon -echo
参数说明:
-F /dev/ttyS0:指定串口设备。
115200:设置波特率为 115200。
cs8:设置数据位为 8 位。
-cstopb:设置停止位为 1 位。
-parenb:禁用奇偶校验。

-icanon:设置为非规范模式(原始模式)。
-echo:关闭回显。
2 编程方式配置串口
在 C/C++ 程序中,可以使用termios 结构体来配置串口参数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
int set_serial_params(int fd, int speed, int parity) {
struct termios tty;
memset(&tty, 0, sizeof(tty));
if (tcgetattr(fd, &tty) != 0) {
perror("tcgetattr");
return -1;
}
// 设置输入和输出波特率
cfsetispeed(&tty, speed);
cfsetospeed(&tty, speed);
// 设置数据位
tty.c_cflag |= CS8; // 8数据位
// 设置停止位
tty.c_cflag &= ~CSTOPB; // 1停止位
// 设置校验位
switch (parity) {
case 0:
tty.c_cflag &= ~PARENB; // 无校验
break;
case 1:
tty.c_cflag |= PARENB;
tty.c_cflag &= ~PARODD; // 偶校验
break;
case 2:
tty.c_cflag |= PARENB;
tty.c_cflag |= PARODD; // 奇校验
break;
default:
return -1;
}
// 设置为非规范模式
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tty.c_oflag &= ~OPOST;
// 设置控制模式
tty.c_cc[VMIN] = 1; // 最小读取字符数
tty.c_cc[VTIME] = 0; // 超时时间
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
perror("tcsetattr");
return -1;
}
return 0;
} 3. 编写串口通信程序
下面以一个简单的串口通信示例为例,展示如何在 ARM Linux 上实现数据的发送和接收。
1 示例代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
// 串口配置函数(见上文)
int set_serial_params(int fd, int speed, int parity);
int main() {
const char *device = "/dev/ttyS0";
int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("open");
return -1;
}
// 设置串口参数:115200波特率,无校验
if (set_serial_params(fd, B115200, 0) != 0) {
close(fd);
return -1;
}
// 发送数据
const char *msg = "Hello, Serial Port!
";
int len = strlen(msg);
int written = write(fd, msg, len);
if (written != len) {
perror("write");
} else {
printf("Sent: %s", msg);
}
// 接收数据
char buffer[100];
memset(buffer, 0, sizeof(buffer));
int read_len = read(fd, buffer, sizeof(buffer) 1);
if (read_len > 0) {
printf("Received: %s
", buffer);
} else if (read_len == 0) {
printf("No data received.
");
} else {
perror("read");
}
close(fd);
return 0;
} 2 编译与运行
假设上述代码保存为serial_test.c,使用以下命令进行编译和运行:
gcc serial_test.c -o serial_test sudo ./serial_test
注意:可能需要超级用户权限才能访问串口设备。
4. 常见问题与解决方法
1 无法打开串口设备
问题:运行程序时提示“Permission denied”或“No such file or directory”。
解决方法:
确保串口设备名称正确,如/dev/ttyS0。
检查当前用户是否有权限访问串口设备,可以通过以下命令将当前用户添加到dialout 组:
sudo usermod -a -G dialout $USER
然后重新登录使组更改生效。
2 数据发送失败或接收不到数据
问题:发送数据后没有响应,或者接收不到预期的数据。
解决方法:
检查串口配置是否正确,包括波特率、数据位、停止位和校验位是否与对方设备一致。
确认硬件连接是否正确,确保串口线连接稳固,且两端设备配置匹配。

使用串口调试工具(如minicom 或screen)测试串口通信是否正常。
使用 screen 测试串口 sudo screen /dev/ttyS0 115200
5. 相关问题与解答
问题1:如何在 ARM Linux 上查看可用的串口设备?
解答:
可以使用以下命令列出系统中的串口设备:
ls -l /dev/ttyS
或者查看所有串口相关的设备:
dmesg | grep tty
使用lsusb 或dmesg 可以查看 USB 转串口设备是否被识别。
问题2:在串口通信中,如何实现数据的实时接收与处理?
解答:
为了实现实时接收与处理数据,可以使用多线程或异步 I/O,以下是一个使用多线程的简单示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
// 串口配置函数(见上文)
int set_serial_params(int fd, int speed, int parity);
void* receive_thread(void* arg) {
int fd = *(int*)arg;
char buffer[100];
while (1) {
memset(buffer, 0, sizeof(buffer));
int read_len = read(fd, buffer, sizeof(buffer) 1);
if (read_len > 0) {
printf("Received: %s
", buffer);
} else if (read_len == 0) {
// No data, continue looping
} else {
perror("read");
break;
}
}
return NULL;
}
int main() {
const char *device = "/dev/ttyS0";
int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("open");
return -1;
}
// 设置串口参数:115200波特率,无校验
if (set_serial_params(fd, B115200, 0) != 0) {
close(fd);
return -1;
}
pthread_t rx_thread;
if (pthread_create(&rx_thread, NULL, receive_thread, &fd) != 0) {
perror("pthread_create");
close(fd);
return -1;
}
// 主线程负责发送数据
while (1) {
const char *msg = "Periodic Message
";
write(fd, msg, strlen(msg));
sleep(1); // 每秒发送一次
}
close(fd);
return 0;
} 说明:
创建一个接收线程,持续监听串口数据并处理。
主线程可以负责发送数据或其他任务,实现并发处理。
各位小伙伴们,我刚刚为大家分享了有关“armlinux串口编程”的知识,希望对你们有所帮助。如果您还有其他相关问题需要解决,欢迎随时提出哦!
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复