赞
踩
最近在使用STM32的HAL库尝试作1个极其简单的小实验:以引脚PC1作外部中断响应,去激励引脚PC0-LED翻转…………但就是这么一个简单的实验,让我卡住了好久。下面来分析下这个实验和出现的问题:
板子的硬件原理图:
HAL库代码配置:
/** 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); }
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); }
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) { } }
while(1)里面不用写东西,后面我们直接在中断回调callback函数编写中断服务
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 */ }
/* 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 */
}
我们在按键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起作用呢,为啥?
知其然,不知其所以然。那能怎么办呢,去请教网上的大佬看看if和while的具体用法呗,搜索中…………出现答案。
哦,意思就是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); }
这样,就能够正常使用外部中断去判断下降沿/上升沿触发啦。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。