STM32F103C8T6 定时器中断实战:4个独立按键+数码管实现交通灯3模式切换

📅 2026/7/10 10:18:30
STM32F103C8T6 定时器中断实战:4个独立按键+数码管实现交通灯3模式切换
STM32F103C8T6 定时器中断实战4个独立按键数码管实现交通灯3模式切换1. 项目概述与设计思路在嵌入式系统开发中定时器中断和状态机设计是两个核心概念。本项目基于STM32F103C8T6最小系统板通过三个定时器中断显示刷新、秒计时、按键扫描协同工作配合四位数码管和四个独立按键实现了一个具备三种工作模式的交通灯控制系统。系统核心架构采用分层设计硬件驱动层处理GPIO、定时器、数码管等底层外设中断服务层实现定时触发的关键任务业务逻辑层管理状态转换和模式切换人机交互层处理按键输入和显示输出这种架构设计使得系统各模块耦合度低便于后期功能扩展和维护。相比传统的51单片机方案STM32的丰富外设资源和更高性能为复杂状态管理提供了硬件基础。2. 硬件设计与关键外设配置2.1 核心硬件选型硬件模块型号/参数功能说明主控MCUSTM32F103C8T672MHz主频3个通用定时器数码管显示4位共阴数码管显示倒计时TM1650驱动按键输入4路轻触开关模式切换/参数调整交通指示灯红/黄/绿LED各2组模拟十字路口信号灯电源管理AMS1117-3.3V提供稳定3.3V系统电压2.2 定时器资源配置// 定时器2配置 - 显示刷新(1ms) TIM_TimeBaseInitTypeDef TIM2_Init; TIM2_Init.TIM_Period 1000-1; // 1kHz刷新率 TIM2_Init.TIM_Prescaler 72-1; // 72MHz/721MHz TIM2_Init.TIM_ClockDivision 0; TIM2_Init.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM2_Init); // 定时器3配置 - 秒计时(1s) TIM_TimeBaseInitTypeDef TIM3_Init; TIM3_Init.TIM_Period 1000-1; // 1s中断 TIM3_Init.TIM_Prescaler 72000-1; // 72MHz/720001kHz TIM_TimeBaseInit(TIM3, TIM3_Init); // 定时器4配置 - 按键扫描(20ms消抖) TIM_TimeBaseInitTypeDef TIM4_Init; TIM4_Init.TIM_Period 200-1; // 50Hz采样 TIM4_Init.TIM_Prescaler 7200-1; // 72MHz/720010kHz TIM_TimeBaseInit(TIM4, TIM4_Init);2.3 GPIO分配方案// 交通灯控制引脚 #define NS_RED GPIO_Pin_0 // PA0 #define NS_YELLOW GPIO_Pin_1 // PA1 #define NS_GREEN GPIO_Pin_2 // PA2 #define EW_RED GPIO_Pin_3 // PA3 #define EW_YELLOW GPIO_Pin_4 // PA4 #define EW_GREEN GPIO_Pin_5 // PA5 // 按键输入引脚 #define KEY_MODE GPIO_Pin_6 // PB6 #define KEY_UP GPIO_Pin_7 // PB7 #define KEY_DOWN GPIO_Pin_8 // PB8 #define KEY_EMER GPIO_Pin_9 // PB93. 软件架构与核心算法3.1 状态机设计系统采用三层状态机架构管理交通灯行为顶层模式状态机普通模式固定时序循环设置模式调整绿灯时长紧急模式强制南北/东西通行中层灯态状态机红灯状态绿灯状态黄灯状态全红过渡状态底层显示状态机正常显示闪烁警告设置提示stateDiagram-v2 [*] -- NormalMode NormalMode -- SettingMode: 长按MODE键 NormalMode -- EmergencyMode: 按下EMER键 SettingMode -- NormalMode: 再次按MODE键 EmergencyMode -- NormalMode: 再次按EMER键 state NormalMode { [*] -- RedState RedState -- GreenState: 计时结束 GreenState -- YellowState: 最后5秒闪烁 YellowState -- RedState: 计时结束 }3.2 定时器中断服务例程TIM3秒中断处理逻辑void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_Update) ! RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 全局秒计数器递增 sysTick; // 根据当前模式处理计时逻辑 switch(currentMode) { case MODE_NORMAL: handleNormalMode(); break; case MODE_SETTING: handleSettingMode(); break; case MODE_EMERGENCY: handleEmergencyMode(); break; } } }按键消抖算法void TIM4_IRQHandler(void) { static uint8_t keyState[4] {0}; static uint16_t keyCnt[4] {0}; if(TIM_GetITStatus(TIM4, TIM_IT_Update) ! RESET) { TIM_ClearITPendingBit(TIM4, TIM_IT_Update); // 扫描4个按键 for(int i0; i4; i) { uint8_t currState GPIO_ReadInputDataBit(KEY_PORT, KEY_PINS[i]); // 状态机消抖 if(currState ! (keyState[i] 0x01)) { keyCnt[i]; if(keyCnt[i] DEBOUNCE_TIME) { keyState[i] (keyState[i] 1) | currState; keyCnt[i] 0; // 检测下降沿按键按下 if((keyState[i] 0x03) 0x02) { handleKeyPress(i); } } } else { keyCnt[i] 0; } } } }4. 三种工作模式实现细节4.1 普通模式标准交通灯时序南北绿灯30秒最后5秒闪烁南北黄灯3秒东西绿灯20秒最后5秒闪烁东西黄灯3秒void handleNormalMode(void) { static uint8_t phase 0; static uint16_t count 0; count; switch(phase) { case 0: // 南北绿灯东西红灯 if(count NS_GREEN_TIME) { phase 1; count 0; setLights(NS_YELLOW | EW_RED); } else if(count (NS_GREEN_TIME-5)) { // 最后5秒绿灯闪烁 toggleLight(NS_GREEN); } break; case 1: // 南北黄灯东西红灯 if(count YELLOW_TIME) { phase 2; count 0; setLights(NS_RED | EW_GREEN); } break; // 其他相位类似... } // 更新数码管显示 updateDisplay(count); }4.2 设置模式进入设置模式后数码管显示当前设置的绿灯时长通过UP/DOWN键以5秒为步长调整10-60秒范围再次按MODE键保存并退出关键代码片段void handleSettingMode(void) { static uint8_t blink 0; // 数码管闪烁提示 if((sysTick % 10) 0) { blink !blink; setDisplayBlink(blink); } // 处理按键调整 if(keyEvent KEY_UP) { greenTime 5; if(greenTime 60) greenTime 10; } else if(keyEvent KEY_DOWN) { greenTime - 5; if(greenTime 10) greenTime 60; } // 显示当前设置值 showNumber(greenTime); }4.3 紧急模式特殊处理逻辑强制所有方向红灯紧急停车或强制特定方向绿灯应急通行倒计时暂停蜂鸣器报警提示void handleEmergencyMode(void) { // 根据紧急类型设置灯态 if(emergencyType EMERGENCY_STOP) { setLights(NS_RED | EW_RED); } else if(emergencyType EMERGENCY_NS) { setLights(NS_GREEN | EW_RED); } else { setLights(NS_RED | EW_GREEN); } // 蜂鸣器报警 BUZZER_ON; delay_ms(100); BUZZER_OFF; }5. 关键问题与优化技巧5.1 定时器中断冲突处理当多个定时器中断同时发生时采用以下策略设置不同的中断优先级NVIC_InitStructure.NVIC_IRQChannel TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_Init(NVIC_InitStructure);中断服务函数尽量简短使用标志位在main循环中处理耗时任务5.2 数码管显示刷新优化采用动态扫描缓冲区机制uint8_t digitBuffer[4]; // 显示缓冲区 void TIM2_IRQHandler(void) { static uint8_t pos 0; if(TIM_GetITStatus(TIM2, TIM_IT_Update) ! RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 关闭所有位选 GPIO_ResetBits(DIGIT_PORT, DIGIT_PINS); // 设置段选数据 GPIO_Write(SEGMENT_PORT, digitData[digitBuffer[pos]]); // 打开当前位选 GPIO_SetBits(DIGIT_PORT, digitPins[pos]); // 更新扫描位置 pos (pos 1) % 4; } }5.3 低功耗设计考虑在无车辆时段自动进入节能模式动态调整显示亮度使用停机模式外部中断唤醒void enterLowPowerMode(void) { // 关闭非必要外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, DISABLE); // 配置唤醒源 EXTI_InitStructure.EXTI_Line EXTI_Line9; EXTI_InitStructure.EXTI_Mode EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger EXTI_Trigger_Rising; EXTI_Init(EXTI_InitStructure); // 进入停机模式 PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); // 唤醒后恢复时钟 SystemInit(); }6. 扩展功能与进阶设计6.1 车流量检测扩展通过红外对管或地磁传感器检测车辆void TIM5_IRQHandler(void) { // 输入捕获定时器 if(TIM_GetITStatus(TIM5, TIM_IT_CC1) ! RESET) { vehicleCount; TIM_ClearITPendingBit(TIM5, TIM_IT_CC1); } }6.2 无线通信模块集成添加ESP8266实现远程监控void sendTrafficStatus(void) { char buffer[128]; sprintf(buffer, NS:%d/%d EW:%d/%d, nsGreenTime, nsCount, ewGreenTime, ewCount); ESP8266_Send(buffer); }6.3 上位机配置界面使用Qt开发配置工具# Python示例 - 串口配置工具 import serial import tkinter as tk def send_config(): ser serial.Serial(port_entry.get(), 115200) ser.write(fCONFIG,{ns_time.get()},{ew_time.get()}\r\n) ser.close() root tk.Tk() tk.Label(root, textNS绿灯时间:).pack() ns_time tk.Scale(root, from_10, to60) ns_time.pack() tk.Label(root, textEW绿灯时间:).pack() ew_time tk.Scale(root, from_10, to60) ew_time.pack() tk.Button(root, text发送配置, commandsend_config).pack() root.mainloop()7. 项目验证与测试方法7.1 单元测试策略定时器精度测试void testTimerAccuracy(void) { uint32_t start sysTick; delay_ms(1000); uint32_t end sysTick; printf(实际计时:%dms, 误差:%dms\n, end-start, (end-start)-1000); }状态机转换测试void testStateTransition(void) { setMode(MODE_NORMAL); simulateKeyPress(KEY_MODE); assert(currentMode MODE_SETTING); }7.2 系统集成测试方案正常模式压力测试连续运行24小时验证稳定性记录状态切换次数和时序准确性紧急模式响应测试随机触发紧急事件测量从触发到完全响应的延迟边界条件测试// 测试最小/最大绿灯时间设置 setGreenTime(10); // 最小值 setGreenTime(60); // 最大值7.3 性能优化建议使用DMA传输数码管数据将频繁访问的变量定义为register类型关键代码段使用内联汇编优化// 使用DMA更新数码管显示 void initDisplayDMA(void) { DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)GPIOB-ODR; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)digitBuffer; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize 4; DMA_Init(DMA1_Channel1, DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); }