问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

STM32通用定时器中断编程实验指南

创作时间:
作者:
@小白创作中心

STM32通用定时器中断编程实验指南

引用
CSDN
1.
https://blog.csdn.net/qq_59757948/article/details/139695497

在单片机开发中,当需要产生严格时序的场景(如DAC输出特定模拟信号或GPIO口控制模拟开关)时,简单的延时函数往往无法满足要求。本文通过一个具体的实验,详细介绍了如何使用STM32的通用定时器中断来实现精确的时序控制。实验中,我们将控制开发板上的LED0和LED1,使其按照LED0亮500ms后熄灭、随后LED1亮100ms后熄灭的循环时序工作。

实验步骤

  1. 设定时钟总线频率
    本实验使用默认的16MHz时钟总线频率。

  2. 配置定时器参数
    需要设置定时器的预分频系数和自动重装载计数器的值。

  3. 使能中断并设置优先级
    配置定时器中断并调整其优先级。

  4. 代码实现

    (1)在定时器初始化函数中开启定时器7中断

    /* TIM7 init function */
    void MX_TIM7_Init(void)
    {
      /* USER CODE BEGIN TIM7_Init 0 */
      /* USER CODE END TIM7_Init 0 */
      TIM_MasterConfigTypeDef sMasterConfig = {0};
      /* USER CODE BEGIN TIM7_Init 1 */
      /* USER CODE END TIM7_Init 1 */
      htim7.Instance = TIM7;
      htim7.Init.Prescaler = 3999;
      htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim7.Init.Period = 199;
      htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
      if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
      {
        Error_Handler();
      }
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
      if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN TIM7_Init 2 */
       HAL_TIM_Base_Start_IT(&htim7);//开启定时器7中断
      /* USER CODE END TIM7_Init 2 */
    }
    

    (2)在stm32f4xx_it.c中找到中断处理函数

    (3)查看中断回调函数的底层逻辑

    (4)重写虚函数并定义所需全局变量

    /* USER CODE BEGIN EV */
    uint8_t g_timTick=0;               //定时器中断节拍
    uint8_t g_timSwitch=0;             //定时器中断“门票”
    /* USER CODE END EV */
    
    /* USER CODE BEGIN 1 */
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
      if(htim->Instance == TIM7){                              //涉及到多个定时器中断的时候检查就很有必要了
        const uint8_t increment=1;                         //计数步长为常量1
        g_timTick = (g_timTick + increment) % 5;               //5:1的GPIO口时序
      }
      g_timSwitch++;                                         //回调函数发放门票
    }
    /* USER CODE END 1 */
    

    (5)在stm32f4xx_it.c中声明全局变量

    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "main.h"            //防止uint8_t无法被编译器识别
    /* USER CODE END Includes */
    /* Exported types ------------------------------------------------------------*/
    /* USER CODE BEGIN ET */
    /* USER CODE END ET */
    /* Exported constants --------------------------------------------------------*/
    /* USER CODE BEGIN EC */
    extern uint8_t g_timTick;          
    extern uint8_t g_timSwitch;
    /* USER CODE END EC */
    

    (6)主函数中编写功能函数

    if(g_timSwitch){
      g_timSwitch--;                             //进入主循环则收回门票,防止CPU重复判断
      if(g_timTick==0){
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);  
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);  
      }else{
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);  
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
      }  
    }
    

    (7)下载验证

    观察到单片机开发板的LED灯进行频闪,试验成功。不过从波形上来看会有较大的误差,因为只有500ms的时序是用中断严格实现的。想要精准控制原理就是上述的那些,感兴趣的同学可以自己试一试。

补充说明:高级定时器的内部时钟计时操作

从模式选择触发模式(Reset Mode),触发源选择内部触发(ITRx即Internal Trigger Input),时钟源选择内部时钟,其他和通用定时器基本相同。最后请大家注意每一个操作的timer挂载的始终总线(APB1之类的)。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号