关于STM32_HAL库调试外部中断EXTI的问题(VSCode)

最近在使用STM32的HAL库尝试作1个极其简单的小实验:以外部中断激励引脚PC1,令引脚PC0-LED响应翻转…………但就是这么一个简单的实验,让我卡住了好久。下面来分析下这个实验和出现的问题:
板子的硬件原理图:
在这里插入图片描述
HAL库代码配置:

一、初始化LED_IO口,即void MX_GPIO_Init(void),记得要在头文件声明

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);

  /*Configure GPIO pin : PC0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

}

二、初始化按键_IO口,即void key_Init(void),下降沿触发EXTI中断,记得要在头文件声明

void key_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOC_CLK_ENABLE();
    
    /*Configure GPIO pin : PC1 */
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI1_IRQn);
}

三、在main.c中调用上述2个初始化函数MX_GPIO_Init();和key_Init();,记得包含有这2个函数的头文件

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  MX_GPIO_Init();
  key_Init();
  USART1_Init();

  while (1)
  {

  }
}

while(1)里面不用写东西,后面我们直接在中断回调callback函数编写中断服务

四、查看stm32f1xx_hal_gpio.c文件中的库函数

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)的作用是获取中断标志位和清除中断标志位、调用中断服务回调函数;__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)是弱函数,如果我们在其他的.c文件重新定义实现这个函数,则该位置函数无效。这2个函数我们无需理会,这里只是作个说明。

/**
  * @brief  This function handles EXTI interrupt request.
  * @param  GPIO_Pin: Specifies the pins connected EXTI line
  * @retval None
  */
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

/**
  * @brief  EXTI line detection callbacks.
  * @param  GPIO_Pin: Specifies the pins connected EXTI line
  * @retval None
  */
__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
   */
}

五、在stm32f1xx_it.c文件的后面手动加入下述中断响应函数

/**
 * @brief This function handles EXTI line0 interrupt.
 */
void EXTI1_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI1_IRQn 0 */

  /* USER CODE END EXTI1_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
  /* USER CODE BEGIN EXTI1_IRQn 1 */

  /* USER CODE END EXTI1_IRQn 1 */
}

六、编写中断服务函数

我们在按键key.c文件中实现void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)中断回调函数,

/**
 * @brief          exit callback function
 * @param[in]      GPIO_Pin:gpio pin
 * @retval         none
 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    //if (GPIO_Pin == GPIO_PIN_1)
    //{
    //    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0);
    //}


    while (GPIO_Pin == GPIO_PIN_1)
    {
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0);
    }


    // do
    // {
    //     HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0);
    // } while (GPIO_Pin == GPIO_PIN_1);
}

在这里问题出现了,如下图所示,我一开始用的while (GPIO_Pin == GPIO_PIN_1)来判断中断响应引脚,把程序下到MCU中,发现按键怎么按下都没有翻转LED,代码检查了一遍又一遍,还是未检查出问题,后面改成if (GPIO_Pin == GPIO_PIN_1)之后,按键就能翻转LED了……啊这……按照我的理解,if和while不都是能判断条件的吗?于是我再改成do{ }while形式去判断,果然也不行,为啥只有if起作用呢,为啥?
在这里插入图片描述
知其然,不知其所以然。那能怎么办呢,去请教网上的大佬看看ifwhile的具体用法呗,搜索中…………出现答案。
在这里插入图片描述
哦,意思就是if不会等你,它只会过一遍,而while会一直在原地等你,直到你来…………原来while的使用会进入无限循环判断,如果不加break,就会一直卡在判断条件成立与否,那EXTI中断就不能跳出循环进行下一次的响应了,害……C语言基础不牢,果真地动山摇。既然如此,那就修改下void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)中断回调函数的实现,添加break跳出语句,如下:

/**
 * @brief          exit callback function
 * @param[in]      GPIO_Pin:gpio pin
 * @retval         none
 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    // if (GPIO_Pin == GPIO_PIN_1)
    // {
    //     HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0);
    // }

    while (GPIO_Pin == GPIO_PIN_1)
    {
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0);
        break;
    }

    //do
    //{
    //    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0);
    //    break;
    //} while (GPIO_Pin == GPIO_PIN_1);
}

这样,就能够正常使用外部中断去判断下降沿/上升沿触发啦。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值