• 关于单片机的分频定时器的记录


    记录一内部时钟:

    对于单片机的频率原来一直不太明白,现在在学习进行记录:

    主频:

    以一个72M的STM32单片机作为主频为例子,这个72M主频说得是一秒钟产生72000000(七千两百万)个脉冲或周期,就是一秒钟振荡七千两百万次。
    
    • 1

    分频

    对于分频来说,实际就是相当于间接降低这个主频,减少这个震荡次数,比如我分频系数为72,那么我就是1S产生的震荡次数就是72000000/72=1000000次,相当于用少的计数来对一秒钟进行计数。
    那么有人好奇了那么分频的好处是什么呢?

    分频的好处:

    时间精度控制:

    (1)时间精度控制:分频器允许你准确地控制定时器的时间精度。通过减慢计数速度,你可以生成更精确的时间延迟,从而满足各种应用的时间精度需求。
    举个例子:
    你的STM32微控制器的主频是72MHz,这意味着每秒钟有72,000,000个时钟周期。如果你直接使用主频来控制定时器,那么时间精度可能会受到限制,因为一些操作可能需要更短的时间间隔。
    为了提高时间精度,你可以使用分频器来降低定时器的计数速度。例如,你可以将分频器设置为72,000,这将使定时器每秒钟计数1,000次。这意味着你可以非常精确地测量时间间隔,因为每个计数周期的时间是1毫秒。如果需要更高的精度,你可以进一步降低分频器的值。

    适应不同的时间间隔

    (2)适应不同的时间间隔:使用分频器,你可以根据需要生成不同范围的时间间隔。如果需要较长的时间延迟,你可以降低计数速度。如果需要较短的时间间隔,你可以增加计数速度。这使得分频器非常灵活。
    举个例子
    长时间间隔:在某些情况下,你可能希望较长的时间间隔,例如每小时采集一次温度数据并上传到服务器。在这种情况下,你可以设置一个较大的分频器值,以降低计数器的计数速度,从而延长时间间隔。例如,如果你的主频是72MHz,可以将分频器设置为720,000,这将使计数器每秒钟计数720,000次,每个计数周期的时间为1秒。这样,你就可以在每秒钟计数一次,然后每小时上传一次数据。

    短时间间隔:在其他情况下,你可能需要更短的时间间隔,比如每分钟采集一次数据并上传到服务器。在这种情况下,你可以减小分频器值,增加计数器的计数速度,从而缩短时间间隔。例如,将分频器设置为72,000,计数器每秒钟计数72,000次,每个计数周期的时间为0.01秒(10毫秒)。这样,你就可以在每10毫秒计数一次,然后每分钟上传一次数据。

    (3)降低功耗:分频器允许你降低定时器或计数器的计数速度,从而降低系统的功耗。这对于需要在低功耗条件下运行的电池供电设备非常重要。

    (4)提高系统稳定性:通过减慢计数速度,分频器可以提高定时器或计数器的稳定性。这有助于减小计数器的溢出频率,防止计数器在非常短的时间内溢出,从而导致错误。

    (5)适应不同的时钟源:有些系统可能需要切换不同的时钟源,分频器可以帮助你调整计数器以适应不同的时钟源频率。

    (2)关于外部时钟的问题

    对于STM32来说使用外部晶体的32.768kHz的振荡器,因为频率比较低就不需要进行分频了。
    那么怎么产生一个1s的一个数据的呢?下面进行计算
    在这里插入图片描述
    我们的RTC_CLK为32.768kHz也就是外部时钟,所以我们把PRL中写入32767即可,为2的15次方,为了能被32.768K进行整除所以我们进行+1操作,为了得到一个整数的计数。
    那么我们产生1S的计数就为1。
    从上述能知道TR_CLK输出必须为1s。如果产生一个0.15S的应该怎么实现呢?

    有一个叫做RTC_DIV:预分频器余数寄存器和RTC_CNT:计数器寄存器的两个东西。重新配置一个0.15S的,我们将PRL设置为0,那么Ftr_clk等于32768。也就是在RTC_DIV装载为32768,因为DIV是自减的,并且从32768一直减少到0,所需要的时间为1s,所以减少一个数,所用的时间为1/32768s,那么减少多少个数,就计时了0.15s呢?

    所以:1/32768s * n = 0.15,n = 0.15 * 32768,又因为DIV寄存器是可读的,所以我们就能实现0.15s的计时。

    下面是一个使用STM32F1标准库的定时器初始化程序,可以生成一个1秒的定时器。这个示例使用了TIM4定时器,你可以根据需要修改为其他定时器。

    #include "stm32f10x.h"
    
    // 定义定时器参数
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    // 定义定时器溢出计数器
    volatile uint32_t timer_counter = 0;
    
    // 定时器初始化函数
    void Timer_Init() {
      // 初始化TIM4定时器
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    
      // 配置定时器参数
      TIM_TimeBaseStructure.TIM_Period = 9999;       // 计数器重载值,产生1秒的定时
      TIM_TimeBaseStructure.TIM_Prescaler = 7199;     // 预分频器,产生1MHz的时钟(72MHz / 7200)
      TIM_TimeBaseStructure.TIM_ClockDivision = 0;    // 时钟分频,不分频
      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式
      TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
    
      // 启用定时器中断
      TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
    
      // 启用定时器
      TIM_Cmd(TIM4, ENABLE);
    
      // 配置定时器4中断
      NVIC_InitTypeDef NVIC_InitStructure;
      NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
    }
    
    int main(void) {
      // 初始化定时器
      Timer_Init();
    
      while (1) {
        // 在这里可以执行其他任务
        // ...
      }
    }
    
    // 定时器4中断处理函数
    void TIM4_IRQHandler(void) {
      if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
        // 定时器中断发生,执行你的操作
        // ...
        
        // 清除中断标志
        TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    解释

    这个示例初始化了TIM4定时器,将其配置为产生1秒的定时,并启用了定时器中断。当定时器溢出时,中断处理函数TIM4_IRQHandler将被调用,你可以在这个函数中执行你的操作。

    请注意,你可以根据需要调整TIM4的预分频器和重载值来生成不同的定时器。在上述代码中,我们使用预分频器7200(72MHz / 7200)和重载值9999来实现1秒的定时。

  • 相关阅读:
    太厉害了,终于有人能把TCP/IP 协议讲的明明白白了
    批量创建Mongodb账号及关联角色
    MapStruct使用方法
    LeetCode刷题复盘笔记—一文搞懂0 - 1背包之494. 目标和问题(动态规划系列第九篇)
    Nodejs中包的介绍及npm安装依赖包的多种方法
    博客系统页面设计
    【Java第22期】:Thread 类的基本用法
    Win7安装nvme协议的SSD硬盘方法
    攻击角度多样化,放置类游戏安全风险分析
    31_ue4进阶末日生存游戏开发[解决碰撞的两个问题]
  • 原文地址:https://blog.csdn.net/qq_38156743/article/details/132858560