STM32通用定时器实现微秒延时函数

         思路:以STM32F103C8T6为例,定时器外设有两个重要的东西:自动重装寄存器(ARR)和32位计数器(CNT),规定计数器跳动一次需要1us,将要延时的时间直接给ARR,每次让CNT的值变0,向上计数。当CNT=ARR时,会触发更新事件标志位,通过该标志位可以知道延时是否结束。注意最后要清除该标志位!

TIM_HandleTypeDef htim2;

/*延时选择TIM2*/
void delay_init(void)
{
  //开启TIM2外设的时钟
  __HAL_RCC_TIM2_CLK_ENABLE();
  
//  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 72-1;  //若系统主频是72MHZ,预分频71表明计数器跳动一次需要1us
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period =1;         //重装载值随便,后面进行动态调整
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

  //定时器配置
  HAL_TIM_Base_Init(&htim2);
  
  //定时器配置时钟源:内部时钟,上电后会默认选择内部时钟
  //sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  //HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig);
}

//根据所传参数,动态调整ARR寄存器的值
void delay_us(uint32_t us)
{
    __HAL_TIM_SET_AUTORELOAD(&htim2, us);  // 设置自动重载值(ARR = us)
    __HAL_TIM_SET_COUNTER(&htim2, 0);       // 清零计数器

    HAL_TIM_Base_Start(&htim2);  // 启动定时器
    while (!__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_UPDATE)); // 等待计数完成
    HAL_TIM_Base_Stop(&htim2);    // 停止定时器
    __HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE); // 清除标志
  
}

        为了能更精确的延时,最好直接操作TIM寄存器

//根据所传参数,动态调整ARR寄存器的值
void delay_us(uint32_t us)
{
    TIM2->ARR = us;                        // 直接设置ARR
    TIM2->CNT = 0;                         // 清零计数器

    TIM2->CR1 |= TIM_CR1_CEN;              // 启动定时器
    while (!(TIM2->SR & TIM_FLAG_UPDATE)); // 轮询等待
    TIM2->CR1 &= ~TIM_CR1_CEN;             // 停止定时器
    TIM2->SR &= ~TIM_FLAG_UPDATE;          // 清除标志位
  
}

STM32定时器配置微秒延时通常使用基本定时器(如TIM1、TIM8等)配合预分频器和计数器来实现。以下是一个简单的步骤: 1. **初始化定时器**: - 首先需要对定时器进行初始化,设置其工作模式(例如为模式3,即PWM模式),时钟源选择以及是否自动装载初始值等。 ```c TIM_HandleTypeDef htim; TIM_TimeBaseInitTypeDef.TIM_Prescaler = PrescalerValue; // 设置预分频器值 TIM_TimeBaseInitTypeDef.TIM_Period = MicrosecondsToPeriod(Microseconds); // 计算周期,假设已知Microseconds到周期的关系 htim.Instance = TIMx; // 替换TIMx为你使用的定时器实例 HAL_TIM_Base_Init(&htim); ``` 2. **启动定时器**: - 启动定时器以便开始计数。 ```c HAL_TIM_Base_Start_IT(&htim); ``` 3. **等待计数完成**: - 使用`TIM_TimeBase_GetCounter()`获取当前计数值,并将其与期望的延时期限相比较,当达到预期值时,可以认为延时结束。 ```c uint16_t counter = HAL_TIM_Base_GetCounter(&htim); while (counter < ExpectedMicroseconds) { if (HAL_TIM_Base_GetOverrunFlag(&htim)) { // 检查溢出标志 // 清除溢出标志并处理异常情况 HAL_TIM_Base_ClearOverrun(&htim); } counter = HAL_TIM_Base_GetCounter(&htim); } ``` 4. **停止定时器**: - 在延时结束后关闭定时器。 ```c HAL_TIM_Base_Stop(&htim); ``` 请注意,这只是一个基础示例,实际应用可能还需要处理中断、延时精度调整等因素。此外,对于更高级的需求,如高精度延时,可能需要结合RTOS的任务调度机制或者使用专门的延时库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值