【HAL库stm32实现中断控制流水灯】

一、实现流水灯

1、CubeMX设置

设置PA4,PB8,PC14模式为推挽输出
在这里插入图片描述

2、代码思路

代码思路:主循环中三个IO口依次每一个引脚置低电平(LED另一端引脚接面包板负极),相应的另外两个IO口置高电平。
主函数

int main(void)
{
SystemClock_Config();//系统时钟初始化
  MX_GPIO_Init();//gpio初始化
  while (1)
  {		
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);//PA4亮灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
		HAL_Delay(1000);//延时1s
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);//PB9亮灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
		HAL_Delay(1000);//延时1s		
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);//PC15亮灯
		HAL_Delay(1000);//延时1s
	}

}

HAL基本流水灯

3、最终效果

二、使用外部中断,按键控制流水灯

1、CubeMX设置

PB1端口设置默认高电平,上升沿触发
PA1,PB8,PC14端口设置为推挽输出
在这里插入图片描述

2、尝试用HAL_Delay函数失败

发现在外部中断中使用HAL_Delay函数会卡死,只能触发一次中断,然后后面无法触发
在这里插入图片描述

原因

查看HAL_Delay函数

/** * @brief This function provides minimum delay (in milliseconds) based * on variable incremented. * @note In the default implementation , SysTick timer is the source of time base. * It is used to generate interrupts at regular time intervals where uwTick * is incremented. * @note This function is declared as __weak to be overwritten in case of other * implementations in user file. * @param Delay specifies the delay time length, in milliseconds. * @retval None */
__weak void HAL_Delay(uint32_t Delay)
{ 
   
  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  { 
   
    wait += (uint32_t)(uwTickFreq);
  }

  while((HAL_GetTick() - tickstart) < wait)
  { 
   
  }
}

注意事项说到,计时器的时基来自SysTick定时器,且在固定时间间隔产生(interrupt)中断
系统滴答定时器(System tick timer)的优先级默认为最低,外部中断处理的优先级比系统滴答定时器优先级高,具体流程如下

按键触发中断处理程序 --> HAL_Delay() --> 系统滴答定时器(未执行)–>外部中断处理 --> HAL_Delay() (卡死)

所以如果HAL_Delay()需要被外部中断处理程序调用,系统滴答定时器必须比外部中断要高,否则调用者的中断处理程序将被阻塞。

解决方法

(1)通过while循环延时代替HAL_Delay函数

在这里插入图片描述

(2)通过更改中断和系统滴答定时器的优先级

设置中断优先级,更改系统滴答定时器和外部中断的优先级,将系统滴答定时器的优先级设置的比外部中断要高
在这里插入图片描述

3、用while循环延时代码实现

中断

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    /* Prevent unused argument(s) compilation warning */
    //HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4);  //翻转电平
	if(flag)flag=0;
	else flag=1;
	
	uint16_t t=(uint16_t)312700;
	while(t--);

	/* NOTE: This function Should not be modified, when the callback is needed,
             the HAL_GPIO_EXTI_Callback could be implemented in the user file
     */
}

主函数

int main(void)
{
 HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  while (1)
  {		if(flag){
 		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);//PA4亮灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
		HAL_Delay(100);//延时1s
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);//PB9亮灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
		HAL_Delay(100);//延时1s		
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);//PC15亮灯
		HAL_Delay(100);//延时1s
		}
	  else{
 		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
	  }
	}
  /* USER CODE END 3 */
}

4、最终效果

HAL按键中断流水灯

三、软件仿真逻辑分析仪功能观察串口输出波形

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
相差两秒,main函数中设置的也是两秒一亮,比较精准

https://blog.csdn.net/weixin_56102526/article/details/120877293
https://blog.csdn.net/weixin_46129506/article/details/120780184
https://blog.csdn.net/qq_44918248/article/details/114579472
https://blog.csdn.net/qq_46380537/article/details/121510324
https://blog.csdn.net/Dir_x/article/details/128899621

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值