1.STM32CubeMX配置如下:
这里GPIO mode一共有六种分别是:
(1)上升沿触发外部中断
(2)下降沿触发外部中断
(3)边沿触发外部中断
(4)上升沿触发外部事件
(5)下降沿触发外部事件
(6)边沿触发外部事件
2.CubeMX生成的代码:
/** Configure pins as* EXTI */
void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIO时钟GPIO_InitTypeDef GPIO_InitStruct = {
0};GPIO_InitStruct.Pin = DATA_433M_Pin;GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; //上升沿触发GPIO_InitStruct.Pull = GPIO_PULLDOWN; //下拉HAL_GPIO_Init(DATA_433M_GPIO_Port, &GPIO_InitStruct);HAL_NVIC_SetPriority(EXTI2_3_IRQn, 0, 0);//设置中断优先级HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);//使能外部中断
}/******************************************************************************/
/* STM32G0xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32g0xx.s). */
/******************************************************************************//*** @brief This function handles EXTI line 2 and line 3 interrupts.*/
void EXTI2_3_IRQHandler(void)
{
/* USER CODE BEGIN EXTI2_3_IRQn 0 *//* USER CODE END EXTI2_3_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);/* USER CODE BEGIN EXTI2_3_IRQn 1 *//* USER CODE END EXTI2_3_IRQn 1 */
}
3.分析外部中断过程
我们可以看见这个外部中断包含了GPIO_Pin_2和GPIO_Pin_3两个外部中断源,这两个脚都可以触发这个外部中断,如果我们想区分具体是2还是3脚的时候,或者需要区分上升沿做不同事情,那么就需要自己重构回调函数来区分,然后执行不同的任务。我们发现里面只有一个函数,打开看看如下:
/*** @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_RISING_IT(GPIO_Pin) != 0x00u){
__HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_Pin);HAL_GPIO_EXTI_Rising_Callback(GPIO_Pin);}if (__HAL_GPIO_EXTI_GET_FALLING_IT(GPIO_Pin) != 0x00u){
__HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_Pin);HAL_GPIO_EXTI_Falling_Callback(GPIO_Pin);}
}
可以发现里面里面一共两个大的判断,一个是上升沿,一个是下降沿。然后先清楚中断标志位,然后执行一个回调函数,这个回调函数是可以自己重构的,仔细看下这个回调函数:
/*** @brief EXTI line detection callback.* @param GPIO_Pin Specifies the port pin connected to corresponding EXTI line.* @retval None*/
__weak void HAL_GPIO_EXTI_Rising_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_Rising_Callback could be implemented in the user file*/
}
凡是前面带__weak
的我们都是可以再重构而不会报错的。
4.重构回调函数
//下降沿回调函数
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_2){
SEGGER_RTT_printf(0,"GPIO_Pin_2 Rising exti!\r\n");}else if(GPIO_Pin == GPIO_PIN_3){
SEGGER_RTT_printf(0,"GPIO_Pin_3 Rising exti!\r\n");}
}
//上升沿回调函数
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_2){
SEGGER_RTT_printf(0,"GPIO_Pin_2 Falling exti!\r\n");}else if(GPIO_Pin == GPIO_PIN_3){
SEGGER_RTT_printf(0,"GPIO_Pin_3 Falling exti!\r\n");}
}
5.调试结果
6.增加GPIO端口判断
1)解决办法:
进中断回调函数的时候通过if(HAL_GPIO_ReadPin(GPIOD,DATA_433M_Pin)==1)
读取对应引脚电平状态来区分
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_2){
if(HAL_GPIO_ReadPin(GPIOD,DATA_433M_Pin)==1) SEGGER_RTT_printf(0,"GPIO_Pin_2 Rising exti!\r\n");}else if(GPIO_Pin == GPIO_PIN_3){
SEGGER_RTT_printf(0,"GPIO_Pin_3 Rising exti!\r\n");}
}
2)实测如下:
第一个是if(HAL_GPIO_ReadPin(GPIOD,DATA_433M_Pin) == 1)
的结果,因为我们是上升沿,所以触发中断的时候肯定是个高电平,所以这个时候是可以正常打印RTT的。
第二个是if(HAL_GPIO_ReadPin(GPIOD,DATA_433M_Pin) == 0)
的结果,因为我们是上升沿,所以触发中断的时候肯定是个高电平,而我们条件是低电平才会正常打印,所以退出低功耗的时候没有看见RTT打印的log。