在嵌入式系统开发中,串口通信(UART)是最常用的基础通信方式之一。为了解决串口数据读写的不连续性问题,通常会配合环形缓冲区使用,以实现高效、稳定的数据收发缓存管理。
本文介绍一个基于 STM32F4 系列 MCU 编写的串口通信驱动,采用中断方式配合发送/接收缓冲区,并封装为控制台接口,便于在系统中调用。
一、串口缓冲区定义与初始化
串口收发数据通常不直接读写寄存器,而是通过缓冲机制管理数据流。本例中使用了两个环形缓冲区 rxbuf 和 txbuf,分别用于接收和发送:
并在串口初始化时调用 ringbufinit() 对缓冲区进行初始化。
二、串口初始化函数 uartinit
该函数用于初始化 USART1,并完成如下步骤:
初始化收发缓冲区控制结构体。
打开 GPIOA 和 USART1 时钟。
配置 USART1 的引脚复用功能(PA9 → TX,PA10 → RX)。
配置 GPIO 模式(复用模式,无上下拉)。
配置串口参数(波特率等)。
配置 NVIC 中断优先级并使能 USART1 中断。
通过将底层串口配置封装在 uartinit() 中,使得后续调用更加简洁。
三、串口写函数 uartwrite
此函数负责将要发送的数据写入发送缓冲区,并开启发送中断:
通过 ringbufput() 将数据写入 rbsend。
开启 USARTITTXE 发送中断。
返回实际写入字节数。
由于发送在中断中进行,所以只需触发中断即可自动依次发送缓冲区数据。
四、串口读函数 uartread
用于从接收缓冲区读取数据:
通过 ringbufget() 从 rbrecv 中取出数据放入 buf。
返回实际读取长度。
适用于非阻塞方式的读取调用。
五、缓冲区状态查询函数
代码中定义了以下缓冲区状态查询接口:
这些函数用于上层逻辑判断是否可以继续发送、是否有接收数据等,提升串口使用灵活性。
六、TTY 接口结构体封装
串口驱动最终以一个结构体 ttyt 形式暴露接口:
这种方式便于统一管理串口控制接口,适合在大型项目中引入“控制台抽象层”统一管理多个串口。
七、串口中断处理函数 USART1IRQHandler
这是串口驱动的核心部分,负责响应 USART1 的收发中断:
主要包含以下处理逻辑:
接收中断 RXNE:
从接收寄存器读取数据。
存入接收缓冲区 rbrecv。
发送中断 TXE:
从发送缓冲区 rbsend 中取出下一个字节发送。
若无数据可发,关闭发送中断。
溢出错误中断 ORERX:
读取一次数据清除溢出标志位。
通过中断方式处理串口收发,不仅避免了阻塞操作,还能在高速数据传输中保持系统响应性。
八、总结
本驱动模块实现了一个完整的串口通信功能,具备如下特点:
支持发送与接收双缓冲。
使用中断驱动方式收发数据。
提供状态判断接口,便于上层调用。
封装为 ttyt 控制台结构,支持模块化应用。
其设计适用于嵌入式系统中多个串口同时工作的场景,也适合作为 CLI 控制台、调试口或上位机通信口的底层驱动支撑。结合环形缓冲区,可有效避免数据丢失或阻塞,是一种常用、稳定的串口通信实现方式。