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。