STM32F103VET6 拂晓按键流水灯及中断与HAL_Delay的冲突
提示:以下是本篇文章正文内容,下面案例可供参考
一、程序代码
本文的工程修改的是STM32 HAL库开发例程17-外部中断 主函数
int main(void)
{
SystemClock_Config();
LED_GPIO_Config();
EXTI_Key_Config();
HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
while(1)
{
}
}
系统时钟初始化
void SystemClock_Config(void)
{
*RCC_ClkInitTypeDef clkinitstruct = {0};
RCC_OscInitTypeDef oscinitstruct = {0};
oscinitstruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
oscinitstruct.HSEState = RCC_HSE_ON;
oscinitstruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
oscinitstruct.PLL.PLLState = RCC_PLL_ON;
oscinitstruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
oscinitstruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&oscinitstruct)!= HAL_OK)
{
while(1);
}
clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2)!= HAL_OK)
{
while(1);
}*
}
LED初始化
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
LED1_GPIO_CLK_ENABLE();
LED2_GPIO_CLK_ENABLE();
LED3_GPIO_CLK_ENABLE();
LED4_GPIO_CLK_ENABLE();
GPIO_InitStruct.Pin = LED1_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LED2_PIN;
HAL_GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LED3_PIN;
HAL_GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LED4_PIN;
HAL_GPIO_Init(LED4_GPIO_PORT, &GPIO_InitStruct);
LED_RGBOFF;
}
按键初始化(不同的单片机需要查看电路图修改.h文件中的宏定义)
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
KEY1_INT_GPIO_CLK_ENABLE();
KEY2_INT_GPIO_CLK_ENABLE();
GPIO_InitStructure.Pin = KEY1_INT_GPIO_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
HAL_NVIC_SetPriority(KEY1_INT_EXTI_IRQ, 2, 0);
HAL_NVIC_EnableIRQ(KEY1_INT_EXTI_IRQ);
GPIO_InitStructure.Pin = KEY2_INT_GPIO_PIN;
HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
HAL_NVIC_SetPriority(KEY2_INT_EXTI_IRQ, 0, 0);
HAL_NVIC_EnableIRQ(KEY2_INT_EXTI_IRQ);
}
中断函数(通过按键中断开启灯循环点亮)
void KEY1_IRQHandler(void)
{
if(__HAL_GPIO_EXTI_GET_IT(KEY1_INT_GPIO_PIN) != RESET)
{
int x =0;
button_flag = 1;
while(button_flag)
{
switch(x)
{
case 0:
LED1_TOGGLE;
HAL_Delay(500);
case 1:
LED2_TOGGLE;
HAL_Delay(500);
case 2:
LED3_TOGGLE;
HAL_Delay(500);
case 4:
LED4_TOGGLE;
HAL_Delay(500);
}
}
__HAL_GPIO_EXTI_CLEAR_IT(KEY1_INT_GPIO_PIN);
}
}
void KEY2_IRQHandler(void)
{
if(__HAL_GPIO_EXTI_GET_IT(KEY2_INT_GPIO_PIN) != RESET)
{
button_flag = 0;
__HAL_GPIO_EXTI_CLEAR_IT(KEY2_INT_GPIO_PIN);
}
}
二、HAL_Delay的源码及使用的定时器
1、HAL_Delay 使用的定时器
HAL_Delay 使用的是系统滴答定时器 滴答定时器是一个 24 位倒计数的定时器,从预装载值一直到 0,重装载寄存器的值会自动装载到计数寄存器中。
2、源码
三、按键中断与HAL_Delay的冲突
1.原因
当把程序烧写到板子上的时候,并没有像想象的那样子运行,而是在LED1亮起的时候就卡死了, 原因是因为系统时钟设置里给滴答定时器的抢占优先级为15,所以在中断里调用HAL_Delay会卡死,所以我们需要去调高滴答定时器的抢占优先级,调低中断的抢占优先级
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
{
uint32_t tickstart = 0U;
assert_param(RCC_ClkInitStruct != NULL);
assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType));
assert_param(IS_FLASH_LATENCY(FLatency));
.............
HAL_InitTick (TICK_INT_PRIORITY);
return HAL_OK;
}
2.解决方法
在系统时钟初始化后调高滴答定时器的中断
HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
|