尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
STM32F103通过USART串口指令实现多LED状态控制
1. 项目背景与硬件准备最近在做一个智能家居控制项目需要STM32通过串口接收指令控制多个LED灯的状态。手头正好有块正点原子的精英版STM32F103ZET6开发板板载4个LED和CH340G串口芯片特别适合做这个实验。先说说硬件连接开发板USART1的PA9(TX)和PA10(RX)已通过CH340G与电脑连接LED1~LED4分别连接在PB5、PB0、PB1、PC13引脚使用USB转串口模块时记得把开发板的BOOT0跳线帽接到1下载模式实测中发现个坑如果直接用杜邦线连接USB转TTL模块必须共地GND接GND否则会出现乱码。有次调试两小时才发现是地线没接气得我差点把开发板扔出窗外。2. USART串口初始化配置先上干货初始化代码要配置三个部分// 1. GPIO初始化 void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; // 开启GPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE); // 配置USART1的TX(PA9)为复用推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // 配置USART1的RX(PA10)为浮空输入 GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); // 配置LED引脚(PB5,PB0,PB1,PC13)为推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_Init(GPIOB, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_13; GPIO_Init(GPIOC, GPIO_InitStructure); } // 2. USART初始化 void USART1_Config(void) { USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); USART_InitStructure.USART_BaudRate 115200; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_Init(USART1, USART_InitStructure); USART_Cmd(USART1, ENABLE); }波特率计算有个小技巧当系统时钟72MHz时115200波特率对应的USARTDIV39.0625。配置时直接填整数部分39小数部分0.0625×161所以BRR寄存器应设置为0x271。3. 指令集设计与状态控制3.1 指令格式定义为了控制多个LED我设计了这样的指令格式单灯控制LEDx_ON / LEDx_OFF x1~4群组控制ALL_ON / ALL_OFF特殊效果ALL_BLINK闪烁3次查询状态STATUS?例如发送LED1_ON点亮PB5的LED发送ALL_BLINK让所有LED闪烁发送STATUS?返回当前LED状态3.2 状态机实现用状态机处理指令更可靠下面是核心逻辑typedef enum { CMD_LED1_ON, CMD_LED1_OFF, CMD_LED2_ON, // ...其他指令枚举 CMD_UNKNOWN } CommandType; CommandType parse_command(char* cmd) { if(strstr(cmd, LED1_ON)) return CMD_LED1_ON; if(strstr(cmd, LED1_OFF)) return CMD_LED1_OFF; // ...其他条件判断 return CMD_UNKNOWN; } void execute_command(CommandType cmd) { switch(cmd) { case CMD_LED1_ON: GPIO_ResetBits(GPIOB, GPIO_Pin_5); USART_SendString(USART1, LED1 is ON\r\n); break; case CMD_LED1_OFF: GPIO_SetBits(GPIOB, GPIO_Pin_5); USART_SendString(USART1, LED1 is OFF\r\n); break; // ...其他case } }4. 字符串解析与中断处理4.1 接收缓冲区管理#define MAX_CMD_LEN 32 char rx_buffer[MAX_CMD_LEN]; uint8_t rx_index 0; void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) { char ch USART_ReceiveData(USART1); if(ch \n || rx_index MAX_CMD_LEN-1) { rx_buffer[rx_index] \0; process_command(rx_buffer); rx_index 0; } else { rx_buffer[rx_index] ch; } } }4.2 实用字符串处理技巧在嵌入式环境处理字符串要特别注意效率我总结了几个技巧用strncmp代替strstr做前缀匹配更高效环形缓冲区比线性缓冲区更适合高频数据使用查表法解析指令比if-else更快const CmdEntry cmd_table[] { {LED1_ON, CMD_LED1_ON}, {LED1_OFF, CMD_LED1_OFF}, // ...其他指令 }; CommandType fast_parse(char* cmd) { for(int i0; isizeof(cmd_table)/sizeof(CmdEntry); i) { if(strncmp(cmd, cmd_table[i].name, strlen(cmd_table[i].name)) 0) return cmd_table[i].cmd; } return CMD_UNKNOWN; }5. 系统整合与调试5.1 主程序逻辑int main(void) { SystemInit(); GPIO_Config(); USART1_Config(); // 使能接收中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); NVIC_EnableIRQ(USART1_IRQn); // 发送欢迎信息 USART_SendString(USART1, LED Control System Ready\r\n); while(1) { // 主循环可以添加其他任务 __WFI(); // 进入低功耗模式 } }5.2 调试经验分享调试时踩过几个坑波特率不匹配电脑端和STM32的波特率必须完全一致中断优先级如果系统有其他中断要合理设置USART中断优先级缓冲区溢出一定要做长度检查我有次就因为没检查导致系统崩溃电气干扰长距离传输时建议加120Ω终端电阻推荐使用SecureCRT或Putty作为串口调试工具比普通的串口助手更稳定。调试时可以添加这样的调试信息#define DEBUG(fmt, ...) \ do { \ char dbg_buf[64]; \ sprintf(dbg_buf, [DEBUG] fmt \r\n, ##__VA_ARGS__); \ USART_SendString(USART1, dbg_buf); \ } while(0)6. 功能扩展与优化6.1 增加指令校验为防止误操作可以增加简单的校验机制指令格式#CMD?问号是校验和校验和计算所有字符异或bool verify_command(char* cmd) { if(cmd[0] ! # || strlen(cmd) 3) return false; char checksum 0; for(int i1; istrlen(cmd)-1; i) { checksum ^ cmd[i]; } return (checksum cmd[strlen(cmd)-1]); }6.2 使用DMA提高效率当需要控制大量LED或高频通信时可以用DMAvoid DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel4); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)USART1-DR; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)tx_buffer; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize 0; DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode DMA_Mode_Normal; DMA_InitStructure.DMA_Priority DMA_Priority_High; DMA_InitStructure.DMA_M2M DMA_M2M_Disable; DMA_Init(DMA1_Channel4, DMA_InitStructure); USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); }7. 最终效果演示烧录程序后打开串口助手测试发送LED1_ON→ PB5 LED点亮发送ALL_BLINK→ 所有LED闪烁三次发送STATUS?→ 返回LED1:ON,LED2:OFF,...为了更直观可以用Python写个测试脚本import serial import time ser serial.Serial(COM3, 115200, timeout1) def send_cmd(cmd): ser.write((cmd \n).encode()) print(ser.readline().decode().strip()) send_cmd(LED1_ON) time.sleep(1) send_cmd(ALL_BLINK) time.sleep(2) send_cmd(STATUS?)这个项目最让我自豪的是指令系统的可扩展性——新增LED或功能只需修改指令表和状态机核心逻辑不用动。后来客户要求增加PWM调光功能我只用了半小时就实现了。
RELATED

