☰
STM32F103C8T6 HAL 库按键中断控制流水灯
2026/9/30 5:22:07 网站建设 项目流程

STM32F103C8T6 HAL 库按键中断控制流水灯实验报告

文章目录

  • STM32F103C8T6 HAL 库按键中断控制流水灯实验报告
    • 一、实验目的
    • 二、实验任务
    • 三、实验环境与器件
      • 3.1 软件环境
      • 3.2 硬件器件
    • 四、硬件连接
    • 五、实验原理
      • 5.1 GPIO 输出控制
      • 5.2 按键外部中断
      • 5.3 按键消抖
      • 5.4 流水灯计时
      • 5.5 暂停与继续
    • 六、关键程序代码
      • 6.1 系统时钟配置
      • 6.2 GPIO 和外部中断初始化
      • 6.3 按键中断回调
      • 6.4 主循环
    • 七、实验结果

一、实验目的

  1. 掌握 STM32F103C8T6 的 GPIO 推挽输出配置方法。
  2. 掌握 HAL 库中 GPIO 初始化、输出控制和延时计时函数的使用。
  3. 掌握外部中断 EXTI、NVIC 和中断回调函数的基本工作原理。
  4. 使用 PB1 按键外部中断控制流水灯的暂停和继续。

二、实验任务

在前面流水灯实验的基础上,使用 STM32 HAL 库和按键外部中断,实现以下功能:

  • PA0、PA3、PC13 三只 LED 轮流点亮;
  • 每只 LED 点亮时间约为 1 秒;
  • 按下 PB1 按键后,流水灯暂停并保持当前 LED 状态;
  • 再次按下 PB1 按键后,流水灯继续运行。

本实验采用按键下降沿中断方式,不在主循环中不断查询按键状态。

三、实验环境与器件

3.1 软件环境

  • Keil µVision5;
  • ARMCC V5.06 编译器;
  • STM32CubeF1 HAL 库;
  • Keil.STM32F1xx_DFP 器件支持包;
  • ST-Link 下载器。

3.2 硬件器件

  • STM32F103C8T6 最小系统核心板一块;
  • LED 两只;
  • 330 Ω~1 kΩ 限流电阻两只;
  • 按键一个;
  • 面包板和杜邦线若干;
  • ST-Link 下载器一个。

四、硬件连接

功能STM32 引脚接线方式有效电平
LED1PA0PA0 → 限流电阻 → LED → GND高电平点亮
LED2PA3PA3 → 限流电阻 → LED → GND高电平点亮
板载 LEDPC13核心板内部已连接 LED低电平点亮
按键PB1PB1 → 按键 → GND低电平有效

PB1 使用 GPIO 内部上拉。按键没有按下时,PB1 为高电平;按键按下时,PB1 被拉低,因此产生下降沿。

PC13 板载 LED 的驱动电平与普通外接 LED 相反,PC13 输出低电平时 LED 点亮,输出高电平时 LED 熄灭。

五、实验原理

5.1 GPIO 输出控制

将 PA0、PA3、PC13 配置为通用推挽输出,通过 HAL 库函数控制输出电平:

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);/* PA0 输出高电平 */HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);/* PA0 输出低电平 */HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);/* PC13 输出低电平 */HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);/* PC13 输出高电平 */

PA0 和 PA3 输出高电平时点亮,PC13 输出低电平时点亮。

5.2 按键外部中断

PB1 配置为下降沿触发中断:

GPIO_InitStruct.Pin=GPIO_PIN_1;GPIO_InitStruct.Mode=GPIO_MODE_IT_FALLING;GPIO_InitStruct.Pull=GPIO_PULLUP;HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);

PB1 对应 EXTI1 中断线,因此需要使能:

HAL_NVIC_SetPriority(EXTI1_IRQn,0U,0U);HAL_NVIC_EnableIRQ(EXTI1_IRQn);

当按键按下时,程序进入:

voidEXTI1_IRQHandler(void){HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);}

