attributeerror: __exit___STM32Cube05 | 使用EXIT检测按键

c6e5948f67fd4788b14c12cdf243e826.png更多精彩~点击上面“蓝字”关注我们呀  67fe9a70b2e74ac670204e17ff86974a.png

寻求更好的阅读体验,请点击阅读原文移步:Mculover666的个人博客。

1. 准备工作

硬件准备

首先需要准备一个开发板,这里我准备的是STM32L4的开发板(BearPi):

816ce33e4ddcc2c0aeb7332ad950b56c.png

软件准备

需要安装好Keil - MDK及芯片对应的包,以便编译和下载生成的代码。

2.生成MDK工程

选择芯片型号

打开STM32CubeMX,打开MCU选择器:

1ba1312c1711c2aff7dcc6d298694c10.png

搜索并选中芯片STM32L431RCT6:
b296b2133eacd23aaa55843eefee20ab.png

配置时钟源

  • 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC;

  • 如果使用默认内部时钟(HSI),这一步可以略过;

这里我都使用外部时钟:

b702df3668d3315b6381df585a88a58c.png

配置LED的GPIO引脚

查看小熊派开发板的原理图,如下:

0306f688d4f21638703dc43079cd03ab.png
mark

所以接下来我们选择配置PC13引脚:

0338706bb87113fc10175757a27334dd.png
mark

设置用户标签为LED:

4a91216295866bfbf9ed5c11c5ba63a7.png
mark

配置GPIO引脚为外部中断引脚

在原理图上如下:

760bfe7626424b91fbcd19afabb2554f.png
=

所以接下来我们选择配置PB2引脚和PB3引脚为外部中断触发引脚
c25b0c1b92d893e0e08d12bf59790915.png

因为没有设置硬件上拉,所以我们配置开启上拉电阻,并设置用户标签为KEY1KEY2,接下来是最重要的一步:

  • 开启下降沿触发中断:即在按下按键时电平由高变为低时触发

  • 开启上升沿触发中断:即在按下按键后松开时电平由低变为高时触发

  • 开启下降沿上升沿都触发中断:即在按下时触发,松开时再次触发

这里我选择开启下降沿触发中断:

62bf866b193dea612a3f62094db79401.png

配置NVIC设置中断优先级

知识小卡片 —— NVIC 

NVIC全称Nested vectored interrupt controller,即嵌套向量中断控制器,用来决定中断的优先级

NVIC在 ARM Conrtex-M 内核中,用一个 8 位的寄存器来配置,总共可以配置2c7fe8430890b7d5dfb2788617d45efe.png级中断,但是 ST 公司在生产 STM32 的时候,发现一个小小的单片机根本用不了这么多,纯属浪费,所以将该寄存器的低 4 位全部置0,只使用高 4 位来配置,这样一来 STM32 就只有 2^4=16 级中断啦。

简化为16级中断后,ST发现 STM32 内部这么丰富的外设,还是不方便配置,干脆人工给这4位来个分组,划分出了5个分组:

优先级分组抢占优先级占的位数子优先级占的位数
NVIC_PriorityGroup_00 bit4 bit
NVIC_PriorityGroup_11 bit3 bit
NVIC_PriorityGroup_22 bit2 bit
NVIC_PriorityGroup_33 bit1 bit
NVIC_PriorityGroup_44 bit0 bit

再次强调一下,这5种中断分组规则是人为的,用哪种规则,之后设置具体的优先级时对应就行,STM32默认使用的规则是 NVIC_PriorityGroup_0 。

STM32 的CPU判断优先级的方法如下:

  • 先判断抢占优先级,数字越小,优先级越高;

  • 若抢占优先级相同,判断子优先级,同样,数字越小,优先级越高;

对NVIC有没有了解呢?

接下来在STM32CubeMX中配置中断优先级:

配置优先级分组

这里我配置使用中断优先级分组规则 NVIC_PriorityGroup_2:

b551153ef2ba7b640519145e1687e311.png
mark
配置具体的优先级大小

根据中断优先级分组规则 NVIC_PriorityGroup_2来设置具体的优先级大小:

aca4a5b705acfa67e9dbc524003a4615.png
mark

配置时钟树

STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz即可:

f95f45ad68b24fc789bd95c161cafb54.png

生成工程设置

829bc9ce80c470b24edc68a7e15f0f31.png

代码生成设置

最后设置生成独立的初始化文件:

3f8b48ed0f0db136b66eb904010a28c6.png

生成代码

点击GENERATE CODE即可生成MDK-V5工程:

efe1a45dd3a15aaf5b2ef7f320bc02bd.png

3. 在MDK中编写、编译、下载用户代码

STM32 HAL库中断处理机制

