ARM——UART串口通信

一、串口通信的基本概念

1. 通信:在嵌入式系统中,通信是指两个或两个以上的主机之间的数据互交,这里的主机可以是计算机也可以是嵌入式主机,甚至可以是芯片。

2.通信的分类:

串行**:**将数据的每一个二进制位(bit)依次、逐位通过一条传输线路进行发送和接收。

并行:将数据的多个二进制位(bit)同时通过多条独立的传输线路进行发送和接收。

核心对比表

对比维度 串行 并行
传输方式 逐位、顺序传输 多位,同时传输
线路数量 少(TX/RX/GND) 多(n条数据需要n条数据线)
传输速度 相对较慢 相对较快
抗干扰能力

3.传输方式

通信模式 定义 数据传方向
单工 数据只能在一个固定方向上传输,一个只能发,一个只能收 单项不可逆
半双工 数据可以双向传输,但同一时刻只能有一个方向传输,收发不能同时进行 双向可逆,但不同时
全双工 数据可以同时在两个方向上传输,收发互不影响 双向可逆且同时

4.数据传输模式

对比维度 异步 同步
时钟 无共享时钟,靠波特率同步 有共享时钟
数据格式 起始位+数据+停止位 连续数据流,无起始位
传输效率 较低 较高
硬件连线 简单(通常:TX/RX) 复杂(需要时钟线)
典型协议 UART SPI

异步通信波特率的计算:

二、数据传输格式图

数据格式:1个起始位+8个数据位+1个校验位+1个停止位

三、UART通信的流程

3.1 UART1初始化

步骤 操作内容 调用函数 / 寄存器 参数 / 值 说明
1.1 配置 UART1_TX 引脚复用 IOMUXC_SetPinMux() IOMUXC_UART1_TX_DATA_UART1_TX, 0 设置为 ALT5(UART1_TX 功能)
1.2 配置 UART1_RX 引脚复用 IOMUXC_SetPinMux() IOMUXC_UART1_RX_DATA_UART1_RX, 0 设置为 ALT5(UART1_RX 功能)
1.3 配置 TX 引脚电气特性 IOMUXC_SetPinConfig() IOMUXC_UART1_TX_DATA_UART1_TX, 0x10B0 100K 上拉、高速、中等驱动强度
1.4 配置 RX 引脚电气特性 IOMUXC_SetPinConfig() IOMUXC_UART1_RX_DATA_UART1_RX, 0x10B0 同上,确保信号完整性

3.2 UART1 初始化 --- 模块控制寄存器配置

步骤 操作内容 寄存器 位操作 说明
2.1 关闭 UART1 模块 UCR1 UCR1[0] = 0 确保在配置期间模块禁用
2.2 配置 UCR2 UCR2 ` = (1<<14)<br>&= ~(1<<8)<br>&= ~(1<<6)<br>
2.3 配置 UCR3 UCR3 ` = (1<<2)`
2.4 使能 UART1 UCR1 ` = (1<<0)`

3.3 UART1 初始化 --- FIFO 与波特率配置

步骤 操作内容 寄存器 值 / 操作 说明
3.1 清除接收触发级别 UFCR &= ~(7 << 7) 清除原触发阈值
3.2 设置接收触发级别 UFCR ` = (5 << 7)`
3.3 设置波特率整数部分 UBIR = 999 Baud Rate Integer Register
3.4 设置波特率模数部分 UBMR = 43401 Baud Rate Modulator Register 配合 UBIR 实现 ≈115200 bps(参考时钟 80 MHz)

3.4 发送数据流程

步骤 操作内容 函数 / 寄存器 条件 / 操作 说明
4.1 等待发送 FIFO 可用 USR2 轮询 USR2[3] == 1(TXFE) TXFE=1 表示 FIFO 空,可写入
4.2 写入发送数据 UTXD UTXD = d 写入后硬件自动移位发送
4.3 发送字符串 puts() 循环调用 putc() 逐字符发送,末尾追

3.5 接收数据流程

步骤 操作内容 函数 / 寄存器 条件 / 操作 说明
5.1 等待接收数据就绪 USR2 轮询 USR2[0] == 0(RXFE=0) RXFE=0 表示 FIFO 非空
5.2 读取接收数据 URXD return (unsigned char)URXD 读操作会清除部分状态位(如帧错)

四、标准库的兼容

4.1添加Raise()函数

原因 :即使使用 -nostdlib,某些 C 库函数(如 assert()、异常处理路径)仍可能引用 raise()。若未定义,链接时报错:undefined reference to 'raise'

复制代码
void raise(int n) {
    // 空函数,仅用于满足链接器要求
}

4.2汇编文件扩展名改为大写 .S

原因

.s:直接汇编,不经过 C 预处理器(无法使用 #include, #define, 条件编译等)。

.S:先经 C 预处理器 处理,再汇编(支持宏、头文件包含等)。

复制代码
#include "imx6ull.h"
.equ STACK_TOP, 0x80200000

4.3 修改 Makefile 以支持 stdio

复制代码
# 头文件搜索路径(含 stdio 头文件)
incdirs = bsp imx6ull stdio/include

# 源文件目录(含 stdio 实现)
srcdirs = bsp project stdio/lib

4.4 更新链接命令

复制代码
# 指定 GCC 内部库路径(如 libgcc.a)
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

 $ (target).elf:  $ (objs)
     $ (ld) -T imx6ull.lds -o  $ @  $ ^  $ (libpath)

4.5 确保编译命令支持预处理

复制代码
# 编译 .c 文件
%.o: %.c
     $ (cc) -Wall -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin  $ (include) -c -o  $ @  $ <

# 编译 .S 文件(会自动预处理)
%.o: %.S
     $ (cc) -Wall -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin  $ (include) -c -o  $ @  $ <
相关推荐
松涛和鸣4 小时前
DAY61 IMX6ULL UART Serial Communication Practice
linux·服务器·网络·arm开发·数据库·驱动开发
代码游侠13 小时前
学习笔记——时钟系统与定时器
arm开发·笔记·单片机·嵌入式硬件·学习·架构
CQ_YM13 小时前
ARM--SDK、led、beep与链接脚本
c语言·arm开发·嵌入式硬件·嵌入式
梁洪飞16 小时前
noc 片上网络
linux·arm开发·嵌入式硬件·arm
持续学习的程序员+118 小时前
强化学习Actor/Learner框架介绍(lerobot版)
arm开发
断水客19 小时前
搭建ARM LINUX 内核 QEMU 仿真调试环境
linux·运维·arm开发·嵌入式
2301_7722042820 小时前
ARM——时钟系统
arm开发·单片机·嵌入式硬件
VekiSon1 天前
ARM架构——时钟系统与定时器详解
linux·c语言·arm开发·嵌入式硬件·架构
松涛和鸣1 天前
60、嵌入式定时器深度解析:EPIT与GPT
c语言·arm开发·单片机·嵌入式硬件·gpt·fpga开发