串口通信是ARM开发板最基础且应用广泛的通信方式之一,因其硬件接口简单、协议直观、成本低廉,在设备调试、传感器数据采集、嵌入式系统互联等场景中发挥着不可替代的作用,本文将从基本原理、硬件连接、软件配置、编程实现及常见问题解决等方面,详细解析ARM开发板的串口通信实践。

串口通信基础:异步串行与UART协议
串口通信(Serial Communication)是一种按位串行传输数据的通信方式,分为同步和异步两种,ARM开发板中最常用的是异步串行通信,无需时钟线同步,通过约定的参数(波特率、数据位、停止位等)确保收发双方数据一致,其核心硬件外设是UART(通用异步收发传输器),大多数ARM芯片(如STM32、树莓派、瑞芯微等)都内置多路UART接口,支持全双工通信(同时收发数据)。
异步串行数据帧格式固定,包含:
- 起始位:1位低电平,标志数据帧开始;
- 数据位:5~9位(通常8位,即1字节),实际传输的有效数据;
- 校验位:可选(无校验/奇校验/偶校验),用于简单错误检测;
- 停止位:1/1.5/2位高电平,标志数据帧结束,为下一帧做准备。
这种格式无需额外时钟线,仅靠收发双方预先约定参数即可实现可靠通信,特别适合嵌入式系统中低速、短距离的数据传输场景。
硬件连接:引脚、电平与接口转换
ARM开发板的串口通信需正确连接硬件,涉及引脚定义、电平匹配和接口转换三个关键环节。
串口引脚定义
每个UART接口有3个核心引脚:
- TX(Transmit):发送数据,开发板通过此引脚向外输出数据;
- RX(Receive):接收数据,开发板通过此引脚输入外部数据;
- GND:地线,确保收发双方参考电位一致,避免数据干扰。
连接时需遵循交叉原则:开发板的TX引脚连接设备的RX引脚,设备的TX引脚连接开发板的RX引脚,GND引脚直接共地,开发板与PC通信时,需通过USB转串口模块(如CH340、FT232)将PC的USB接口转为串口,模块的TX接开发板RX,模块RX接开发板TX。
电平匹配问题
ARM开发板的串口电平通常为TTL电平(0V表示逻辑0,3.3V或5V表示逻辑1),而工业设备或PC的串口可能采用RS232电平(-3V~-15V表示逻辑1,+3V~+15V表示逻辑0)或RS485电平(差分信号,抗干扰强),若电平不直接连接,会导致芯片损坏或通信失败,需通过电平转换芯片解决:

