当前位置:   article > 正文

stm32F40x系统滴答定时器计算方法及应用(寄存器版本)_定时器延时1s时间怎么算

定时器延时1s时间怎么算

概述

        系统滴答定时器计算方法,在这记录一下,防止时间久了遗忘。

下图是:时钟树的一小部分:在STM32F4xx中文参考手册.pdf文档第107页可以找到。

框架图:

控制状态寄存器:  SysTick->CTRL

自动重装载寄存器:SysTick->LOAD

当前值寄存器:    SysTick->VAL

校准值寄存器:    SysTick->CALIB

上面框架图是来自于:Cortex M3权威指南(中文).pdf 文档第282-315页

1、换算与时钟源选择     

外部时钟源: HCLK = 168MHz / 8
内核时钟:  HCLK = 168MHz
这里选择了  168MHz / 8 = 21MHz
  21MHz = 21000KHz = 21000 000Hz
  1us = (21 000 000Hz/s) / 1000 000 = 21次
也就是1us它里面的val会减21次,因为在21MHz频率,1us中有21个脉冲波。但减到0时,会产生一个中断事件。
2、系统滴答定时器是什么?

答:系统滴答定时器(Systick)是一个24bit的定时器,因此它一次最多可以计数2的24次方个时钟脉冲。用于系统中的时钟节拍,可以不断地产生1uS的中断。
①:SysTick->VAL(最大值24位)
存放24位:二进制(1111 1111 1111 1111 1111 1111) <=> 16进制 0xFFFFFF
       计数最多为:16777215次
       16777215 / 168 = 0.099864375s = 99.864375ms 约等于 100ms 
       16777215 四舍五入 16800000
       168MHz = 168000000
       16800000/168000000 = 0.1s = 100ms   这个计时太短(过快)无法满足所需
       如果是使用了21MHz来计算的话刚好是168的8倍,所以得出计算结果为:800ms
②:800ms计算过程
       同样计算公式: oxffffff / 21000    
       16777215 / 21 = 798.9ms            这个时间基本满足所有计时时间
       也就是最多可以记这么多毫秒: oxffffff / 21000 = 798.9ms    

3、系统滴答定时器延时1S的原理

       思路:利用systick定时器为递减计数器,设定初值并使能它后,它会对每1个系统时钟周期计数器减1,计数到 0时,SysTick计数器自动重装初值并继续计数,同时触发中断。那么每次计数器减到0,时间经过了:系统时钟周期*计数器初值。我们使用168M作为系统时钟,那么每次计数器减1所用的时间是1/168M,计数器的初值如果是168000,那么每次计数器减到0,时间经过(1/168M)*168000=0.001,即1ms。
答:(简单理解:用168M的时钟频率,即1s计数168M=168000000次,那1ms计数168000次,所以计数值为168000,那1us计数168次,所以计数值为168)。

4、配置流程:
①:系统滴答ms级延时设置
    选择时钟源、清空当前计数器的值、设置重载值、使能计数器、等待定时时间到、关闭倒数计数器、计数器清零

②:系统滴答us级延时设置
    选择时钟源、清空当前计数器的值、设置重载值、使能计数器、等待定时时间到、关闭倒数计数器、计数器清零



systick.h文件

  1. #ifndef __SYSTICK_H__
  2. #define __SYSTICK_H__
  3. #include <stm32f4xx.h>
  4. void systick_delay_us(u32 nus);
  5. void systick_delay_ms(u16 nms);
  6. void systick_delay_xms(u32 xms);
  7. #endif

systick.c文件

  1. #include "sysTick.h"
  2. /*
  3. 函数功能:系统滴答微秒延时
  4. 函数形参:nus
  5. 返回值:无
  6. */
  7. void systick_delay_us(u32 nus)
  8. {
  9. //21MHz = 21000000Hz/s = 21000Hz/ms = 21us
  10. if(nus>(0xffffff / 21)) //微秒,只要是大于这个值就不允许延时
  11. {
  12. return;
  13. }
  14. SysTick->CTRL &= ~(0x1<<2);//选择21MHz的时钟源
  15. SysTick->VAL = 0x00; //清空当前计数器的值
  16. SysTick->LOAD = nus * 21; //要记的数
  17. SysTick->CTRL |= 1<<0; //使能倒计数寄存器
  18. /** SysTick->CTRL中的Set bit 16 - count flag **/
  19. while(!(SysTick->CTRL & (0x1<<16)))//等待定时时间达到产生(位16)的标志
  20. {
  21. ;
  22. }
  23. SysTick->CTRL &= ~(1<<0); //关闭倒数计数器 清零 可以不写
  24. SysTick->VAL &= ~(1<<0); //计数器清零 可以不写,寄存器有自动清零功能
  25. }
  26. /*
  27. 函数功能:系统滴答豪秒延时
  28. 函数形参:nms
  29. 返回值:无
  30. */
  31. void systick_delay_ms(u16 nms)
  32. {
  33. //21MHz = 21000000Hz/s = 21000Hz/ms
  34. if(nms>(0xffffff / 21000)) //毫秒,只要是大于这个值就不允许延时
  35. {
  36. return;
  37. }
  38. SysTick->CTRL &= ~(0x1<<2); //选择21MHz的时钟源
  39. SysTick->VAL = 0x00; //清空当前计数器的值
  40. SysTick->LOAD = nms * 21000; //要记的数
  41. SysTick->CTRL |= 1<<0; //使能倒计数寄存器
  42. /** SysTick->CTRL中的Set bit 16 - count flag **/
  43. while(!(SysTick->CTRL & (0x1<<16)))//等待定时时间达到产生(位16)的标志
  44. {
  45. ;
  46. }
  47. SysTick->CTRL &= ~(1<<0); //关闭倒数计数器 清零 可以不写
  48. SysTick->VAL &= ~(1<<0); //计数器清零 可以不写,寄存器有自动清零功能
  49. }
  50. /*
  51. 函数功能:系统滴答 实现任意ms级别的延时
  52. 函数形参:nms
  53. 返回值: 无
  54. 备注: 以500ms的延时为基准延时
  55. */
  56. void systick_delay_xms(u32 xms)
  57. {
  58. u16 i =0;//延时的倍数循环变量
  59. //计算整数个基准延时
  60. for(i=0; i<xms/500; i++)
  61. {
  62. delay_ms(500);
  63. }
  64. //如果不是整数倍 有剩余的延时
  65. if(xms%500!=0)  //有余数
  66. {
  67. delay_ms(xms%500);
  68. }
  69. }

main.c

  1. #include "led.c"
  2. #include "systick.h"
  3. int main(void)
  4. {
  5. led_init();
  6. while(1)
  7. {
  8. LED1_ON;
  9. systick_delay_ms(500); //延时0.5s
  10. LED1_OFF;
  11. systick_delay_ms(500); //延时0.5s
  12. }
  13. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/755644
推荐阅读
相关标签
  

闽ICP备14008679号