news 2026/9/29 11:48:07

ARM-uart

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ARM-uart

今天学习ARM裸机下UART串口。串口是嵌入式开发最基础的调试工具,打印日志、收发指令全都靠它。以前直接用printf,没关心底层怎么实现;今天搞懂串行通信基础概念,手写UART寄存器配置,还把stdio库移植到裸机,直接能用scanf、printf,收获挺大。

一、串口通信基础概念

嵌入式通信分为并行通信和串行通信。
并行通信同一时刻传输多个比特,速度快,但是占用引脚多;串行通信把数据拆成一比特一比特,在一根线上依次传输,引脚占用少,硬件简单,UART串口就属于串行里面的异步通信。

按照数据传输方向分为三种模式:

  1. 单工:只能单向传输,一端固定发送、一端固定接收;
  2. 半双工:双向可以通信,但同一时刻只能一方发、另一方收,不能同时收发,类似对讲机;
  3. 全双工:两根数据线,收发独立,可以同时发送和接收,就像打电话,我们常用的TTL‑UART、RS232都是全双工;RS485是差分信号,属于半双工。

同步通信 、异步通信
同步通信:除数据线之外额外带一根时钟线,收发双方跟着同一个时钟节拍采样数据,例如I2C、SPI;
异步通信(UART):没有时钟线,收发双方事先约定波特率,依靠起始位、停止位来区分字节,双方本地时钟误差不能超过6%。

UART一帧数据格式(TTL电平):
空闲状态:数据线高电平;
起始位:拉低1个bit时间,代表一帧开始;
数据位:从最低位LSB开始发送;
校验位:无校验、奇校验、偶校验;
停止位:拉高,标记本字节结束。

波特率bps:每秒传输的比特数,常用:9600、115200。波特率决定每一位电平持续时间。

电气标准区别:
TTL:芯片引脚电平,3.3V/5V,传输距离很短;我们开发板CH340芯片做USB转TTL,电脑USB转成TTL电平给到IMX6ULL的UART引脚;
RS232:使用正负电压,逻辑1为‑3V‑15V,逻辑0为+3V+15V,距离最远二三十米;
RS485:差分信号A/B,依靠电压差值识别信号,抗干扰强,可以传到1200米。

二、IMX6ULL UART硬件与寄存器要点

我们板子上CH340负责USB转TTL,连接到UART1的TX、RX引脚。写裸机UART,步骤固定:

  1. 开启UART外设时钟(时钟系统前面学过,CCGR时钟门控)
  2. IO引脚复用配置:把普通GPIO复用为UART_TX、UART_RX,同时配置电气属性
  3. UART软件复位,配置控制寄存器UCR1、UCR2、UCR3
  4. 配置分频寄存器UFCR,设置波特率相关UBIR、UBMR
  5. 使能发送、接收,打开UART模块总开关

重点寄存器:
UTXD:发送寄存器,写入数据就启动发送; URXD:接收寄存器,只读,存放收到字节;
UCR1:bit0 UARTEN,UART模块总开关; UCR2:软件复位位、RX接收使能、TX发送使能、数据位长度、停止位、校验位;
UCR3:UART多路复用模式,IMX6ULL必须把bit2置1; UFCR:参考时钟分频;
UBIR / UBMR:波特率生成,波特率计算公式: BaudRate = Ref Freq/(16 \times ((UBMR + 1) / (UBIR + 1))) USR2状态寄存器:bit3TXDC发送完成标志;bit0RDR接收数据就绪标志。

三、UART1底层驱动代码

#include"uart.h"#include"MCIMX6Y2.h"#include"fsl_iomuxc.h"voiduart1_init(void){//1.引脚复用:配置TX RX为UART功能IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX,0);IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX,0);//2.配置引脚电气属性IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX,0x10B0);IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX,0x10B0);//UART软件复位UART1->UCR2&=~(1<<0);unsignedintr=0;r=UART1->UCR2;r|=(1<<14);//忽略RTS流控r&=~(1<<8);//关闭奇偶校验r&=~(1<<6);//1位停止位r|=(1<<5);//8位数据位r|=(1<<2);//TX发送使能r|=(1<<1);//RX接收使能UART1->UCR2=r;//IMX6ULL UART必须设置RXDMUXSEL=1UART1->UCR3|=(1<<2);//设置参考时钟分频UART1->UFCR&=~(7<<7);UART1->UFCR|=(5<<7);//波特率参数配置UART1->UBIR=999;UART1->UBMR=43402;//打开UART模块总使能UART1->UCR1|=(1<<0);}//发送单个字符voidputc(unsignedcharc){//等待发送完成标志TXDCwhile((UART1->USR2&(1<<3))==0);UART1->UTXD=c;}//发送字符串voidputs(constchar*s){while(*s){putc(*s++);}putc('\n');}//接收单个字符,阻塞等待unsignedchargetc(void){//等待接收数据就绪RDRwhile((UART1->USR2&(1<<0))==0);returnUART1->URXD&0xFF;}//移植stdio库必须提供空的raise函数,否则编译报错voidraise(intn){}

