使用HAL库在stm32中实现中断控制流水灯

HAL库中断控制LED流水灯

  • 一、实现流水灯
  • 1、CubeMX设置
  • 2、代码思路
  • 3、最终效果
  • 二、使用外部中断,按键控制流水灯
  • 1、CubeMX设置
  • 2、尝试用HAL_Delay函数失败
  • 原因
  • 解决方法
  • (1)通过while循环延时代替HAL_Delay函数
  • (2)通过更改中断和系统滴答定时器的优先级
  • 3、用while循环延时代码实现
  • 4、最终效果
  • 三、软件仿真逻辑分析仪功能观察串口输出波形
  • 一、实现流水灯

    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

    作者:Xkccsdn147

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用HAL库在stm32中实现中断控制流水灯

    发表回复