本文主要是介绍普冉(PUYA)单片机开发笔记(12): 获取外部中断,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
概述
将单片机的 GPIO 引脚作为外部按键的输入端是单片机较为常用的方式,例如把这颗 MCU 部署在一块控制面板的触点底板,使用者按压按钮(按键)对产品进行控制。本着学以致用的原则,使用 PY32F003 对外部中断如何处理是一项必须完成的学习内容了。今天我们就来操练一把。
参考厂家的例程,使用 PA12 作为外部中断的输入管脚,掌握一下 PY32F003 对外部中断处理的代码。PA12 设置为突变检测,当 PA12 上产生高低电平的变化时,翻转一次板载 LED 可以验证 MCU 是否正确捕捉了外部中断。
在我的这一个系列的实验,Keil 的文件组织都是沿用下来的,请参见我的任意一期《开发笔记》,这里就不罗嗦了,直接上代码。
实现代码
1. 在 main.h 中加一个预定义,然后定义和外部中断相关的函数原型
代码片段如下。
#define TIM_PWM_TEST 0
#define ADC_SAMPLE_TEST 0
#define FLASH_WR_TEST 0
#define I2C_COMM_TEST 0
#define I2C_SLAVE 0
#define EXTI_TEST 1...
...#if(EXTI_TEST)
void EXTI_Config(void);
void EXTI_Demo(void);
#endif...
...
文件新定义了预编译开关: EXTI_TEST,其它的开关全部设置为 0(关掉其它功能,免得产生冲突)。然后声明了 Config 和 Demo 两个函数。
2. app_exti.c 中实现相关函数
这一次我们将获取外部中断的相关函数都写到 app_exti.c 这一个文件中,包括 main.h 中预定义的 EXTI_Config() 函数,HAL_EXTI_MspInit() 函数和 EXTI4_15_IRQHandler() 函数,酱紫就不需要再“麻烦” 去修改 py32_f0xx_hal_msp.c 文件了。
完整代码如下。
/********************************************************************************* @file app_exti.c* @brief External Interrupt test functions.******************************************************************************* @copyright** Copyright (c) 2023 CuteModem Intelligence.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/#include "main.h"#if(EXTI_TEST)
/** ----------------------------------------------------------------------------
* @name : void EXTI_Config(void)
* @brief : EXTI 初始化, 配置引脚 PA12 为下降沿中断
* @param :
* @retval : void
* @remark :
*** ----------------------------------------------------------------------------
*/
void EXTI_Config(void)
{GPIO_InitTypeDef GPIO_InitStruct;__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; // 下降沿中断GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 速度为高速GPIO_InitStruct.Pin = GPIO_PIN_12;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);HAL_NVIC_EnableIRQ(EXTI4_15_IRQn); // 使能EXTI中断HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0); // 配置中断优先级
}/** ----------------------------------------------------------------------------
* @name : void EXTI4_15_IRQHandler(void)
* @brief : EXTI 初始化, 配置事件引脚 PA12
* @param : 每产生一次下降沿, LED翻转一次
* @retval : void
* @remark :
*** ----------------------------------------------------------------------------
*/
void EXTI4_15_IRQHandler(void)
{BSP_LED_Toggle(LED3);HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);//处理EXTI中断请求
}/** ----------------------------------------------------------------------------
* @name : void EXTI_Demo(void);
* @brief : 由 main() 调用的外部中断实验程序
* @param :
* @retval : void
* @remark :
*** ----------------------------------------------------------------------------
*/
void EXTI_Demo(void)
{EXTI_Config();
}#endif
- 使用 EXTI_Config() 函数分配 PA12 为外部中断源,内部上拉,下降沿中断,GPIO 高速。
- 使用 EXTI4_15 中断,设置成 0 组最高优先级。
- 在 EXT4_15中断服务程序中,翻转板载 LED 一次,然后调用 HAL_GPIO_EXTI_IRQHandler(GPIO_Pinx) 函数清除这个 GPIO 的中断标志,以便下一次捕获。
- 定义了一个非常简单的 Demo 函数。
3. 修改一下 py32_f0xx_hal_it.c
已经在 app_exti.c 中实现了 EXTI_15_IRQ4_Handler,所以在 py32_f0xx_hal_it.c 中把那个函数关掉。
请注意这里不能重复定义其为 __weak 类型,这么做不会导致编译错误,但程序运行时会卡死。
/********************************************************************************* @file py32f0xx_it.c* @author MCU Application Team* @Version V1.0.0* @Date 2020-10-19* @brief Interrupt Service Routines.*******************************************************************************/...
...#if(!EXTI_TEST)
void EXTI4_15_IRQHandler(void)
{
}
#endif...
...
4. 在 main() 函数中调用
/********************************************************************************* @file main.c* @brief Main program entry.******************************************************************************...
...********************************************************************************/#include "main.h"
#include <stdio.h>/**
* -------------------------------------------------------------------------
* @file : int main(void)
* @brief : main函数
* @param : 无
* @retval : 无限循环,无返回值
* @remark :
* -------------------------------------------------------------------------
*/
int main(void)
{HAL_Init(); // systick初始化SystemClock_Config(); // 配置系统时钟if(USART_Config() != HAL_OK) Error_Handler(); printf("\r\n\r\n\r\n""[SYS_INIT] Debug port initilaized.\r\n");printf("\r\n+---------------------------------------+""\r\n| PY32F003 MCU is ready. |""\r\n+---------------------------------------+""\r\n 10 digits sent to you! ""\r\n+---------------------------------------+""\r\n");HAL_Delay(0);if (DBG_UART_Start() != HAL_OK) Error_Handler();HAL_Delay(0);#if(EXTI_TEST)EXTI_Config();
#endifwhile (1){
#if(!EXTI_TEST)BSP_LED_Toggle(LED3);HAL_Delay(500);
#endif}
}
程序很短,如果不考虑打印的话,只需要 HAL_Init(); SystemClock_Config(); 和 EXTI_Config(); 三个函数。主循环用 #if(!EXTI_TEST)关掉了,实际上是空的。
实验结果
编译烧录后,使用一根杜邦线连接 PA12 引脚,杜邦线的另一头接上 GND,反复插拔,观察板载 LED 的明灭。可以发现板载 LED 随着杜邦线的插拔一明一灭,说明实验是成功了的。
总结
- 使用 PY32F003 的外部中断功能的配置很简单。
- 如果使用 GPIO 的高速模式,对捕获外部中断有好处,但要避免插拔抖动造成的多次触发。实测使用 GPIO_SPEED_FREQ_VERY_HIGH 时,一次接触会产生 LED 的多次明灭;使用 GPIO_SPEED_FREQ_MEDIUM 时,好像又有点丢失的感觉。在实用设计中,在使用 HIGH 或者 VERY_HIGH 的同时,应该加一套时间常数较为合适的 RC 低通电路用于防抖。
本实验只是完成了一个管脚作为外部中断源的捕获,如果有多个的话,想来可能大同小异吧,毕竟芯片的 NVIC 构架是相同的。
谬误之处,欢迎在评论区讨论指正。
这篇关于普冉(PUYA)单片机开发笔记(12): 获取外部中断的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!