当前位置: 首页 > news >正文

第30讲:实战——USART串口收发原型快速搭建+调试

CSDN专栏:

  • 嵌入式程序开发实战
  • 嵌入式双范式AI编程
  • 嵌入式开发必掌握
  • 嵌入式求职面试技术资料

第30讲:实战——USART串口收发原型快速搭建+调试

一、USART基础

USART(通用同步/异步收发器)是嵌入式最常用的通信接口,用于与PC、其他MCU、模块通信。

1.1 USART配置要点

基本参数

  • 波特率:9600、19200、38400、57600、115200等
  • 数据位:8位(最常用)
  • 停止位:1位(最常用)
  • 校验位:无(最常用)
  • 流控:无(最常用)

引脚配置

USART1:PA9(TX)、PA10(RX)
USART2:PA2(TX)、PA3(RX)
USART3:PB10(TX)、PB11(RX)

1.2 通信模式

轮询模式

特点:阻塞等待
适用:简单应用、调试

中断模式

特点:非阻塞、事件驱动
适用:实际应用

DMA模式

特点:高效、CPU占用少
适用:高速、大数据量

二、串口发送实战

2.1 基础发送

需求

串口发送"Hello World"

Prompt

生成STM32F103 USART发送代码: - USART1:PA9(TX)、PA10(RX) - 波特率:115200 - 功能:发送"Hello World" - 使用HAL库

AI生成

#include"stm32f1xx_hal.h"UART_HandleTypeDef huart1;voidUSART1_Init(void){huart1.Instance=USART1;huart1.Init.BaudRate=115200;huart1.Init.WordLength=UART_WORDLENGTH_8B;huart1.Init.StopBits=UART_STOPBITS_1;huart1.Init.Parity=UART_PARITY_NONE;huart1.Init.Mode=UART_MODE_TX_RX;huart1.Init.HwFlowCtl=UART_HWCONTROL_NONE;huart1.Init.OverSampling=UART_OVERSAMPLING_16;HAL_UART_Init(&huart1);}intmain(void){HAL_Init();SystemClock_Config();USART1_Init();char*msg="Hello World\r\n";HAL_UART_Transmit(&huart1,(uint8_t*)msg,strlen(msg),100);while(1);}

2.2 printf重定向

需求

使用printf输出到串口

代码

// 重定向fputcintfputc(intch,FILE*f){HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,100);returnch;}// 使用intmain(void){HAL_Init();SystemClock_Config();USART1_Init();printf("System Start\r\n");printf("Version: 1.0\r\n");while(1){printf("Tick: %d\r\n",HAL_GetTick());HAL_Delay(1000);}}

Keil配置

Options → Target → Use MicroLIB(勾选)

2.3 格式化输出

需求

输出各种格式的数据

代码