相关推荐

08-LCD1602驱动实战:从时序解析到自定义字符显示

08-LCD1602驱动实战:从时序解析到自定义字符显示

1. LCD1602基础认知与硬件解析第一次接触LCD1602时,我盯着这个巴掌大的屏幕想了半天——这玩意儿怎么就能显示两行字符呢?后来拆开看才发现,它内部藏着个精密的点阵世界。LCD1602本质上是个16列2行的字符型液晶显示器,每个字符位置…

📅 2026/9/13 0:20:05
从赛题到实战:剖析三端口DC-DC变换器的双模式能量管理策略

从赛题到实战:剖析三端口DC-DC变换器的双模式能量管理策略

1. 三端口DC-DC变换器的设计挑战与工程价值在新能源和智能硬件快速发展的今天,高效能量管理成为技术突破的关键。2021年全国大学生电子设计竞赛的C题——三端口DC-DC变换器,正是对这一技术痛点的精准捕捉。这个看似专业的赛题,实际上解决的是…

📅 2026/8/24 2:34:13
QQ截图独立版:5个隐藏功能让你的Windows截图效率提升300%

QQ截图独立版:5个隐藏功能让你的Windows截图效率提升300%

QQ截图独立版:5个隐藏功能让你的Windows截图效率提升300% 【免费下载链接】QQScreenShot 电脑QQ截图工具提取版,支持文字提取、图片识别、截长图、qq录屏。默认截图文件名为ScreenShot日期 项目地址: https://gitcode.com/gh_mirrors/qq/QQScreenShot 还在为…

📅 2026/8/24 2:34:13
MORE NEWS

更多资讯

📰

物联网安防系统架构解析:从感知层到平台层的全链路实践

1. 安博会现场:物联网正在改写“安防”的传统定义济南数字安博会办到第25届,规模和气场都跟前几年不太一样。这次一二三物联网的展台没有堆砌产品样本,而是把物联感知、数据传输、平台应用三层串成了一条完整链路,现场大屏上告警弹…

📰

现在实用的一键生成论文工具有哪些品牌?分享我的实测感受

每到期末、毕业答辩、课题申报阶段,很多学生都会陷入论文写作的困境:选题毫无头绪、大纲搭建逻辑混乱、正文撰写耗时长、参考文献格式出错、查重重复率偏高、AIGC检测告警、本校论文排版标准复杂。纯人工从零开始撰写、反复修改格式和降重,往…

📰

个人网页作业完整指南:HTML+CSS+JavaScript从架构到交互

简介:这是一份面向Web前端初学者的个人网页设计作业源码包,采用HTMLCSSJavaScript实现,涵盖个人主页、个人博客、轮播相册、魔方相册、视频主页、收藏、日志与图片展示等典型页面,可帮助学习者系统练习多页面布局、交互事件绑定、…

📰

写开题报告怕内容水、文献假、格式乱?毕业之家一键智能生成

关于 毕业之家 品牌:毕业之家产品资料 毕业之家官方网站:www.biye.com。一键智能生成论文开题报告,生成内容时参考真实参考文献,文献真实性真实可查,精准标注文章引用,文献信息、论文年份、作者、观点转述都…

📰

单神经元自适应PID:Hedd学习规则与Simulink仿真实践

简介:单神经元自适应PID有监督Hedd仿真资料包,面向自动控制、智能算法方向的研究者与工程师,聚焦传统PID在非线性、时变系统下参数整定困难的问题,利用单神经元网络实现增益在线自整定,并通过有监督方式优化权重更新。…

📰

Mastra Agent 接入 MCP(Model Context Protocol):从概念到实战配置指南

Mastra Agent 接入 MCP(Model Context Protocol):从概念到实战配置指南 【免费下载链接】mastra Mastra is the modern TypeScript framework for AI-powered applications and agents. 项目地址: https://gitcode.com/GitHub_Trending/ma/…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