非常不错的文章|GPIO模拟串口

💡 原文中文,约1700字,阅读约需5分钟。
📝

内容提要

本文介绍了如何使用通用输入输出(GPIO)来模拟串口功能,以解决微控制器串口数量不足的问题。文章首先解释了串行通信的传输协议,然后详细说明了UART的工作原理和时序图。接着,文章介绍了如何使用GPIO和定时器来模拟串口的发送和接收功能,并提供了相应的代码实现。最后,文章提到了可以关注公众号“良许Linux”获取更多Linux相关知识。

🔎

延伸解读

GPIO模拟串口的适用场景与限制

当微控制器硬件串口数量不足时,用GPIO模拟串口是一种软件补救方案。它需要占用两个GPIO和两个定时器,分别控制接收和发送的时序。由于完全依赖软件定时和中断采样,其可靠性和最高波特率受MCU主频、中断响应速度及系统负载影响。文中在NXP MCU上实测波特率可达38400,但未提及更高波特率下的稳定性,实际使用需根据具体平台评估。

接收端采样策略与起始位检测

接收时,RX引脚检测到下降沿后触发中断,启动定时器。首次定时周期设为半个波特率周期,目的是在起始位中心处采样,确认是否为低电平,从而避免毛刺误判。之后每隔一个波特率周期采样一次数据位。这种中心采样法能提高抗干扰能力,但要求定时器精度足够,且中断服务程序必须及时执行,否则可能丢失位同步。

发送流程与LSB优先顺序

发送时,先输出起始位(逻辑0),然后以1/波特率为周期,在定时器中断中依次发送数据位。数据位按最低位优先(LSB First)顺序发送,例如0x23(二进制00100011)的发送顺序为1→1→0→0→0→1→0→0。停止位为逻辑1,表示传输结束并帮助时钟同步。整个发送过程完全由定时器驱动,需确保中断周期准确,否则接收端可能解析错误。

代码接口与移植注意事项

文章提供了三个关键函数:gpio_uart_demo_init()用于配置波特率、校验位和数据位长度;gpio_uart_read()用于接收指定长度数据,接收完成后停止,需再次调用才能继续接收;gpio_uart_write()用于发送数据。移植到其他平台时,只需修改GPIO和定时器配置。但需注意,当前实现未使用奇偶校验,且采样频率等于波特率,可能影响抗噪性能,实际应用可根据需求调整。

❓

Q&A

微控制器串口数量不够用怎么办?

可以使用GPIO模拟串口功能,通过两个GPIO和两个定时器分别控制接收和发送时序,从而扩展串口数量。

UART通信的8/N/1格式具体指什么?

8/N/1表示1位起始位、8位数据位、无奇偶校验位、1位停止位,这是UART最常用的数据格式。

UART没有时钟信号,接收端如何准确采样数据?

接收端通过检测起始位的下降沿开始采样,并利用波特率确定每位长度,实际采样频率高于波特率,通常对每位进行多次采样并取中间值作为结果。

用GPIO模拟串口接收数据的具体步骤是什么?

当RX引脚检测到下降沿时触发GPIO中断,开启定时器,第一次定时周期设为1/波特率的一半以在中心判断起始位,之后每隔1/波特率在定时器中断中采样RX引脚电平,直到接收完数据。

GPIO模拟串口发送数据时如何控制时序?

首先发送起始位(逻辑0),然后以1/波特率为周期,在定时器中断中依次发送数据位(LSB First)和停止位。

GPIO模拟串口的代码移植到其他平台方便吗?

非常方便,只需要修改GPIO和定时器的配置即可,核心逻辑不变。

🏷️

标签

➡️

继续阅读