裸机移植C标准库stdio要注意:

  1. 必须实现空函数void raise(int n);
  2. 启动汇编文件后缀要用大写start.S,大写S会做预处理;小写s不会预处理;
  3. Makefile需要增加stdio头文件路径、源码路径,链接时加入libgcc库。

底层写好putc、getc之后,标准库的printf、scanf内部就会调用这两个底层函数,于是裸机就可以直接使用格式化输入输出。

四、main主函数测试代码

这里复用我们之前写好的时钟、GPT定时器驱动,初始化顺序:中断控制器 → 时钟初始化 → 外设初始化,最后初始化uart1。
测试功能:串口输入两个整数,板子计算加法,把结果打印回串口工具。

#include"MCIMX6Y2.h"#include"fsl_iomuxc.h"#include"led.h"#include"beep.h"#include"key.h"#include"interrupt.h"#include"clock.h"#include"epit.h"#include"gpt.h"#include"uart.h"#include"stdio.h"intmain(void){system_interrupt_init();clock_init();led_init();beep_init();key_init();//epit1_init();gpt1_init();uart1_init();unsignedintnum1=0,num2=0;while(1){led_nor();//串口输入两个数字,板子做加法运算回显scanf("%d %d",&num1,&num2);printf("%d + %d = %d\n",num1,num2,num1+num2);}return0;}

现象:打开串口调试助手,波特率和代码配置保持一致,输入两个数字按回车,开发板计算加法并打印算式结果。也可以把注释打开,直接调用getc()接收单字符,puts()输出字符串。

小结

  1. UART是异步串行通信,没有时钟线,全靠双方约定好波特率,依靠起始、停止位识别每一帧数据;和I2C/SPI这类同步通信要区分开。TTL、RS232、RS485是不同电气物理标准,逻辑电平、传输距离各不相同。
  2. IMX6ULL裸机UART开发流程:时钟 → IO复用配置 → 寄存器复位配置 → 波特率配置 → 使能收发模块,任何一步出错串口都无法正常收发。特别记住UCR3的bit2必须置1,这是IMX6ULL的坑点。
  3. putc、getc是最底层字符收发,实现这两个接口之后,就可以移植stdio,直接使用printf、scanf格式化输入输出,极大方便裸机调试。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 11:43:20

数智人一体机低功耗设计全解析:从硬件选型到运营成本优化

1. 功耗这件事&#xff0c;为什么决定了一体机的生死我之前见过太多项目翻车&#xff0c;不是翻在功能做不出来&#xff0c;而是翻在运营三个月后的电费单上。数智人一体机这东西&#xff0c;跟普通广告屏不一样&#xff0c;它得一天到晚醒着&#xff0c;随时准备跟人对话。你说…

作者头像 李华
网站建设 2026/9/29 11:40:19

OpenHarmony I2C实战:从物理层波形到HDF驱动适配

1. I2C 总线不是“接上线就能通”的黑盒子——它是一条需要被“读懂”的双向对话通道I2C 总线在 OpenHarmony 系统开发中&#xff0c;远不止是“连两根线、配个地址、调个 read/write API”这么简单。我带过十几支嵌入式团队做鸿蒙设备侧开发&#xff0c;几乎每支队伍都在 I2C …

作者头像 李华
网站建设 2026/9/29 11:37:24

模拟IC设计全流程指南:从PDK到版图,告别玄学

做模拟IC设计这个行当&#xff0c;说起来有点尴尬——它明明是最古老的集成电路方向之一&#xff0c;从早期运放芯片诞生到现在已经好几十年&#xff0c;却老被当成“玄学”来看待。很多刚入行的同学拿着EDA工具打开PDK里的器件模型&#xff0c;对着原理图一调好几天&#xff0…

作者头像 李华
网站建设 2026/9/29 11:34:25

10 分钟跑通 UI-TARS Desktop:用一句自然语言操作你的电脑

10 分钟跑通 UI-TARS Desktop&#xff1a;用一句自然语言操作你的电脑 【免费下载链接】UI-TARS-desktop The Open-Source Multimodal AI Agent Stack: Connecting Cutting-Edge AI Models and Agent Infra 项目地址: https://gitcode.com/GitHub_Trending/ui/UI-TARS-deskto…

作者头像 李华
网站建设 2026/9/29 11:31:14

网络安全应急处置流程图:从静态PDF到可执行响应机制

简介&#xff1a;一份面向企业网络安全管理的应急处置流程图文档&#xff0c;适用于信息安全负责人、IT运维及应急响应人员&#xff0c;用于规范从预防、预警到事件分类、分级和处置的完整流程。文档依据国家相关标准编制&#xff0c;明确了由董事长任组长的信息安全领导小组与…

作者头像 李华