cube gpio中断_STM32CubeMX学习笔记2:GPIO按键外部中断控制LED状态

本文介绍了使用STM32F103ZET6和STM32CubeMX配置GPIO中断,通过按键改变LED状态的方法。详细步骤包括设置时钟、GPIO模式、中断配置以及代码分析与改写,特别提到了消抖处理和中断服务函数的实现。
摘要由CSDN通过智能技术生成

MCU:STM32F103ZET6

IDE:  MDK-ARM V5 +STM32CubeMX5.0.0

本次实现的功能是通过按键的外部中断,来改变对应LED的状态,需要将按键的I/O端口映射到外部中断线上。

需要初始化的按键I/O口分别对应PA0PE2PE3PE4,LEDI/O口分别为PC0PC1PC2PC3PC4。

一. 在 Pinout&Configuration---System Core中:

1. 首先设置时钟RCC的HSE(外部高速时钟)为晶振模式:Crystal/ceramic Resonator

2. 设置系统SYS的Debug为Serial Wire:

3. 设置GPIO中的LED管脚。

根据MCU的硬件原理图可以看出LED均是低电平触发,且对应的端口为PC0-PC7,因此在使能是应开启GPIOC端口。

在MCU管脚图中找到PC0-PC4管脚,右键将管脚设置为GPIO_Output输出模式。

此时在System Core的GPIO中,会出现对应端口,点击端口将GPIO output level设置为low,将User Label定义为LED。

4. 设置按键映射到外部中断线上。

选择PA0的端口为GPIO_EXTI0,PE2PE3PE4的端口依次为GPIO_EXTI234。

此时在System Core的GPIO中,会出现对应I/O端口,按键部分的硬件原理图:

KEY_UP应为上升沿触发,并外接下拉电阻,点击端口将GPIO mode设置为External Interrupt Mode with Rising edge trigger detection,将GPIO Pull-up/Pull-down配置为Pull-down,将User Label定义为KEY_UP。

K1K2K3应为下降沿触发,点击端口将GPIO mode设置为External Interrupt Mode with Falling edge trigger detection,将User Label定义为KEY_LEFTKEY_DOWNKEY_RIGHT。

接着在GPIO-Configuration中使能四个GPIO的中断:

*在将端口映射到EXTI线上后,SYS会出现以下警告:表示红色部分的模式不可使用,且因为PA0本身对应的是系统唤醒功能,因此System Wake-UP的功能也无法被选中。

二.在 Clock Configuration中:

配置时钟为72 Mhz。

三.在 Project Manager---Project中:

1.设置项目的名称以及保存的位置,选择Toolchain/IDE为MDK-ARM V5,

Tips:最好把Linker Settings中的Minimum Heap Size设置为0x600。

2.在Code Generator选项中如下勾选:

最后点Generate Code生成代码,并选择“Open Project”:

四.代码分析与改写:

在生成的stm32f1xx_it.c中是系统中断的相关函数,找到四个外部中断的中断服务函数:

void EXTI0_IRQHandler(void)

{

/* USER CODE BEGIN EXTI0_IRQn 0 */

/* USER CODE END EXTI0_IRQn 0 */

HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

/* USER CODE BEGIN EXTI0_IRQn 1 */

/* USER CODE END EXTI0_IRQn 1 */

}

进入“HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0)”函数后发现定义如下:

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)

{

/* EXTI line interrupt detected */

if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)

{

__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);

HAL_GPIO_EXTI_Callback(GPIO_Pin);

}

}

服务函数中第一步对中断口清零,随后进入回调函数“HAL_GPIO_EXTI_Callback”:

__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符号弱定义,(库中定义的弱符号可以被用户定义的强符号覆盖,从而使程序可以使用自定义版本的库函数)但是回调函数中没有定义任何操作,因此将我们要实现的功能编写在回调函数中。

*关于强弱符号的详细定义见:强符号 弱符号。

在main.c中添加下列程序:

/* USER CODE BEGIN 4 */

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

if(GPIO_Pin==KEY_UP_Pin)

{

for(long i = 1;i<72000;i++){}; //消除抖动

if(HAL_GPIO_ReadPin(KEY_UP_GPIO_Port,KEY_UP_Pin)==1)

{

HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);

}

}

else if(GPIO_Pin==KEY_DOWN_Pin)

{

for(long i = 1;i<72000;i++){};

if(HAL_GPIO_ReadPin(KEY_DOWN_GPIO_Port,KEY_DOWN_Pin)==0)

{

HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);

}

}

else if(GPIO_Pin==KEY_LEFT_Pin)

{

for(long i = 1;i<72000;i++){};

if(HAL_GPIO_ReadPin(KEY_LEFT_GPIO_Port,KEY_LEFT_Pin)==0)

{

HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);

}

}

else if(GPIO_Pin==KEY_RIGHT_Pin)

{

for(long i = 1;i<72000;i++){};

if(HAL_GPIO_ReadPin(KEY_RIGHT_GPIO_Port,KEY_RIGHT_Pin)==0)

{

HAL_GPIO_TogglePin(LED4_GPIO_Port,LED4_Pin);

}

}

__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);

}

/* USER CODE END 4 */

在编程中一般不在中断函数中添加延时函数,(这里有个BUG:当PA0按下时,只要进入HAL_delay函数就无法跳出循环,解决未果,因此用上面的for循环代替了延时函数,实现消抖的功能)。

以KEY_UP按下为例:当KEY_UP按键按下后,

“GPIO_Pin==KEY_UP_Pin”

进入for循环(相当于小型的延时函数),循环一段时间后判断KEY_UP管脚是否仍未高电平:

“HAL_GPIO_ReadPin(KEY_UP_GPIO_Port,KEY_UP_Pin)==1”

这里因为UP管脚是高电平触发,其余管脚是低电平触发,因此判断条件不同。

若此时KEY_UP仍为高电平,说明不是抖动引起,则改变对应LED的状态:

“HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin)”

最终在退出函数时要清除中断标志位,避免对下次按键的判断造成影响。

至此,编译后无错并下载到开发板中,就完成了通过STM32CubeMX调用HAL库实现按键控制LED的效果程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值