用STM32F103C8T6和串口通信,5分钟搞定一个简易红绿灯控制原型(附完整代码)

张开发
2026/4/20 15:03:11 15 分钟阅读

分享文章

用STM32F103C8T6和串口通信,5分钟搞定一个简易红绿灯控制原型(附完整代码)
用STM32F103C8T6实现串口控制红绿灯原型开发指南1. 项目概述与硬件准备红绿灯控制系统是嵌入式开发的经典入门项目能帮助初学者快速掌握GPIO控制和串口通信两大核心技能。我们选用STM32F103C8T6这款性价比极高的ARM Cortex-M3内核开发板它内置丰富的外设资源特别适合教学演示和小型原型开发。所需硬件清单STM32F103C8T6最小系统板蓝色PCB版USB转TTL串口模块推荐CH340G芯片红黄绿LED各两个共6个LED220Ω限流电阻6个面包板和杜邦线若干提示购买开发板时注意区分正版丝印清晰和山寨版可能存在USB接口问题。LED建议选择3mm直径的亮度适中且方便观察。2. 开发环境搭建2.1 软件工具链配置对于STM32开发我们推荐使用以下免费工具组合Keil MDK-ARM注册后即可获得32KB代码限制的免费版本ST-Link驱动用于程序烧录和调试串口调试助手推荐使用SSCOM或Putty安装步骤# ST-Link驱动安装示例Windows 1. 下载STSW-LINK009驱动包 2. 以管理员身份运行dpinst_amd64.exe 3. 连接开发板后应在设备管理器看到STMicroelectronics STLink dongle2.2 工程模板创建在Keil中新建工程的正确姿势选择Device为STM32F103C8添加启动文件startup_stm32f10x_md.s配置Target选项勾选Use MicroLIB简化串口打印设置ROM地址为0x8000000Size为64KB设置RAM地址为0x20000000Size为20KB3. 硬件电路设计3.1 LED连接方案采用共阳极接法通过STM32的GPIO输出低电平点亮LEDLED颜色GPIO引脚对应交通灯红色PA0南北方向黄色PA1南北方向绿色PA2南北方向红色PB0东西方向黄色PB1东西方向绿色PB2东西方向电路连接注意事项每个LED串联220Ω电阻防止过流开发板的3.3V电源作为共阳极端确保GND共地连接3.2 串口通信配置使用USART1与PC通信接线方式开发板引脚USB-TTL模块PA9(TX)RXPA10(RX)TXGNDGND配置参数115200波特率8数据位无校验1停止位4. 核心代码实现4.1 GPIO初始化void LED_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); // 配置PA0-PA2为推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // 配置PB0-PB2为推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; GPIO_Init(GPIOB, GPIO_InitStructure); // 初始状态全部熄灭 GPIO_SetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2); GPIO_SetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2); }4.2 串口初始化与中断配置void USART1_Init(void) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // 配置PA9为复用推挽输出(TX) 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); // 配置PA10为浮空输入(RX) GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); // USART参数配置 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_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure); // 使能接收中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 配置NVIC NVIC_InitStructure.NVIC_IRQChannel USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); USART_Cmd(USART1, ENABLE); }4.3 红绿灯状态机实现定义三种基本控制模式定时自动切换固定时间间隔循环串口指令控制通过PC发送命令切换紧急模式所有方向红灯typedef enum { MODE_AUTO, MODE_MANUAL, MODE_EMERGENCY } TrafficMode; void TrafficLight_Update(void) { static uint32_t lastTick 0; static uint8_t state 0; if(HAL_GetTick() - lastTick 1000) return; lastTick HAL_GetTick(); switch(currentMode) { case MODE_AUTO: // 状态自动切换逻辑 switch(state) { case 0: // 南北绿灯东西红灯 GPIO_ResetBits(GPIOA, GPIO_Pin_2); // 南北绿 GPIO_SetBits(GPIOA, GPIO_Pin_0); GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 东西红 GPIO_SetBits(GPIOB, GPIO_Pin_2); state 1; break; case 1: // 南北黄灯东西红灯 GPIO_SetBits(GPIOA, GPIO_Pin_2); GPIO_ResetBits(GPIOA, GPIO_Pin_1); // 南北黄 state 2; break; // 其他状态类似... } break; case MODE_EMERGENCY: // 全方向红灯 GPIO_ResetBits(GPIOA, GPIO_Pin_0); GPIO_ResetBits(GPIOB, GPIO_Pin_0); GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2); GPIO_SetBits(GPIOB, GPIO_Pin_1 | GPIO_Pin_2); break; } }5. 调试技巧与常见问题5.1 串口通信调试当串口无法正常工作时按以下步骤排查检查接线是否正确TX-RX交叉连接确认波特率设置一致测量TXD引脚是否有波形输出检查代码中USART时钟是否使能5.2 LED不亮的可能原因GPIO配置模式错误应为推挽输出限流电阻值过大导致亮度不足共阳/共阴接法混淆引脚复用功能未正确配置5.3 程序下载失败处理典型错误及解决方案错误现象可能原因解决方法No target connected驱动未安装或连接不稳定重新插拔ST-Link检查驱动Flash timeout复位电路异常按住复位键再点击下载Option bytes error读保护使能使用ST-Link Utility解除保护6. 项目扩展思路基础版本实现后可以考虑以下增强功能添加按键控制通过开发板上的用户按键切换模式OLED状态显示使用I2C接口的OLED屏显示当前状态无线控制通过蓝牙模块如HC-05实现手机控制车流量检测外接红外传感器统计车辆通过数量进阶开发建议// 示例使用PWM实现灯光渐亮渐灭效果 void LED_PWM_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置PA1为复用推挽输出(TIM2_CH2) GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // 定时器基础配置 TIM_TimeBaseStructure.TIM_Period 999; // 1kHz PWM TIM_TimeBaseStructure.TIM_Prescaler 71; // 72MHz/72 1MHz TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure); // PWM模式配置 TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 500; // 初始占空比50% TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC2Init(TIM2, TIM_OCInitStructure); TIM_Cmd(TIM2, ENABLE); }

更多文章