一、通信基础概念
在嵌入式系统中,通信的本质是主机之间的数据交互。根据数据传输方式的不同,可从多个维度进行分类:
-
异步与同步
异步通信以字符为单位传输,依赖起始位和停止位进行帧同步,无需共享时钟信号;同步通信则以数据块为单位,通过时钟线实现收发双方的严格同步。
-
串行与并行
串行通信逐位传输数据,占用引脚少,适合长距离通信;并行通信多bit同时传输,速度高但布线复杂,适用于短距离高速总线。
-
单工、半双工与全双工
-
单工:数据只能单向传输,如广播。
-
半双工:允许双向传输,但同一时刻只能一个方向,如对讲机。
-
全双工:可同时收发,如电话通信。
-
-
电气特性
TTL电平(3.3V/5V)常用于板内通信;RS-232采用负逻辑(±12V),抗干扰能力较弱;RS-485利用差分信号,适合远距离、多节点场景。
二、硬件原理图分析
参考《IMX6ULL_MINI_V2.2(Mini底板原理图).pdf》,UART模块的关键硬件设计如下:
-
USB转串口(U8 CH340)
CH340芯片实现USB到TTL串口的转换,使得开发板可通过USB与主机进行串口通信,便于调试与数据交互。
-
电源模块(U12、U13)
提供DCDC稳压功能,并引入防抖与抗干扰设计。需注意,不建议通过USB接口直接为整板供电,以免电流不足导致芯片发热或工作异常。
-
引脚连接
UART1的TX与RX引脚分别对应IMX6ULL的IOMUX复用功能,底板中已通过CH340连接至USB接口,无需额外接线即可使用。
三、UART驱动程序设计
UART驱动开发围绕时钟、引脚、寄存器三部分展开,所有配置均基于《IMX6ULL参考手册》。
1. 时钟初始化
UART模块参考时钟为80MHz,通过**UARTx_UFCR[RFDIV]**设置预分频为1分频,保证波特率计算的基准频率稳定。
2. 引脚复用与电气属性
通过IOMUXC模块配置UART1的TX和RX引脚:
IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX, 0);
IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX, 0x10B0);
IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX, 0);
IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX, 0x10B0);
其中0x10B0配置了驱动能力、压摆率与上拉电阻,确保信号完整性。
3. 核心寄存器配置
| 寄存器 | 作用 | 关键位 |
|---|---|---|
| UCR1 | 模块总使能 | UARTEN |
| UCR2 | 收发控制、数据格式、软件复位 | TXEN, RXEN, WS, STPB, PREN, IRTS |
| UCR3 | 多路复用模式选择 | RXDMUXSEL 置1 |
| UFCR | 参考时钟分频 | RFDIV |
| USR2 | 状态查询 | TXDC(发送完成),RDR(接收就绪) |
| UBIR / UBMR | 波特率配置 | 公式:BaudRate = RefFreq / (16 × (UBMR+1)/(UBIR+1)) |
4. 波特率计算实例
若需115200波特率,取UBIR=31,UBMR=173,代入公式:
text
115200 = 80MHz / (16 × (173+1)/(31+1))
可通过调整UBIR与UBMR的比例实现精确波特率。
四、基础输入输出函数实现
1. 字符发送(putc)
void putc(unsigned char d)
{
while ((UART1->USR2 & (1 << 3)) == 0); // 等待发送完成
UART1->UTXD = d;
}
2. 字符串发送(puts)
void puts(const char *pStr)
{
while (*pStr) putc(*pStr++);
putc('\n');
}
3. 字符接收(getc)
unsigned char getc(void)
{
while ((UART1->USR2 & (1 << 0)) == 0); // 等待接收数据就绪
return (unsigned char)(UART1->URXD & 0xFF);
}
五、stdio库移植要点
在裸机环境中移植标准输入输出库,需注意以下几点:
-
异常处理函数
在
uart.c中添加空实现void raise(int n) {},避免因缺少异常处理函数导致链接错误。 -
汇编文件扩展名
start.s需改为start.S。大写S的汇编文件会先经过预处理,支持宏定义与文件包含,满足stdio库对符号处理的依赖。 -
Makefile调整
-
添加
stdio/include与stdio/lib目录 -
链接时加入
-lgcc及指定库路径 -
编译选项中加入
-Wa,-mimplicit-it=thumb解决Thumb模式下条件执行指令的兼容问题
-
makefile
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
incdirs = bsp imx6ull stdio/include
srcdirs = bsp project stdio/lib
六、实验与作业
实验内容
通过串口输入指令控制外设:
| 输入 | 输出现象 |
|---|---|
led on |
开发板LED点亮 |
led off |
开发板LED熄灭 |
beep on |
蜂鸣器响 |
beep off |
蜂鸣器停止 |
该实验验证了UART输入解析与GPIO控制的能力。
练习题
-
数据类型字节大小
在IMX6ULL平台中,通过
sizeof验证各类型长度(如char=1,int=4,short=2),理解不同架构的数据对齐差异。 -
大小端检测
通过联合体或指针访问整型最低字节,判断当前系统为小端(如ARM Cortex-A系列默认小端)还是大端模式。
七、作业解答
-
单工、半双工、全双工
单工:单向通信;半双工:分时双向;全双工:同时双向。
-
串行与并行通信
串行逐位传输,并行多bit同时传输。
-
异步与同步通信
异步依赖起始/停止位,同步需共享时钟。
-
串口通信分类
串口通信属于异步、串行、全双工通信(TTL/RS-232场景)。
-
串口通信的电气表达
TTL、RS-232、RS-485等,区别在于电平标准、传输距离与抗干扰能力。