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  $ @  $ <
相关推荐
陌上花开缓缓归以10 小时前
LiteOS和RTOS 系统选型分析
arm开发
深圳市九鼎创展科技12 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
森焱森15 小时前
嵌入式硬件工程师应知 白银快速分析报告
linux·c语言·arm开发·嵌入式硬件·去中心化
森G1 天前
七、04ledc-sdk--------makefile有变化
linux·c语言·arm开发·c++·ubuntu
VekiSon1 天前
Linux内核驱动——杂项设备驱动与内核模块编译
linux·c语言·arm开发·嵌入式硬件
AI+程序员在路上1 天前
Nand Flash与EMMC区别及ARM开发板中的应用对比
arm开发
17(无规则自律)2 天前
深入浅出 Linux 内核模块,写一个内核版的 Hello World
linux·arm开发·嵌入式硬件
梁洪飞2 天前
内核的schedule和SMP多核处理器启动协议
linux·arm开发·嵌入式硬件·arm
代码游侠3 天前
学习笔记——Linux字符设备驱动
linux·运维·arm开发·嵌入式硬件·学习·架构
syseptember3 天前
Linux网络基础
linux·网络·arm开发