stm32h743一个定时器实现秒和微妙延时

一、定时器溢出公式

Tout(溢出时间)=(ARR+1)(PSC+1)/Tclk

二、确定定时器类型

三种定时器:基础定时器,通用定时器,高级定时器
STM32H743有众多的定时器,其中包括 2 个基本定时器( TIM6 和 TIM7 )、 10 个通用定时
器( TIM2~TIM5 , TIM12~ TIM17 )、 2 个高级控制定时器( TIM1 和 TIM8 )和 5 个低功耗定时
器( LPTIM1~LPTIM5 )。这些定时器彼此完全独立,不共享任何资源。
这里我们使用通用定时器TIM2,其中有一个原因是TIM2是 32位计数器 , 可以满足我们后面实现一个定时器实现秒和微妙延时

三、确定定时器时钟的频率

在 TIMPRE 位默认设置为 0 的情况下,

当 APB1 的 D2PPRE1 预分频器预的分频系数为 1 时,这个倍频器系数就为 1,即定时器的时钟源频率等于APB1 总线时钟频率;

当 APB1 的 D2PPRE1 预分频器的预分频系数≥2 分频时,这个倍频器系数就为 2,即定时器的时钟源频率等于 APB1 总线时钟频率的两倍。

HCLK (High-speed AHB Clock)是 AHB 总线(Advanced High-performance Bus)的时钟源

这里的系统主频是480MHZ,HCLK经过2分频为240MHZ

APB 总线时钟(PCLK1/PCLK2/D1PCLK1/D3PCLK1)由 HCLK 进一步分频得到:

  • PCLK1 = HCLK ÷ 2 = 120 MHz(APB1 总线)
  • PCLK2 = HCLK ÷ 2 = 120 MHz(APB2 总线)

通用定时器的时钟都挂载在APB,故我们要配置的时钟TIM2的频率为120MHZ*2=240MHZ

四、确定psc和arr

根据公式:Tout(溢出时间)=(ARR+1)(PSC+1)/Tclk

采用,psc为240-1,arr为1000000(提前该定时器为32位定时器)

这样中断溢时周期为1s,每一次计数为1us(调用TIM2->CNT)

五、实现代码

注意

在使用HAL_TIM_Base_Start_IT(&g_timx_handle); 使能定时器x和定时器x更新中断

必须在GTIM_TIMX_INT_IRQHandler定时器中断函数中加上__HAL_TIM_CLEAR_IT(&g_timx_handle, TIM_IT_UPDATE); /* 清除定时器溢出中断标志位 */

原因:必须手动清除标志位,否则中断会不断触发,导致程序进入死循环

btim.c

复制代码
#include "./BSP/TIMER/btim.h"
#include "./BSP/LED/led.h"

/* 定时器配置句柄 定义 */
TIM_HandleTypeDef g_timx_handle;                          /* 定时器x句柄 */

/**
 * @brief       通用定时器TIMX定时中断初始化函数
 * @note
 *              定时器的时钟来自APB1 或 APB2, 当D2PPRE1(D2PPRE2)≥2分频的时候
 *              通用定时器的时钟为APB1 或 APB2时钟的2倍, 而APB1(APB2)为120M,
 *              所以定时器时钟 = 240Mhz
 *              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft=定时器工作频率,单位:Mhz
 *
 * @param       arr: 自动重装值
 * @param       psc: 预分频系数
 * @retval      无
 */

volatile uint32_t time_s = 0;    // 秒计数器
volatile uint32_t ms_counter = 0; // 毫秒计数器
volatile uint32_t time_us = 0; // 毫秒计数器


// 初始化 TIM2(产生周期中断)//arr1000000   psc 240-1
void gtim_tim2_int_init(uint32_t arr, uint16_t psc)
{
    GTIM_TIMX_INT_CLK_ENABLE();                             /* 使能TIMx时钟 */

    g_timx_handle.Instance = GTIM_TIMX_INT;                 /* 通用定时器x */
    g_timx_handle.Init.Prescaler = psc;                     /* 预分频系数 */
    g_timx_handle.Init.CounterMode = TIM_COUNTERMODE_UP;    /* 递增计数模式 */
    g_timx_handle.Init.Period = arr;                        /* 自动装载值 */
    HAL_TIM_Base_Init(&g_timx_handle);

    HAL_NVIC_SetPriority(GTIM_TIMX_INT_IRQn, 1, 3);         /* 设置中断优先级,抢占优先级1,子优先级3 */
    HAL_NVIC_EnableIRQ(GTIM_TIMX_INT_IRQn);                 /* 开启ITMx中断 */

    HAL_TIM_Base_Start_IT(&g_timx_handle);                  /* 使能定时器x和定时器x更新中断 */
}

/**
 * @brief       定时器中断服务函数
 * @param       无
 * @retval      无
 */
void GTIM_TIMX_INT_IRQHandler(void)
{
    /* 以下代码没有使用定时器HAL库共用处理函数来处理,而是直接通过判断中断标志位的方式 */
    if (__HAL_TIM_GET_FLAG(&g_timx_handle, TIM_FLAG_UPDATE) != RESET)
    {
        // 处理 TIM2 中断事件
        // 例如,可以在这里进行一些定时操作
        time_s++; // 秒计数
        __HAL_TIM_CLEAR_IT(&g_timx_handle, TIM_IT_UPDATE);  /* 清除定时器溢出中断标志位 */
    }
}

// 获取当前秒数
uint32_t GetSec(void)
{
    return time_s;
}

// 获取当前微秒数
uint32_t GetUSec(void)
{
    time_us = (TIM2->CNT)%1000000;
    return time_us;
}

btim.h

复制代码
#ifndef __BTIM_H
#define __BTIM_H

#include "./SYSTEM/sys/sys.h"

/*******************************以下是通用定时器中断实验相关宏定义*************************************/

/* 通用定时器 定义 */
#define GTIM_TIMX_INT                       TIM2
#define GTIM_TIMX_INT_IRQn                  TIM2_IRQn
#define GTIM_TIMX_INT_IRQHandler            TIM2_IRQHandler
#define GTIM_TIMX_INT_CLK_ENABLE()          do{ __HAL_RCC_TIM2_CLK_ENABLE(); }while(0)  /* TIM2 时钟使能 */

/****************************************************************************************************/

void gtim_tim2_int_init(uint32_t arr, uint16_t psc);        /* 通用定时器 定时中断初始化函数 */

#endif
相关推荐
LS_learner2 小时前
树莓派(ARM64 架构)Ubuntu 24.04 (Noble) 系统 `apt update` 报错解决方案
嵌入式硬件
来自晴朗的明天3 小时前
16、电压跟随器(缓冲器)电路
单片机·嵌入式硬件·硬件工程
钰珠AIOT3 小时前
在同一块电路板上同时存在 0805 0603 不同的封装有什么利弊?
嵌入式硬件
代码游侠3 小时前
复习——Linux设备驱动开发笔记
linux·arm开发·驱动开发·笔记·嵌入式硬件·架构
代码游侠14 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
xuxg200516 小时前
4G 模组 AT 命令解析框架课程正式发布
stm32·嵌入式·at命令解析框架
CODECOLLECT18 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen18 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠21 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件