voidPrint_Data(void){uint8_tdata=0x55;uint16_tvalue=1234;floattemperature=25.6f;// 十进制printf("Value: %d\r\n",value);// 十六进制printf("Hex: 0x%02X\r\n",data);// 浮点数printf("Temperature: %.2f\r\n",temperature);// 二进制printf("Binary: ");for(inti=7;i>=0;i--){printf("%d",(data>>i)&1);}printf("\r\n");}

三、串口接收实战

3.1 轮询接收

需求

接收数据并回显

代码

intmain(void){HAL_Init();SystemClock_Config();USART1_Init();uint8_trxData;while(1){// 接收数据if(HAL_UART_Receive(&huart1,&rxData,1,100)==HAL_OK){// 回显HAL_UART_Transmit(&huart1,&rxData,1,100);}}}

3.2 中断接收

需求

使用中断接收数据

Prompt

生成STM32F103 USART中断接收代码: - USART1:PA9(TX)、PA10(RX) - 波特率:115200 - 功能:中断接收并回显 - 使用HAL库

AI生成

uint8_trxData;voidUSART1_Init(void){huart1.Instance=USART1;huart1.Init.BaudRate=115200;huart1.Init.WordLength=UART_WORDLENGTH_8B;huart1.Init.StopBits=UART_STOPBITS_1;huart1.Init.Parity=UART_PARITY_NONE;huart1.Init.Mode=UART_MODE_TX_RX;huart1.Init.HwFlowCtl=UART_HWCONTROL_NONE;huart1.Init.OverSampling=UART_OVERSAMPLING_16;HAL_UART_Init(&huart1);// 启动接收中断HAL_UART_Receive_IT(&huart1,&rxData,1);}voidUSART1_IRQHandler(void){HAL_UART_IRQHandler(&huart1);}voidHAL_UART_RxCpltCallback(UART_HandleTypeDef*huart){if(huart->Instance==USART1){// 回显HAL_UART_Transmit(&huart1,&rxData,1,100);// 继续接收HAL_UART_Receive_IT(&huart1,&rxData,1);}}intmain(void){HAL_Init();SystemClock_Config();USART1_Init();while(1){// 主循环可以做其他事情}}

3.3 环形缓冲区接收

需求

使用环形缓冲区接收数据,避免数据丢失

代码

#defineBUFFER_SIZE256typedefstruct{uint8_tbuffer[BUFFER_SIZE];uint16_thead;uint16_ttail;}RingBuffer_t;RingBuffer_t rxBuffer={0};voidRingBuffer_Write(uint8_tdata){uint16_tnextHead=(rxBuffer.head+1)%BUFFER_SIZE;if(nextHead!=rxBuffer.tail){// 缓冲区未满rxBuffer.buffer[rxBuffer.head]=data;rxBuffer.head=nextHead;}}uint8_tRingBuffer_Read(uint8_t*data){if(rxBuffer.head==rxBuffer.tail){// 缓冲区空return0;}*data=rxBuffer.buffer[rxBuffer.tail];rxBuffer.tail=(rxBuffer.tail+1)%BUFFER_SIZE;return1;}uint16_tRingBuffer_Available(void){return(rxBuffer.head-rxBuffer.tail+BUFFER_SIZE)%BUFFER_SIZE;}// 中断回调voidHAL_UART_RxCpltCallback(UART_HandleTypeDef*huart){if(huart->Instance==USART1){RingBuffer_Write(rxData);HAL_UART_Receive_IT(&huart1,&rxData,1);}}// 主循环处理voidProcess_UartData(void){uint8_tdata;while(RingBuffer_Read(&data)){// 处理数据printf("Received: 0x%02X\r\n",data);}}

四、串口调试技巧

4.1 串口工具

常用工具

- 串口调试助手:SSCOM、XCOM、串口精灵 - 终端工具:PuTTY、Tera Term、SecureCRT - 分析工具:逻辑分析仪、协议分析仪

配置

波特率:115200 数据位:8 停止位:1 校验位:无 流控:无

4.2 调试输出

分级日志

#defineLOG_LEVEL3// 0:无 1:错误 2:警告 3:信息 4:调试#defineLOG_ERROR(fmt,...)if(LOG_LEVEL>=1)printf("[ERROR] "fmt"\r\n",##__VA_ARGS__)#defineLOG_WARN(fmt,...)if(LOG_LEVEL>=2)printf("[WARN] "fmt"\r\n",##__VA_ARGS__)#defineLOG_INFO(fmt,...)if(LOG_LEVEL>=3)printf("[INFO] "fmt"\r\n",##__VA_ARGS__)#defineLOG_DEBUG(fmt,...)if(LOG_LEVEL>=4)printf("[DEBUG] "fmt"\r\n",##__VA_ARGS__)// 使用LOG_ERROR("UART initialization failed");LOG_WARN("Buffer nearly full: %d",usage);LOG_INFO("System started");LOG_DEBUG("Received byte: 0x%02X",data);

4.3 数据分析

十六进制输出

voidPrint_Hex(uint8_t*data,uint16_tlen){printf("Hex: ");for(uint16_ti=0;i<len;i++){printf("%02X ",data[i]);}printf("\r\n");}

ASCII输出

voidPrint_ASCII(uint8_t*data,uint16_tlen){printf("ASCII: ");for(uint16_ti=0;i<len;i++){if(data[i]>=32&&data[i]<=126){// 可打印字符printf("%c",data[i]);}else{printf(".");}}printf("\r\n");}

混合输出

voidPrint_Data_Mixed(uint8_t*data,uint16_tlen){printf("Data[%d]:\r\n",len);for(uint16_ti=0;i<len;i++){printf("%02X ",data[i]);if((i+1)%16==0){// 每16字节换行printf(" ");for(uint16_tj=i-15;j<=i;j++){if(data[j]>=32&&data[j]<=126){printf("%c",data[j]);}else{printf(".");}}printf("\r\n");}}// 处理剩余字节if(len%16!=0){for(uint16_ti=len%16;i<16;i++){printf(" ");}printf(" ");for(uint16_tj=len-(len%16);j<len;j++){if(data[j]>=32&&data[j]<=126){printf("%c",data[j]);}else{printf(".");}}printf("\r\n");}}

五、常见问题与解决

5.1 乱码问题

现象:串口输出乱码

原因

1. 波特率不匹配 2. 系统时钟配置错误 3. 数据格式不匹配

解决

// 验证波特率voidVerify_Baudrate(void){printf("SystemCoreClock: %d\r\n",SystemCoreClock);printf("UART BRR: 0x%04X\r\n",USART1->BRR);uint32_tactualBaud=SystemCoreClock/(USART1->BRR&0xFFFF);printf("Actual baudrate: %d\r\n",actualBaud);}

5.2 数据丢失

现象:接收数据丢失

原因

1. 接收缓冲区溢出 2. 处理速度慢 3. 中断被阻塞

解决

// 使用环形缓冲区// 提高处理速度// 优化中断优先级

5.3 发送卡死

现象:发送函数卡死

原因

1. 超时时间过短 2. UART未初始化 3. 引脚配置错误

解决

// 增加超时时间HAL_UART_Transmit(&huart1,data,len,1000);// 1秒超时// 检查初始化if(huart1.Instance!=USART1){printf("UART not initialized\r\n");}

六、本讲核心要点

6.1 记住这三句话

  1. 串口配置:波特率、数据位、停止位、校验位,最常用8N1

  2. 接收方式:轮询(简单)、中断(常用)、DMA(高效)

  3. 调试技巧:printf重定向、分级日志、数据分析

6.2 实践建议

对于新手

  • 学习串口配置
  • 实践中断接收
  • 使用调试工具

对于有经验工程师

  • 建立串口驱动模板
  • 实现环形缓冲区
  • 优化调试输出

6.3 下讲预告

第31讲将深入讲解:实战:SPI屏驱动快速试错、点亮屏幕

SPI常用于驱动屏幕,如何快速试错点亮屏幕?下一讲将详细讲解。

http://www.jsqmd.com/news/1246468/

相关文章:

  • 本地CDN部署优化VRChat资源加载实践
  • 也谈TDD,以及三层架构、设计模式、ORM……:没有免费的午餐
  • ERP物料编码乱码问题排查与解决方案
  • Unity开发进阶:从可视化编辑到面向对象编程的思维跃迁
  • 2026年镇远小吃避坑指南:锁定26年零预制老店 - 万相科技
  • 2026年宁波大型搬家公司联系方式与价格透明实力测评 - myqiye
  • Visual C++运行库终极修复指南:从原理到一键解决方案
  • 企业微信应用消息推送(Markdown与图文)的可靠性重试与限流设计
  • C++实现神经网络:从底层原理到高性能部署实战
  • 2025护颈仪深度测评:性能对比与选购指南
  • 亲身到店探访上海爱彼售后服务中心|地址与客服服务热线(2026年7月最新) - 爱彼中国官方服务中心
  • 笔类产品评测:从技术参数到使用体验的全面分析
  • 主流内网穿透汇总,全是大实话
  • 2026年7月海信洗衣机售后服务电话24小时全新专属热线升级公示最新公告 - 家电技术百科
  • 零代码组态让产线看板当天上线,HiWoo Edge 边缘监测一体机这么干
  • 3D视频生成框架WorldWarp:几何一致性与时空噪声调度
  • 浏览器内 LLM 推理:WebGPU 量化模型与推理管线搭建
  • 星海皇冠假日酒店实力测评,价格透明无隐形消费避坑必看 - myqiye
  • 亲身到店体验上海亨得利名表服务中心|热线电话及门店地址(2026年7月更新) - 亨得利官方
  • Playwright自动化测试:跨浏览器、自动等待与网络拦截实战指南
  • 做 AI 视频,先让 Blender 把镜头演一遍
  • 基于远距离观察的话轮转换沉默阈值建模与Python实践
  • AI 辅助安全审计:让模型逐行分析 Rust 代码中的安全薄弱点的方法
  • 佛山乐从低预算实体店如何选择?看美诚AI自动化获客方案
  • 高校科研成果可视化展示系统设计与实现
  • 基于扩散模型的4K视频生成技术解析与应用实践
  • UE5 RPG游戏交互设计:基于接口与自定义深度的智能悬停描边系统实现
  • 嵌入式I2C通信实战:从寄存器配置到驱动实现与故障排查
  • 社交媒体内容创作:暖心毒舌的爆款方法论
  • 网页上一个词或一段话看不懂?划一下就可以翻译