STM32
直播中

陈杰

7年用户 1357经验值
私信 关注
[问答]

如何实现一个按键控制两个LED灯在两个状态下的自由切换?

如何实现一个按键控制两个LED灯在两个状态下的自由切换?

回帖(1)

卢兰凤

2021-11-18 15:19:59
本文说明

  项目功能
实现一个按键控制两个LED灯在两个状态下的自由切换
一个状态是跑马灯,另一个状态是双闪
  相关软件使用说明
STM32CubeMX+Keil+Proteus相关的安装、使用、配置等基础操作不再赘述,有关内容的详细介绍如下
STM32CubeMX+Keil5+Proteus实现按键控制LED灯(入门篇).
  外部中断介绍

  中断知识点

  

  • ARM Cortex M3内核支持256个中断,包括16个内核中断和240个外设中断,拥有256个中断优先级别
  • STM32的中断通道可能会由多个中断源共用,即表明某个中断服务函数可能被多个中断源共用。所以在中断服务函数的入口,需要有一个判断机制,来辨别究竟是哪个中断源触发了中断
  • STM32有两个优先级:抢占优先级响应优先级
  • Cortex M3内核里有一个设备叫做嵌套向量中断控制器(NVIC),它对中断进行统一的协调和控制。最主要的工作就是控制中断使能确定中断优先级

  STM32外部中断

  

  • 外部中断(EXTI)是STM32芯片实时处理外部事件的一种机制,由于中断请求来自于GPIO端口的引脚,所以称之为外部中断
  • STM32芯片有16个外部中断源EXTI0–EXTI15,分别对应7个中断服务函数,其中EXTI0–EXTI4是专用,其他为共用
  • EXTI0的连接引脚是:PA0–PG0,即每个端口的0号引脚
    EXTI1的连接引脚是:PA1–PG1,即每个端口的1号引脚,其他以此类推
  • 外部中断的触发条件包括上升沿触发下降沿触发

  基于STM32CubeMX的外部中断的程序设计思路

  

  • 在STM32CubeMX中指定引脚
  • 设置GPIO_EXTI
  • 设置中断触发条件
  • 使能NVIC通道
  • 重写该I/O引脚对应的中断回调函数

  前4步在STM32CubeMX里面点一点就可以配置,简单了好多!!!
  STM32CubeMX配置

  1.指定引脚
选择PA1,PA2引脚做为LED灯的输出引脚
选择PB0引脚做为按键输入的引脚
  2.将GPIO设置为GPIO_EXTI功能
右键PB0引脚,选择GPIO_EXTI0(PB0对应的连接引脚)
  
  

  

3.设置中断触发条件
在GPIO中配置PB0引脚的模式为外部中断且下降沿触发检测
同时设置上拉,标签名Key
选择的时候看看英文是否对应
  
  

  

PA1和PA2引脚设置默认输出低电平,无上拉/下拉,高速输出,标签的话设置LED1和LED2
  4.使能NVIC通道
在NVIC(内嵌向量中断控制器)中勾选"EXTI line0 interrupt",使能中断
  
  

  

接着设置晶振,配置时钟树,72MHz即可
最后输出生成项目代码。
  Keil编辑代码逻辑

  打开工程,我们看一下用户代码目录
由于在STM32CubeMX中设置了外部中断,所以多了一个stm32f1xx_it.c文件
  
  

  

进入文件,找到函数EXTI0_IRQHandler()
该函数的内部就是外部中断服务函数,右键选择“Go To Definition Of…"
  
  

  

可以看到这个函数if语句中又有两个函数
其中HAL_GPIO_EXTI_CLEAR_IT()的作用就是清除中断标志
  而我们需要关注的则是回调函数HAL_GPIO_EXTI_Callback()
它被定义为一个虚函数 __weak void HAL_GPIO_EXTI_Callback(… )
我们作为用户只需要调用重写这个虚函数即可
  
  

  

  找到main.c文件,粘贴我们的外部中断处理函数
注意要在主函数体外的"Private user code"下的
/* USER CODE BEGIN 0 /
/
USER CODE END 0 */
内写我们的代码,如下图所示
  
  

  


设置一个变量EXTI_SIGN记录外部中断的次数
每发生一次外部中断该变量+1


int EXTI_SIGN = 0;                             //外部中断标志


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //外部中断回调函数
{
        EXTI_SIGN++;
}


然后我们通过判断变量EXTI_SIGN的奇偶性来切换LED灯的状态
具体代码写在主函数内的循环体while(1)内,代码如下


  while (1)
  {
                //程序功能:利用外部中断来实现按键控制LED灯在两个状态(跑马灯和双闪)之间的切换
                if(EXTI_SIGN%2 == 0)
                {
                        HAL_GPIO_WritePin(GPIOA,LED1_Pin,GPIO_PIN_RESET);
                        HAL_GPIO_WritePin(GPIOA,LED2_Pin,GPIO_PIN_RESET);
                        HAL_Delay(100);
                        HAL_GPIO_WritePin(GPIOA,LED1_Pin,GPIO_PIN_SET);
                        HAL_GPIO_WritePin(GPIOA,LED2_Pin,GPIO_PIN_SET);
                        HAL_Delay(100);                       
                }
                else if(EXTI_SIGN%2 == 1)
                {
                        HAL_GPIO_WritePin(GPIOA,LED1_Pin,GPIO_PIN_SET);
                        HAL_GPIO_WritePin(GPIOA,LED2_Pin,GPIO_PIN_RESET);
                        HAL_Delay(100);
                        HAL_GPIO_WritePin(GPIOA,LED1_Pin,GPIO_PIN_RESET);
                        HAL_GPIO_WritePin(GPIOA,LED2_Pin,GPIO_PIN_SET);
                        HAL_Delay(100);                       
                }
    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */
  }


最后编译生成hex文件即可拿来仿真了
  Proteus仿真

  原理图如下
  
  

  

  别忘记点击芯片选择hex文件,同时配置主频72MHz
  
  

  

点击左下角,仿真运行即可验证结果,这里就不展示了
  总结

  主要学习了外部中断的原理,然后用一个具体项目来实现外部中断
  我是爱学习的诸葛铁锤,觉得有用的话点个赞哈,啾咪
举报

更多回帖

发帖
×
20
完善资料,
赚取积分