完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
MCU:STM32F103ZET6 IDE: MDK-ARM V5 +STM32CubeMX5.0.0 本次实现的功能是通过按键的外部中断,来改变对应LED的状态,需要将按键的I/O端口映射到外部中断线上。 需要初始化的按键I/O口分别对应PA0PE2PE3PE4,LEDI/O口分别为PC0PC1PC2PC3PC4。 一. 在 Pinout&Configuration---System Core中:
在MCU管脚图中找到PC0-PC4管脚,右键将管脚设置为GPIO_Output输出模式。 此时在System Core的GPIO中,会出现对应端口,点击端口将GPIO output level设置为low,将User Label定义为LED。
此时在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中:
最后点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的效果程序。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1781 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1085 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1680 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
732浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
596浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
559浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 12:09 , Processed in 0.524332 second(s), Total 75, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号