利用STM32TIM自制延迟函数实验

一、实验目的

  1. 掌握STM32定时器(TIM)的工作原理及配置方法
  2. 学习使用HAL库实现微秒级/毫秒级延时函数
  3. 理解定时器中断服务程序的编写规范

二、实验原理

  1. 定时器基础

    • STM32定时器包含向上计数器、向下计数器、中心对齐模式
    • 通过预分频器(PSC)和自动重载寄存器(ARR)控制计数周期
  2. 时间计算公式

    延时时间 = (自动重载值 + 预分频系数 - 1) / (系统时钟频率 × 预分频系数)

三、硬件准备

  1. 开发板:STM32F103C8T6

四、实验步骤

  • 选择STM32F103C8T6芯片

  • 设置调试接口

  • 启用TIM1定时器

  • 配置TIM1

选择RCC做为时钟信号源

计算TIM需要的参数

如图我们PSC = 7,ARR = 999,RCR = 0,同时使用ARR寄存器预加载

  • 设置updata中断

  • 生成项目

  1. 代码配置:

 我们要实现自己的延迟函数首先要自定义一个函数

static void MyDelay(uint32_t Delay){

    uint32_t expireTime = MyGetTick() + Delay;
    
    while(MyGetTick() < expireTime)//等待延迟结束
}

其中MyGetTick()是获取当前计时器时间的函数,也是我们要自编写的函数之一。Delay是要延迟的毫秒数。

实现MyGetTick()函数

static volatile uint32_t currentMiliSeconds = 0;
static uint32_t MyGetTick(void){
    return currentMiliSeconds;
}

我们是通过计时器中断的方法来实现自己的延迟函数的,我们要使用先关的库函数,要重写库函数完成currentMiliSeconds值的累加。基本原理是启动定时器,产生update事件并触发中断并回调重写函数HAL_TIM_PeriodElapsedCallback()。

组织代码如下

static volatile uint32_t currentMiliSeconds = 0;

static void MyDelay(uint32_t Delay){
    uint32_t expireTime = MyGetTick() + Delay;  
    while(MyGetTick() < expireTime);//等待延迟结束
}


static uint32_t MyGetTick(void){
    return currentMiliSeconds;
}



void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    if(htim == &htim1){
        currentMiliSeconds++; 
    }
}

编写GPIO闪灯代码

 while (1)
  {
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
	    MyDelay(1000);
	    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
	    MyDelay(1000);    
  }

五、预期现象

  • LED灯以1Hz频率交替闪烁(亮0.5s/灭0.5s)
  • 使用逻辑分析仪测量TIM1计数周期应为1ms
### STM32 定时器 TIM 延时函数实现教程 #### 使用硬件定时器实现精确延时 对于 STM32 微控制器而言,利用内置的定时器 (Timer) 实现高精度延时是一种常见且有效的方法。通过配置定时器的工作模式和参数,可以轻松创建一个基于硬件中断的延时函数。 具体来说,可以通过以下方式来设置 TIM 定时器以达到所需的延时效果: - **初始化定时器**:选择合适的定时器外设并对其进行基本配置,包括预分频系数、自动重装载值以及计数方向等。 ```c void TIM_Config(void){ TIM_TimeBaseInitTypeDef TIM_InitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 启用TIM2时钟 TIM_InitStruct.TIM_Period = 999; // 自动重装载值 TIM_InitStruct.TIM_Prescaler = 7199; // 预分频系数 TIM_InitStruct.TIM_ClockDivision = 0; // 不使用时基单元中的CK_INT时钟分割功能 TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 计数向上 TIM_TimeBaseInit(TIM2, &TIM_InitStruct); TIM_Cmd(TIM2, ENABLE); // 开启定时器 } ``` - **编写延时函数**:定义一个 `Delay_ms` 函数用于执行指定毫秒级别的延时操作。该函数会等待直到定时器溢出事件发生为止。 ```c volatile uint32_t TimingDelay; void Delay_ms(uint32_t nTime){ TimingDelay = nTime; while(TimingDelay != 0); } void TIM2_IRQHandler(void){ // 中断服务程序 if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){ TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 清除更新标志位 if (--TimingDelay == 0){ /* Do nothing */ } } } ``` 以上代码片段展示了如何在 STM32 上构建一个简单的基于 TIM延时机制[^3]。 为了确保延时准确性,还需要合理调整定时器的预分频寄存器 (`PSC`) 和自动重装载寄存器 (`ARR`) 的数值,这取决于系统的主频率及时所需要的具体延时时长。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值