ARM(9) - UART
一、基本概念
1. 通信
嵌入式系统中的通信,指两个或两个以上主机(或设备)之间的数据交互,是设备间传递指令、数据的核心方式。
2. 异步通信与同步通信
类型 | 核心区别 | 关键特征 | 应用场景 |
---|---|---|---|
异步通信 | 无统一时钟,靠起始 / 停止位同步 | 1. 每个数据帧含起始位(1 位)、数据位、校验位(可选)、停止位(1-2 位) 2. 收发双方需预先约定波特率、数据位等参数 | UART(串口)、RS232/485 |
同步通信 | 有统一时钟(单独时钟线) | 1. 数据连续传输,无起始 / 停止位,效率高 2. 时钟同步错误会导致数据错位 | SPI、I2C、CAN |
3. 串行通信与并行通信
类型 | 数据传输方式 | 优缺点对比 | 应用场景 |
---|---|---|---|
串行通信 | 仅 1 根数据线(加地线)传输 | ✅ 优点:布线少、抗干扰强、传输距离远(如 100m+) ❌ 缺点:速度慢(逐位传输) | UART、RS485、SPI、I2C |
并行通信 | 多根数据线(如 8/16 根)同时传输 | ✅ 优点:速度快(并行传多位) ❌ 缺点:布线多、干扰大、传输距离近(如 1m 内) | 板内芯片互联(如 CPU 与 RAM) |
4. 单工、半双工、全双工
类型 | 数据流向 | 关键特征 | 应用场景 |
---|---|---|---|
单工 | 仅单向传输(固定发送→接收) | 只能 A 发 B 收,无法反向传输 | 红外遥控、广播 |
半双工 | 双向传输,但同一时间仅单向 | 需切换收发状态(如 RS485 的 DE/RE 引脚),避免冲突 | RS485 总线(多设备组网) |
全双工 | 双向同时传输 | 有独立的发送线(TX)和接收线(RX),可同时收发 | UART(串口)、USB、以太网 |
5. TTL、RS232、RS485
均为串行通信的电平标准,核心区别在于电平范围和传输能力:
- TTL 电平:嵌入式芯片内部常用,
高电平=3.3V/5V
,低电平=0V
;传输距离短(<10m),仅支持板内 / 近距离设备(如 CH340 输出的 TTL 信号)。 - RS232 电平:
逻辑1=-3~-15V
,逻辑0=+3~+15V
;传输距离约 15m,需 TTL-RS232 转换芯片(如 MAX232),常用于 PC 与设备短距离通信。 - RS485 电平:采用差分传输(见下文),
逻辑1=A-B>200mV
,逻辑0=B-A>200mV
;传输距离可达 1200m,支持 32 个设备组网,抗干扰强,常用于工业现场。
6. 差分传输
一种抗干扰的信号传输方式,核心原理:
- 用两根双绞线(A 线、B 线)传输相反信号(A 为正,B 为负);
- 外界干扰会同时影响两根线,干扰信号相互抵消,最终接收端通过计算 A-B 的差值恢复原始信号;
- 典型应用:RS485、CAN 总线,是工业环境抗干扰的关键技术。
二、原理图分析(基于《IMX6ULL_MINI_V2.2 (Mini 底板原理图).pdf》)
模块:USB USART & USB POWER
⚠️ 重要注意事项:不建议使用 USB 接口作为电源供电,会导致板子发热严重,影响稳定性。
1. USB 接口(USB_TTL)
- 功能:作为 USB-TTL 转换的物理接口,连接 PC 的 USB 口与底板;
- 作用:实现 PC 与 IMX6ULL 芯片的 UART 通信(PC 端通过串口工具发送指令,底板接收并执行)。
2. CH340(U8 芯片)
- 核心功能:USB 转 TTL 串口芯片;
- 工作原理:将 PC 端 USB 协议的数据流,转换为 IMX6ULL 可识别的 TTL 电平串口数据(反之亦然);
- 关键引脚:USB_D+、USB_D-(接 USB 接口),TXD、RXD(接 IMX6ULL 的 UART1 引脚)。
3. DCDC 电源稳压模块(U12、U13)
- 功能:对输入电源进行稳压、滤波;
- 核心作用:防抖、抗干扰,确保 CH340 和 UART 模块供电稳定,避免电源波动导致通信错误。
三、代码编写(基于《IMX6ULL 参考手册.pdf》)
1. 初始化配置
(1)时钟初始化
- 基准时钟:
80MHz
(IMX6ULL 默认高频时钟); - 预分频配置:1 分频(即 UART 模块的参考时钟 = 80MHz,无分频)。
(2)引脚初始化
- 功能:将 IMX6ULL 的特定引脚配置为 UART1 的收发引脚;
- 核心代码:
// 配置UART1_TX引脚(复用为UART1发送功能) IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX, 0); // 配置引脚电气属性(上拉、驱动能力等,0x10B0为标准配置) IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX, 0x10B0);// 配置UART1_RX引脚(复用为UART1接收功能) IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX, 0); IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX, 0x10B0);
(3)寄存器配置(UART 核心寄存器)
寄存器名称 | 地址别名 | 核心功能 | 关键位说明 |
---|---|---|---|
UART Receiver Register | UARTx_URXD | 接收数据寄存器(只读) | [RX_DATA] (b0~b7):存储接收到的 8 位数据(7 位模式下最高位为 0) |
UART Transmitter Register | UARTx_UTXD | 发送数据寄存器(只写) | [TX_DATA] (b0~b7):写入需发送的数据,写入后硬件自动启动发送 |
UART Control Register 1 | UARTx_UCR1 | UART 总控制寄存器 | [UARTEN] (b0):UART 模块总开关(1 = 开启,0 = 关闭) |
UART Control Register 2 | UARTx_UCR2 | 收发控制与格式配置 | [RXEN] (b1):接收器使能(1 = 开启) [TXEN] (b2):发送器使能(1 = 开启) [WS] (b5):数据位(0=7 位,1=8 位) [STPB] (b6):停止位(0=1 位,1=2 位) [PREN] (b8):校验使能(0 = 关闭) [IRTS] (b14):忽略 RTS 流控(1 = 忽略) |
UART Control Register 3 | UARTx_UCR3 | 多路复用模式配置 | [RXDMUXSEL] (b2):必须设为 1(IMX6ULL UART 默认工作于多路复用模式) |
UART FIFO Control Register | UARTx_UFCR | FIFO 与时钟分频控制 | [RFDIV] (b7~b9):参考时钟分频(设为 000=1 分频,即参考时钟 = 80MHz) |
UART Status Register 2 | UARTx_USR2 | 收发状态寄存器 | [TXDC] (b3):发送完成标志(1 = 发送缓冲区空,可写新数据) [RDR] (b0):接收就绪标志(1 = 接收缓冲区有数据,可读取) |
UART BRM Incremental Reg | UARTx_UBIR | 波特率增量寄存器 | [INC] (b0~b15):波特率计算参数(需与 UBMR 配合) |
UART BRM Modulator Reg | UARTx_UBMR | 波特率调制寄存器 | [MOD] (b0~b15):波特率计算参数 |
(4)波特率计算
- 公式:
BaudRate = Ref Freq / (16 × ((UBMR + 1) / (UBIR + 1)))
- 已知条件:
- Ref Freq(参考时钟):80MHz(基准时钟 80MHz,RFDIV=1 分频);
- 目标波特率:常用 115200bps;
- 计算示例(115200bps):
代入公式得:115200 = 80000000 / (16 × ((UBMR+1)/(UBIR+1)))
化简得:(UBMR+1)/(UBIR+1) = 80000000 / (16×115200) ≈ 43.4028
取整配置:UBMR=42
,UBIR=0
(此时 (42+1)/(0+1)=43,波特率约 115741bps,误差可接受)。
2. 核心函数实现(输入 / 输出)
(1)字符发送函数 putc
- 功能:发送 1 个 unsigned char 类型数据;
- 逻辑:循环判断
USR2.TXDC
(发送完成标志),直到发送缓冲区为空,再写入数据到UTXD
;
void putc(unsigned char d)
{// 等待发送完成(TXDC=1表示缓冲区空)while ((UART1->USR2 & (1 << 3)) == 0); // 写入数据到发送寄存器,启动发送UART1->UTXD = d;
}
(2)字符串发送函数 puts
- 功能:发送 1 个字符串(以
\0
结尾),并自动换行(发送\n
);
void puts(const char *pStr)
{// 遍历字符串,直到结束符'\0'while (*pStr) {putc(*pStr++); // 逐个字符发送}putc('\n'); // 发送换行符
}
(3)字符接收函数 getc
- 功能:接收 1 个 unsigned char 类型数据;
- 逻辑:循环判断
USR2.RDR
(接收就绪标志),直到接收缓冲区有数据,再读取URXD
;
unsigned char getc(void)
{// 等待接收就绪(RDR=1表示有数据)while ((UART1->USR2 & (1 << 0)) == 0); // 读取接收数据(&0xFF确保只取低8位)return (unsigned char)(UART1->URXD & 0XFF);
}
3. 移植标准输入输出(stdio)
需解决编译器依赖问题,确保printf
/scanf
能通过 UART 工作,步骤如下:
- 添加
raise
函数:在uart.c
中添加空实现(避免链接报错);void raise(int n) {// 函数体为空,仅用于解决stdio依赖 }
- 修改汇编文件扩展名:将
project/start.s
改为start.S
(大写 S 表示需要预处理,小写 s 不预处理,避免编译错误); - 更新 Makefile:添加新源码路径和库路径,确保编译时包含
stdio
相关文件;makefile
# 库路径(指定ARM-GCC的库位置) libpath = -lgcc -L/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.4 # 头文件目录(包含bsp、imx6ull、stdio/include) incdirs = bsp imx6ull stdio/include # 源码目录(包含bsp、project、stdio/lib) srcdirs = bsp project stdio/lib# 链接命令(指定链接脚本imx6ull.lds) $(ld) -Timx6ull.lds -o$(target).elf $^ $(libpath) # 编译命令(开启警告、Thumb模式、无标准库) $(cc) -Wall -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c $(include) -o $@ $<
4. 实验验证
输入指令 | 开发板响应 |
---|---|
led on | 开发板 LED 灯点亮 |
led off | 开发板 LED 灯熄灭 |
beep on | 开发板蜂鸣器启动(发声) |
beep off | 开发板蜂鸣器停止(不发声) |
- 实现逻辑:在主函数中循环调用
getc
读取指令,判断字符串后控制 LED(GPIO 输出高 / 低电平)和蜂鸣器(GPIO 控制)。
N 81
波特率
1.什么是单工,半双工,全双工通信?
这三种方式描述了通信中数据传输的方向性。
- 单工通信:数据只能单向传输,一端固定为发送端,另一端固定为接收端。例如:广播(收音机)、遥控器、传统的电视信号。
- 半双工通信:数据可以双向传输,但不能同时进行,需要轮流交替。某一时刻,一方发送,另一方接收。例如:对讲机、某些无线电设备。
- 全双工通信:数据可以同时进行双向传输。通信双方都拥有独立的发送器和接收器,可以同时发送和接收数据。例如:电话通话、手机通话、现代网络通信。
2. 什么是串行通信,什么是并行通信?
这两者描述了数据位的传输方式。
串行通信
:数据位在单一信道上按顺序依次传输。就像单车道的公路,车辆必须一辆接一辆地通过。
- 优点:抗干扰能力强、成本低(线缆数量少)、适合远距离传输。
- 缺点:相对并行通信,传输速率较低(但在现代高速技术下已非常出色)。
- 常见应用:USB、SATA、PCIe、网络通信(如以太网、Wi-Fi)、RS-232、RS-485等。
并行通信
:多个数据位通过多条并行信道同时传输。就像多车道的公路,多辆车可以并排同时行驶。
- 优点:在短距离内,理论上传输速率更高(因为一次可传输多位)。
- 缺点:成本高(线缆多)、各信道间容易产生串扰(Crosstalk)、抗干扰能力弱、信号同步困难,不适合远距离传输。
- 常见应用:计算机内部总线(如早期的IDE硬盘接口、并行打印机接口)、芯片内部总线等。
下面是串行通信与并行通信的对比表,可以帮你更直观地理解它们的区别:
特性 串行通信 并行通信 传输方式 数据位按顺序依次传输(1bit after another) 多个数据位同时传输(multiple bits at once) 数据线数量 少(1条或1对差分线) 多(如8位、16位、32位等) 传输速度 现代高速串行技术(如USB4, PCIe 5.0)速率极高 短距离内理论上更快(一次传多位),但受制于时钟偏移和串扰 抗干扰能力 强(尤其差分串行,如RS-485) 弱(多线间易串扰,信号同步难) 成本与复杂度 较低(线缆少,连接器小,布线简单) 较高(线缆多,连接器大且复杂,布线麻烦) 传输距离 远(可达千米以上,如RS-485) 近(通常小于30米) 典型应用 USB, SATA, PCIe, 以太网, RS-232, RS-485 早期打印机接口(LPT)、IDE硬盘接口、计算机内部总线 3. 什么是异步通信,什么是同步通信?
这两者描述了通信中收发双方如何协调数据传输的时序。
异步通信
:发送和接收设备有各自独立的时钟,不需要统一的时钟信号。通过特定的“起始位”和“停止位” 来标识每个数据帧的开始和结束,帧之间的时间间隔可以变化。
- 优点:对时钟同步要求不高,实现简单,灵活性好。
- 缺点:附加的起始位、停止位等开销降低了有效数据的传输效率。
- 常见应用:UART(常用于RS-232、RS-485)、HTTP/1.1(请求-响应模式)。
同步通信
:收发双方基于统一的时钟信号或同步字符(Sync Word)进行数据传输。数据通常以稳定的数据流或大的数据块形式连续传输。
- 优点:传输效率高(无额外开销),适合高速、大数据量传输。
- 缺点:硬件实现更复杂,需要时钟线或复杂的编码机制来保持同步。
- 常见应用:SPI、I2C、USB、SATA、光纤通道、PCIe。
4. 串口通信的归类
串口通信 特指通过串行接口进行的数据传输。
- 从传输方式看:它属于串行通信(数据逐位传输)。
- 从时序同步方式看:最常见的串口通信(如UART)属于异步通信。它依靠起始位和停止位来界定数据帧,无需独立的时钟信号线。
- 从数据传输方向看:标准的串口通信(如UART)通常包含独立的发送线(TXD)和接收线(RXD),因此支持全双工通信。
所以,串口通信通常是一种异步的、串行的通信方式,并且通常支持全双工。
5. 串口通信的常见电气标准
“电气标准”定义了信号在物理线路上的表示方式(电压水平、阻抗等),直接影响通信距离、抗干扰能力和速度。
标准 逻辑电平表示 特点与用途 TTL 逻辑1: +3.3V 或 +5V
逻辑0: 0V板级电平。常用于单片机、开发板、模块内部芯片之间的短距离通信(通常几十厘米内)。直接与MCU的GPIO引脚电平兼容。 RS-232 逻辑1: -3V ~ -15V
逻辑0: +3V ~ +15V传统串口标准。采用负逻辑和较高电压,抗干扰能力比TTL强。用于计算机COM口、工业设备调试等。传输距离通常不超过15米,速度较低。 RS-485 逻辑1: 两线电压差 +2V ~ +6V (B-A)
逻辑0: 两线电压差 -6V ~ -2V (B-A)差分信号传输。抗共模干扰能力极强,传输距离远(可达1200米),支持多点总线网络(一主多从)。是工业环境中最常用的串行通信标准之一。