找回密码
 立即注册
查看: 433|回复: 1

STC32 定时器0做滴答,设计millis(),micros(),delay_ms()函数

[复制链接]

该用户从未签到

11

主题

331

回帖

886

积分

荣誉版主

积分
886
发表于 2023-7-21 10:51:57 | 显示全部楼层 |阅读模式
本帖最后由 熊仔 于 2023-7-21 12:10 编辑

用过arduino的人都知道,millis()是获取系统运行时间单位ms;micros()是获取系统运行时间单位us。
当然delay_ms()看名字就知道了,毫秒延时函数。这个根据micros()获取系统us时间,延时挺准的。
delay_us(),微秒延时函数,自适应系统时钟。
while(t--) 翻译汇编需要6T时钟,所以时钟最好选6的倍数:12,24,30,36,42,48,54

注意:delay_ms() 不能在中断中使用。
  1. #include "config.h"
  2. /*
  3. 2023-07-13 修复定时器读取计数值不准的问题。
  4. */
  5. uint32_t volatile edata timer0_millis = 0;
  6. //定时器0初始化
  7. void Timer0_Init(void)                //1毫秒
  8. {
  9.     TM0PS = MAIN_Fosc / 1000000 - 1; //分频,定时器1M时钟
  10.     AUXR |= 0x80;                        //定时器时钟1T模式
  11.     TMOD &= 0xF0;                        //设置定时器模式
  12.     TL0 = (uint8_t)(65536 - 1000);                                //设置定时初始值
  13.     TH0 = (uint8_t)((65536 - 1000) / 256);                                //设置定时初始值
  14.     TF0 = 0;                                //清除TF0标志
  15.     TR0 = 1;                                //定时器0开始计时
  16.     ET0 = 1;                //开启中断
  17. }
  18. //定时器溢出中断
  19. void Timer0_Isr(void) interrupt 1
  20. {
  21.     timer0_millis++;
  22.     P20 = ~P20;
  23. }
  24. //获取系统运行时间单位ms
  25. uint32_t millis()
  26. {
  27.     return timer0_millis;
  28. }
  29. //获取系统运行时间单位us
  30. uint32_t micros()
  31. {
  32.     uint32_t ms, us;
  33.     uint8_t th, tl, tf;
  34.     F0 = EA;
  35.     EA = 0;
  36.     /*
  37.     动态读取运行中的计数值
  38.     一种可避免读错的方法是:先读 THx,后读TLx,将两次读得的THx 进行比较,
  39.     若两次读得的值相等,则可确定读的值是正确的,否则重复上述过程,
  40.     重复读得的值一般不会再错。
  41.     */
  42.     do
  43.     {
  44.         th = TH0;
  45.         tl = TL0;
  46.     }
  47.     while(th != TH0);
  48.     tf = TF0;
  49.     ms = timer0_millis;
  50.     EA = F0;
  51.     if(tf)
  52.     {
  53.         ms++;
  54.         us = ms * 1000;
  55.     }
  56.     else
  57.     {
  58.         us = ms * 1000 + th * 256 + tl - 64536;
  59.     }
  60.     return us;
  61. }
  62. //毫秒延时函数
  63. void delay_ms(uint32_t ms)
  64. {
  65.     uint32_t start, current;
  66.     start = micros();
  67.     while (ms > 0)
  68.     {
  69.         current = micros();
  70.         if (( current - start) >= 1000)
  71.         {
  72.             ms--;
  73.             start += 1000;
  74.         }
  75.     }
  76. }
  77. //while(t--) 翻译汇编需要6T时钟,所以时钟最好选6的倍数:12,24,30,36,42,48,54
  78. #define US_6T  (MAIN_Fosc/6000000UL)
  79. void delay_us(uint16_t us)
  80. {
  81.     uint32_t t;
  82.     t =  us * US_6T;     //3T
  83.     t -= 2;           //1T
  84.     while(t--);     //6T*t
  85.     //最后退出只需要1T,所以-2T
  86.     //RET 3T  参数 1T lcall 3T
  87. }
  88. //由于micros()需要时间,导致不是很准
  89. /*
  90. void delay_us(uint32_t us)
  91. {
  92.         uint32_t end,current;
  93.     end = micros()+us;
  94.     #if(MAIN_Fosc>=40000000UL)
  95.     end--;
  96.     #endif
  97.     #if(MAIN_Fosc<40000000UL)
  98.     end-=2;
  99.     #endif
  100.     do{
  101.         current = micros();
  102.     }while (current < end) ;
  103. }
  104. */
复制代码


回复 送花

使用道具 举报

该用户从未签到

11

主题

331

回帖

886

积分

荣誉版主

积分
886
 楼主| 发表于 2023-7-21 11:43:38 | 显示全部楼层
这个代码调试了很久,才弄对。
调试过程中,遇到2个难题:
1,动态读取运行中的计数值,读不准的问题。请教了STC技术才解决。
2,必须读取溢出标志位,溢出的时候tl不是马上重载的,这个要注意,计算的时候去掉th和tl的数值。
回复 支持 反对 送花

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2024-5-19 13:06 , Processed in 0.056742 second(s), 33 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表