先打开stm32l4xx_it.c文件:

729aeace9fcbb3551001fd2426a4b18b.png
mark

可以看到其中处理EXIT2和EXIT3中断都调用了同一个函数,但是EXIT2和EXIT3向该函数传入的参数不同:

HAL_GPIO_EXTI_IRQHandler();

那么,HAL库对于中断是如何处理的呢?我们打开 stm32l4xx_hal_gpio.c 文件,看一下该函数的原型,一探究竟:

/**
  * @brief  Handle EXTI interrupt request.
  * @param  GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
  * @retval None
  */
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin){
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

可以看到,在该函数中首先读取了一下中断寄存器,确认该中断是否发生,确认之后又调用了一个函数,并将接收到的参数 GPIO_Pin 继续传给该函数:

HAL_GPIO_EXTI_Callback(GPIO_Pin);

该函数称为EXIT中断的回调函数,用来处理所有发生的EXIT中断事件。

那么,这个函数又干了什么呢?接着探索哈哈哈~

同样在stm32l4xx_hal_gpio.c文件中找到该函数的原型:

/**
  * @brief  EXTI line detection callback.
  * @param  GPIO_Pin: Specifies the port pin connected to corresponding EXTI line.
  * @retval None
  */
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);

  /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */
}

哈哈哈,这下是不是非常清楚了~

该回调函数使用__weak进行了弱定义,所以用户可以再次定义该函数,并且这个note写的非常清楚:

这个函数不应该被改变,如果需要使用回调函数,请重新在用户文件中实现该函数。

自己实现EXIT中断处理回调函数

这个函数放在哪都行,为了方便,我们放在gpio.c的最后。

实现的基本思想是:

  • 因为所有的EXIT中断都会调用该函数,所以首先判断具体的中断事件;

  • 对该中断事件进行处理

实现代码如下:

/* USER CODE BEGIN 2 */
/**
 * @brief    EXIT中断回调函数
 * @param GPIO_Pin —— 触发中断的引脚
 * @retval    none
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    /* 判断哪个引脚触发了中断 */
    switch(GPIO_Pin)
    {
        case GPIO_PIN_2:
            /* 处理GPIO2发生的中断 */
            //点亮LED
            HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);
            break;
        case GPIO_PIN_3:
            /* 处理GPIO3发生的中断 */
            //熄灭LED
            HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);
            break;
        default:
            break;
    }
}
/* USER CODE END 2 */

然后编译整个工程:

67a96a15b4973be3794e8aab18731764.png

最后进行下载设置:
985d438febe47a6188c9b8e13c5bb5ad.png
b70b742069992f66dfb7047524513ebb.png

最后点击下载即可:
a45718180e95f4258af8c31285c13b1a.png

实验现象如下:
372c0f2e08aa802846a7313202f95f48.png

至此,我们已经学会了如何配置NVIC使用外部中断检测按键,并了解了NVIC和HAL库中断处理机制的一些基本知识,下一节讲述如何配置USART以及实现printf函数。

更多精彩文章及资源,请关注我的微信公众号:『mculover666』。

848e4428b9c817adc3efbfc45ce3702c.png
mark
09:18:14 **** Incremental Build of configuration Debug for project ov2640_AI **** make -j20 all arm-none-eabi-gcc "../Core/Src/main.c" -mcpu=cortex-m3 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F103xB -c -I../Core/Inc -I../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy -I../Drivers/STM32F1xx_HAL_Driver/Inc -I../Drivers/CMSIS/Device/ST/STM32F1xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/main.d" -MT"Core/Src/main.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/main.o" arm-none-eabi-gcc -o "ov2640_AI.elf" @"objects.list" -mcpu=cortex-m3 -T"C:\Users\l\STM32CubeIDE\workspace_1.19.0\ov2640_AI\STM32F103C8TX_FLASH.ld" --specs=nosys.specs -Wl,-Map="ov2640_AI.map" -Wl,--gc-sections -static --specs=nano.specs -mfloat-abi=soft -mthumb -Wl,--start-group -lc -lm -Wl,--end-group C:/ST/STM32CubeIDE_1.19.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.13.3.rel1.win32_1.0.0.202411081344/tools/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld.exe: ov2640_AI.elf section `.bss' will not fit in region `RAM' C:/ST/STM32CubeIDE_1.19.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.13.3.rel1.win32_1.0.0.202411081344/tools/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld.exe: region `RAM' overflowed by 57984 bytes collect2.exe: error: ld returned 1 exit status make: *** [makefile:64: ov2640_AI.elf] Error 1 "make -j20 all" terminated with exit code 2. Build might be incomplete. 09:18:14 Build Failed. 3 errors, 0 warnings. (took 338ms)
最新发布
07-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值