HAL_GPIO_EXTI_IRQHandler()会清除中断标志,并调用用户编写的回调函数:

voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin)

5.3 按键消抖

机械按键在按下和松开的瞬间会产生抖动,如果直接处理中断,可能被误认为按了很多次。

本实验没有在中断中使用HAL_Delay(),而是比较两次按键的时间:

if((now_tick-last_press_tick)>=200U)

只有在距离上一次有效按键超过 200 ms 时,才认为本次按键有效,并将key_event置为 1。

5.4 流水灯计时

程序在主循环中使用HAL_GetTick()判断时间,而不使用阻塞延时代码。

if((HAL_GetTick()-last_change_tick)>=1000U)

HAL_GetTick()返回当前系统启动后的毫秒数,时间差达到 1000 ms 时切换下一只 LED。

这样的写法不会长时间阻塞主程序,按键中断也可以及时响应。

5.5 暂停与继续

程序使用变量running表示运行状态:

  • running = 1:流水灯运行;
  • running = 0:流水灯暂停。

每次按下 PB1,中断回调置位key_event,主循环检测到事件后,将running取反:

running=(running==0U)?1U:0U;

当running == 0时,主循环不改变 LED 输出状态,因此当前 LED 保持点亮;再次按下 PB1 后,恢复流水灯切换。

六、关键程序代码

6.1 系统时钟配置

本实验使用内部 HSI 8 MHz,不依赖外部晶振。

staticvoidSystemClock_Config(void){RCC_OscInitTypeDef RCC_OscInitStruct={0};RCC_ClkInitTypeDef RCC_ClkInitStruct={0};RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState=RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue=RCC_HSICALIBRATION_DEFAULT;RCC_OscInitStruct.PLL.PLLState=RCC_PLL_NONE;if(HAL_RCC_OscConfig(&RCC_OscInitStruct)!=HAL_OK){Error_Handler();}RCC_ClkInitStruct.ClockType=RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource=RCC_SYSCLKSOURCE_HSI;RCC_ClkInitStruct.AHBCLKDivider=RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider=RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider=RCC_HCLK_DIV1;if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct,FLASH_LATENCY_0)!=HAL_OK){Error_Handler();}}

6.2 GPIO 和外部中断初始化

staticvoidMX_GPIO_Init(void){GPIO_InitTypeDef GPIO_InitStruct={0};__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_AFIO_CLK_ENABLE();/* 初始状态熄灭 LED */HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull=GPIO_NOPULL;GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.Pin=GPIO_PIN_0;HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.Pin=GPIO_PIN_3;HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.Pin=GPIO_PIN_13;HAL_GPIO_Init(GPIOC,&GPIO_InitStruct);/* PB1 按键下降沿中断 */GPIO_InitStruct.Pin=GPIO_PIN_1;GPIO_InitStruct.Mode=GPIO_MODE_IT_FALLING;GPIO_InitStruct.Pull=GPIO_PULLUP;HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);HAL_NVIC_SetPriority(EXTI1_IRQn,0U,0U);HAL_NVIC_EnableIRQ(EXTI1_IRQn);}

6.3 按键中断回调

voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin){staticuint32_tlast_press_tick=0U;uint32_tnow_tick;if(GPIO_Pin==GPIO_PIN_1){now_tick=HAL_GetTick();if((now_tick-last_press_tick)>=200U){last_press_tick=now_tick;key_event=1U;}}}

6.4 主循环

while(1){if(key_event!=0U){key_event=0U;running=(running==0U)?1U:0U;last_change_tick=HAL_GetTick();}if(running==0U){last_change_tick=HAL_GetTick();continue;}if((HAL_GetTick()-last_change_tick)>=1000U){last_change_tick=HAL_GetTick();HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);if(step==0U){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);}elseif(step==1U){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);}else{HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);}step++;if(step>=3U){step=0U;}}}

七、实验结果

受帧率问题,本gif动图并不能很好体现实验结果,详情请看视频内容

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询