- TTL转RS232:使用MAX232芯片,将TTL电平转换为±12V的RS232电平;
- TTL转RS485:使用MAX3485芯片,支持半双工差分传输,传输距离可达1.2km(波特率≤9600bps)。
常见接口类型
| 接口类型 | 电平标准 | 传输距离 | 抗干扰能力 | 典型应用场景 |
|---|---|---|---|---|
| TTL | 0V/3.3V | ≤1m | 弱 | 开发板与模块近距离通信(如传感器、Wi-Fi模块) |
| RS232 | ±3V~±15V | ≤15m | 中 | PC与开发板调试、工业设备低速通信 |
| RS485 | 差分信号 | ≤1200m | 强 | 多节点工业控制、远程数据传输 |
软件配置:参数与驱动
硬件连接完成后,需在软件层面配置串口参数并启用驱动,确保操作系统或应用程序能正确访问串口。
串口核心参数配置
串口通信的“语言”是双方约定的参数,必须完全一致,否则会出现乱码或通信失败,关键参数包括:
- 波特率(Baud Rate):每秒传输的比特数,常见值有9600、19200、38400、115200等,低速传感器用9600,高速调试用115200,需根据设备能力选择;
- 数据位(Data Bits):通常8位(1字节),支持5~9位,需与发送端一致;
- 停止位(Stop Bits):通常1位,低速设备可选2位;
- 校验位(Parity):无校验(None)最常用,奇校验(Odd)和偶校验(Even)用于简单错误检测;
- 流控(Flow Control):硬件流控(RTS/CTS)或软件流控(XON/XOFF),用于防止数据溢出,短距离通信可关闭。
Linux系统下的串口操作
大多数ARM开发板运行Linux系统,串口设备文件位于/dev/目录下,如/dev/ttySAC0(板载UART)、/dev/ttyAMA0(树莓派默认UART),操作步骤如下:
权限管理:普通用户默认无串口访问权限,需将用户加入
dialout组:sudo usermod -aG dialout $USER # 登录后重启生效
工具调试:使用
minicom或screen工具测试串口,以minicom为例:sudo minicom -s # 进入配置菜单 选择“Serial port setup” -> 设置串口设备(如/dev/ttySAC0)、波特率(115200)、数据位(8)、停止位(1)、校验位(None) 保存配置并退出,按Ctrl+A+Q退出minicom
驱动加载:若串口设备文件不存在,需检查内核是否加载对应驱动,树莓派启用串口需在
/boot/config.txt中添加enable_uart=1,并禁用串口终端(sudo raspi-config-> Interface -> Serial Port -> No)。
编程实现:C语言串口通信示例
在ARM开发板上,可通过C语言直接操作串口设备文件,实现数据的收发,以下是基于Linux的串口通信代码框架,包含配置、发送、接收功能:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
// 配置串口参数
int serial_config(const char *dev, int baud) {
int fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0) {
perror("Open serial port failed");
return -1;
}
struct termios options;
tcgetattr(fd, &options); // 获取当前配置
// 设置波特率
cfsetispeed(&options, baud);
cfsetospeed(&options, baud);
// 设置数据位8位,停止位1位,无校验
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~PARENB;
// 忽略调制解调器控制,启用接收
options.c_cflag |= (CLOCAL | CREAD);
// 原始输入模式,关闭 canonical 模式和回显
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
// 设置超时:100ms内读取至少1个字节
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 10;
// 应用配置
tcsetattr(fd, TCSANOW, &options);
return fd;
}
// 串口发送数据
int serial_send(int fd, const char *data, int len) {
return write(fd, data, len);
}
// 串口接收数据
int serial_receive(int fd, char *buf, int max_len) {
return read(fd, buf, max_len);
}
int main() {
const char *dev = "/dev/ttySAC0";
int baud = B115200;
char send_buf[100] = "Hello, ARM Serial Communication!";
char recv_buf[100] = {0};
int fd = serial_config(dev, baud);
if (fd < 0) {
return -1;
}
// 发送数据
serial_send(fd, send_buf, strlen(send_buf));
printf("Sent: %sn", send_buf);
// 接收数据(假设有设备回复)
sleep(1); // 等待接收
int len = serial_receive(fd, recv_buf, sizeof(recv_buf));
if (len > 0) {
printf("Received: %.*sn", len, recv_buf);
}
close(fd);
return 0;
} 编译运行:
gcc serial_test.c -o serial_test && ./serial_test
常见问题与解决
通信乱码
原因:波特率不匹配、数据位/停止位/校验位设置错误、电平不匹配、接线交叉(TX接TX而非TX接RX)。
解决:用示波器或逻辑分析仪检测信号,确认双方参数一致;检查电平是否需转换;用万用表验证接线是否交叉共地。
无法接收数据
原因:串口未启用(如树莓派蓝牙占用串口)、权限不足、设备未打开(open()返回-1)。
解决:检查设备文件是否存在(ls /dev/ttyS*);确认用户是否在dialout组;通过minicom工具测试,若工具能接收则问题在应用程序代码。
FAQs
问:ARM开发板串口通信时,为什么有时能发送数据但接收不到?
答:可能原因包括:① 接线错误(开发板TX未接设备RX,或设备TX未接开发板RX);② 串口设备未启用(如树莓派默认串口被蓝牙占用,需通过/boot/config.txt禁用蓝牙);③ 接收端程序未正确打开串口或配置参数(如波特率不匹配),解决方法:① 用万用表或示波器检查接线是否交叉且共地;② 检查设备文件是否存在(ls /dev/ttyS*),确认开发板文档中的串口编号;③ 在接收端用minicom等工具测试,若能接收则问题在接收端程序,检查参数配置和读取逻辑。
问:如何在Linux下通过C语言实现串口数据的实时发送和接收?
答:步骤如下:① 包含头文件,打开串口设备(open,O_RDWR模式);② 配置termios结构体,设置波特率、数据位、停止位、校验位等,关闭 canonical 模式(ICANON)和回显(ECHO),设置非阻塞读取(O_NONBLOCK);③ 创建循环,用read()读取串口数据到缓冲区,若数据有效则处理(如打印);用write()发送数据(如从键盘输入发送);④ 关闭串口(close),关键代码:struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, B115200); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag |= CS8; options.c_cflag |= (CLOCAL | CREAD); tcsetattr(fd, TCSANOW, &options); char buf[1024]; while(1) { int n = read(fd, buf, sizeof(buf)); if(n > 0) { printf(“Received: %.*sn”, n, buf); } char send_buf[256]; fgets(send_buf, sizeof(send_buf), stdin); write(fd, send_buf, strlen(send_buf)); }
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复