GD32F103串口调试:从printf重定向到中断收发,一个工程搞定所有(附完整代码)

张开发
2026/4/21 2:32:17 15 分钟阅读

分享文章

GD32F103串口调试:从printf重定向到中断收发,一个工程搞定所有(附完整代码)
GD32F103串口工程实战从printf重定向到中断收发的完整解决方案刚拿到GD32F103开发板时串口调试往往是第一个需要攻克的难题。如何快速搭建一个稳定可靠的串口通信环境本文将带你从零开始构建一个完整的串口工程涵盖printf重定向、中断收发等核心功能并提供可直接复用的模块化代码。1. 工程架构设计一个优秀的嵌入式工程应该具备清晰的模块划分。我们采用以下文件结构组织串口功能gd32_usart_project/ ├── board_usart.c # 串口驱动实现 ├── board_usart.h # 串口接口声明 ├── gd32f10x_it.c # 中断服务函数 └── main.c # 应用逻辑这种设计将硬件相关代码与业务逻辑分离便于后期维护和移植。每个文件职责明确board_usart.c/h封装串口初始化、数据收发等底层操作gd32f10x_it.c集中处理所有中断事件main.c保持简洁只包含应用逻辑提示模块化设计是嵌入式开发的重要原则能显著提高代码复用率和可维护性。2. 硬件初始化配置串口正常工作需要正确配置GPIO和USART外设。以下是关键初始化步骤void USART_Init(void) { // 1. 使能时钟 rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_USART0); // 2. 配置GPIO gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); // TX gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // RX // 3. 配置串口参数 usart_deinit(USART0); usart_baudrate_set(USART0, 115200U); usart_word_length_set(USART0, USART_WL_8BIT); usart_stop_bit_set(USART0, USART_STB_1BIT); usart_parity_config(USART0, USART_PM_NONE); usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE); // 4. 使能收发功能 usart_receive_config(USART0, USART_RECEIVE_ENABLE); usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); usart_enable(USART0); }关键参数说明参数推荐值说明波特率115200常用调试波特率数据位8bit标准配置停止位1bit最常见设置校验位无简化调试流程硬件流控禁用多数调试场景不需要3. printf重定向实现在嵌入式开发中printf调试是最常用的手段之一。通过重定向fputc函数我们可以让printf输出到串口int fputc(int ch, FILE *f) { usart_data_transmit(USART0, (uint8_t)ch); while(RESET usart_flag_get(USART0, USART_FLAG_TBE)); return ch; }使用前需要包含stdio.h头文件并在工程设置中勾选Use MicroLIBKeil环境或配置相应的标准库支持。实际应用示例printf(系统启动成功版本%s\n, V1.0); printf(温度读数%.1f℃\n, 25.5f);4. 中断接收实现轮询方式接收数据会占用大量CPU资源中断方式更为高效。以下是实现步骤4.1 中断配置// 在USART_Init函数中添加 nvic_irq_enable(USART0_IRQn, 0, 0); // 使能USART0中断 usart_interrupt_enable(USART0, USART_INT_RBNE); // 使能接收中断4.2 中断服务函数void USART0_IRQHandler(void) { if(RESET ! usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) { uint8_t data usart_data_receive(USART0); // 这里可以添加数据处理逻辑 usart_data_transmit(USART0, data); // 回传测试 } }4.3 数据缓冲区设计简单的回环测试可以直接发送接收到的数据但实际应用通常需要缓冲区#define BUF_SIZE 128 uint8_t rx_buf[BUF_SIZE]; uint16_t rx_index 0; void USART0_IRQHandler(void) { if(RESET ! usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) { if(rx_index BUF_SIZE) { rx_buf[rx_index] usart_data_receive(USART0); } } }5. 工程优化技巧5.1 DMA传输对于高速数据传输可以使用DMA减轻CPU负担// DMA配置示例 dma_parameter_struct dma_init_struct; dma_deinit(DMA0, DMA_CH4); dma_init_struct.direction DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory_addr (uint32_t)rx_buffer; dma_init_struct.memory_inc DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number BUF_SIZE; dma_init_struct.periph_addr (uint32_t)USART_DATA(USART0); dma_init_struct.periph_inc DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority DMA_PRIORITY_ULTRA_HIGH; dma_init(DMA0, DMA_CH4, dma_init_struct);5.2 命令解析框架构建简单的命令解析器可以提升调试效率void process_command(uint8_t *cmd) { if(strcmp(cmd, help) 0) { printf(可用命令\n); printf(help - 显示帮助\n); printf(reboot - 重启系统\n); } else if(strcmp(cmd, reboot) 0) { printf(系统即将重启...\n); NVIC_SystemReset(); } }5.3 错误处理机制健壮的串口驱动需要处理各种异常情况void USART0_IRQHandler(void) { // 溢出错误处理 if(usart_flag_get(USART0, USART_FLAG_ORERR) ! RESET) { usart_data_receive(USART0); // 读取DR寄存器清除错误 printf(错误数据溢出\n); } // 帧错误处理 if(usart_flag_get(USART0, USART_FLAG_FERR) ! RESET) { usart_data_receive(USART0); printf(错误帧格式错误\n); } // 正常数据接收 if(RESET ! usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) { uint8_t data usart_data_receive(USART0); // 处理数据... } }6. 完整工程实现将上述模块组合起来我们得到完整的main.c实现#include gd32f10x.h #include systick.h #include board_usart.h #include stdio.h int main(void) { systick_config(); // 初始化系统时钟 USART_Init(); // 初始化串口 printf(\n**** GD32串口调试工程 ****\n); printf(版本: V1.0\n); printf(波特率: 115200\n); printf(已就绪等待输入...\n); while(1) { // 主循环可以添加其他任务 // 串口处理完全由中断驱动 } }实际项目中我曾用这套框架快速搭建了多个产品的调试系统。最令人满意的是它的稳定性——即使在复杂的多任务环境中串口通信也能可靠工作。

更多文章