STM32CubeMX系列 | 外部中断

2023-03-20  

1. 外部中断简介

STM32F1的每个IO口都可以作为外部中断的中断输入,STM32F103的中断控制器支持19个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM32F103的19个外部中断为:

  • EXTI线0~15:对应外部IO口的输入中断

  • EXTI线16:连接到PVD输出

  • EXTI线17:连接到RTC闹钟事件

  • EXTI线18:连接到USB唤醒事件

  • EXTI线19:连接到以太网唤醒事件(互联网型产品)

STM32F103供IO口使用的中断线只有16个,但是IO口却远不止16个。下图为GPIO跟中断线的映射关系图

2. 硬件设计

用到的硬件资源有:

  • 指示灯D1、D2

  • 蜂鸣器BUZ

  • 4个按键:KEY_UP、K1、K2、K3

硬件连接原理图如下,注意K1、K2、K3是低电平有效的,而KEY_UP是高电平有效。因此K1、K2、K3应设置为上拉、下降沿触发中断,KEY_UP应设置为下拉、上升沿触发中断 STM32F103芯片单个IO口最大输出电流是25mA,而蜂鸣器的驱动电流是30mA左右,整个芯片的输出电流最大为150mA,如果在蜂鸣器上就消耗30mA,那么芯片的其他IO口及外设电流就比较拮据了,因此此处不会直接使用IO口驱动蜂鸣器,而是通过三极管把电流放大后再驱动蜂鸣器,这样IO口只需提供不到1mA的电流就可以控制蜂鸣器 本实验利用板载的4个按键,通过外部中断来控制板载的两个LED的亮灭和蜂鸣器。其中KEY_UP控制蜂鸣器;K1控制D1,按一次亮再按一次灭;K2控制D2,按一次亮再按一次灭;K3同时控制D1和D2,按一次它们的状态就翻转一次

3. 软件设计

3.1 STM32CubeMX设置

  • RCC设置外接HSE,时钟设置为72M

  • PC0和PC2设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

  • PB5设置为GPIO推挽输出、高速模式

  • PA0设置为下拉、上升沿触发,PE2/3/4设置为上拉、下降沿触发

  • 在NVIC(嵌套向量中断控制器)中,勾选EXIT Line0/2/3/4 interrupt,使能PA0和PE2/3/4中断。右边两个选项设置抢占优先级和响应优先级

  • 输入工程名,选择工程路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

3.2 MDK-ARM编程

  • 在gpio.c文件中可以看到PC0/PC1/PB5/PA0/PE2/PE3/PE4管脚的初始化函数

void MX_GPIO_Init(void){

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */

  __HAL_RCC_GPIOE_CLK_ENABLE();     //开启GPIOE时钟

  __HAL_RCC_GPIOC_CLK_ENABLE();     //开启GPIOC时钟

  __HAL_RCC_GPIOA_CLK_ENABLE();     //开启GPIOA时钟

  __HAL_RCC_GPIOB_CLK_ENABLE();     //开启GPIOB时钟

  /*Configure GPIO pin Output Level */

  HAL_GPIO_WritePin(GPIOC, LED1_Pin|LED2_Pin, GPIO_PIN_SET);    //LED1/LED2默认输出是电平为高电平

  /*Configure GPIO pin Output Level */

  HAL_GPIO_WritePin(BUZ_GPIO_Port, BUZ_Pin, GPIO_PIN_RESET);    //BUZ默认输出是电平为低电平    

  /*Configure GPIO pins : PE2 PE3 PE4 */

  GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4;       //PE2/PE3/PE4

  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;                  //下降沿触发

  GPIO_InitStruct.Pull = GPIO_PULLUP;                           //上拉

  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pins : PCPin PCPin */

  GPIO_InitStruct.Pin = LED1_Pin|LED2_Pin;                      //PC0/PC1

  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;                   //推挽输出

  GPIO_InitStruct.Pull = GPIO_PULLUP;                           //上拉

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;                 //高速

  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PA0 */

  GPIO_InitStruct.Pin = GPIO_PIN_0;                             //PA0

  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;                   //上升沿触发

  GPIO_InitStruct.Pull = GPIO_PULLDOWN;                         //下拉

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PtPin */

  GPIO_InitStruct.Pin = BUZ_Pin;                                //PB5

  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;                   //推挽输出

  GPIO_InitStruct.Pull = GPIO_NOPULL;                           //无上下拉

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;                 //高速

  HAL_GPIO_Init(BUZ_GPIO_Port, &GPIO_InitStruct);

}

找到弱符号中断回调函数原型,并在gpio.c中自定义该回调函数 __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){

    HAL_Delay(10);

    switch(GPIO_Pin){

        case GPIO_PIN_0:

            HAL_GPIO_WritePin(GPIOB,BUZ_Pin,GPIO_PIN_SET);

            HAL_Delay(300);

            HAL_GPIO_WritePin(GPIOB,BUZ_Pin,GPIO_PIN_RESET);

            HAL_Delay(300);

            break;

        case GPIO_PIN_2:

            HAL_GPIO_TogglePin(GPIOC,LED1_Pin);

            break;

        case GPIO_PIN_3:

            HAL_GPIO_TogglePin(GPIOC,LED2_Pin);

            break;

        case GPIO_PIN_4:

            HAL_GPIO_TogglePin(GPIOC,LED1_Pin);

            HAL_GPIO_TogglePin(GPIOC,LED2_Pin);

            break;

    }

}

4. 下载验证

编译无误后下载到开发板,按下KEY_UP蜂鸣器响一下;K1控制D1,按一次亮再按一次灭;K2控制D2,按一次亮再按一次灭;K3同时控制D1和D2,按一次它们的状态就翻转一次


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。