当前位置:   article > 正文

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

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

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

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

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
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);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

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

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

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

    // /*Configure GPIO pin : PC1 */
    // GPIO_InitStruct.Pin = GPIO_PIN_1;
    // GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    // GPIO_InitStruct.Pull = GPIO_PULLUP;
    // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
    // HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /*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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

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

int main(void)
{
  /* MCU Configuration--------------------------------------------------------*/

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

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

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

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

  while (1)
  {

  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

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
   */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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

/* USER CODE END 1 */
/**
 * @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 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

六、编写中断服务函数

我们在按键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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这里问题出现了,如下图所示,我一开始用的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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/817915?site
推荐阅读
相关标签
  

闽ICP备14008679号