找回密码
 立即注册
查看: 154|回复: 0

32G8K64 实现32位系统us计时和软件定时器

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-04-05 23:13:15
已绑定手机

2

主题

1

回帖

46

积分

新手上路

积分
46
发表于 2025-2-28 15:51:33 | 显示全部楼层 |阅读模式
stc里没有32位的定时器获取系统us的定时太麻烦了, 还要安全取值才行, 要不然会出现时间回退,
使用定时器0来进行系统us计时, 系统运行在40Mhz,8位预分频器设置0x27, 自动重装载值为0, 溢出时间为65536us,
然后再设置一个变量来记录溢出次数, 这样就可以实时获取系统的us计时了

受javascript定时器的启发, 可以实现这种软件定时器跟js的语法一样

  1. //========================================================================
  2. // ---------------------- 类javascript定时器  开始-------------------------
  3. //========================================================================
  4. #define JSTimeSize 10 // 初始化定时的个数, 数量越多, 运行效率越低, 够用就好
  5. unsigned long globeTime = 0;     // 定时器0溢出次数
  6. unsigned long system_us = 0;     // 系统微秒计时
  7. unsigned long tempGlobeTime = 0; // 临时存储globeTime
  8. unsigned char tempTH0 = 0;       // 临时存储TH0
  9. unsigned char tempTL0 = 0;       // 临时存储TL0
  10. struct JSTimeStruct
  11. {
  12.   unsigned long id;         // 定时器id,用来取消定时器, id>0x80000000是setTimeout的id, id<0x80000000是setInterval的id
  13.   unsigned long startTime;  // 开始执行的时间, 单位us
  14.   unsigned long periodTime; // 延时的时间 或者 间隔执行的时间, 单位us
  15.   void (*callback)();       // 回调函数
  16. };
  17. struct JSTimeStruct JSTime_arr[JSTimeSize];
  18. // 获取系统微秒计时
  19. unsigned long micros()
  20. {
  21.   // 系统微秒计时, 保持严格单调递增, 禁止出现时间倒退, 32位溢出时间为71分钟
  22.   // globeTime*65536+(TH0-0)*256+(TL0-0)
  23.   do
  24.   {
  25.     // 如果在读取过程中发生溢出,重新读取
  26.     tempTH0 = TH0;
  27.     tempTL0 = TL0;
  28.     tempGlobeTime = globeTime;
  29.   } while (tempTH0 != TH0 || tempTL0 != TL0 || tempGlobeTime != globeTime);
  30.   // 计算当前时间
  31.   system_us = (tempGlobeTime << 16) + (tempTH0 << 8 | tempTL0);
  32.   return system_us;
  33. }
  34. // 定时器0中断
  35. void T_IRQ0(void) interrupt 1 using 1
  36. {
  37.   globeTime++; // 定时器0溢出次数
  38. }
  39. // 定时器0初始化
  40. void Timer0_Init(void) // 65536微秒@40.000MHz
  41. {
  42.   TM0PS = 0x27; // 设置定时器时钟预分频
  43.   AUXR |= 0x80; // 定时器时钟1T模式
  44.   TMOD &= 0xF0; // 设置定时器模式
  45.   TL0 = 0x00;   // 设置定时初始值
  46.   TH0 = 0x00;   // 设置定时初始值
  47.   TF0 = 0;      // 清除TF0标志
  48.   TR0 = 1;      // 定时器0开始计时
  49.   ET0 = 1;      // 打开定时器0中断
  50.   IPH |= 0x02;  // 设置定时器0的中断的优先级为高
  51.   IP |= 0x02;   // 设置定时器0的中断的优先级为高
  52. }
  53. // 定时器初始化函数
  54. void JSTime_init()
  55. {
  56.   unsigned char i = 0;
  57.   for (i = 0; i < JSTimeSize; i++)
  58.   {
  59.     JSTime_arr[i].callback = 0;
  60.     JSTime_arr[i].periodTime = 0;
  61.     JSTime_arr[i].startTime = 0;
  62.     JSTime_arr[i].id = 0;
  63.   }
  64.   Timer0_Init();
  65. }
  66. unsigned long JSTime_createTimeId = 0x80000000; // `setTimeout`的id
  67. unsigned long JSTime_createIntervalTimeId = 1;  // `setInterval`的id
  68. // loop循环中不断刷新定时器, JSTime_refresh中的局部变量变成全局变量
  69. unsigned long JSTime_cacheId = 0; // 缓存id
  70. unsigned long JSTime_currentTime = 0;
  71. unsigned char JSTime_i = 0;
  72. unsigned char JSTime_isFree = 0;
  73. void JSTime_refresh()
  74. {
  75.   JSTime_currentTime = micros();
  76.   for (JSTime_i = 0; JSTime_i < JSTimeSize; JSTime_i++)
  77.   {
  78.     if (JSTime_arr[JSTime_i].id != 0)
  79.     {
  80.       if (JSTime_currentTime - JSTime_arr[JSTime_i].startTime >=
  81.           JSTime_arr[JSTime_i].periodTime)
  82.       {
  83.         JSTime_cacheId = JSTime_arr[JSTime_i].id;
  84.         if (JSTime_cacheId >= 0x80000000)
  85.         {
  86.           // setTimeout 执行完毕就销毁
  87.           JSTime_isFree = 1;
  88.         }
  89.         else
  90.         {
  91.           JSTime_isFree = 0;
  92.           // setInteval 不断进行
  93.           JSTime_arr[JSTime_i].startTime = JSTime_currentTime;
  94.         }
  95.         if (JSTime_arr[JSTime_i].callback)
  96.         {
  97.           JSTime_arr[JSTime_i].callback();
  98.           JSTime_currentTime = micros();
  99.         }
  100.         // 防止在回调函数里调用了 clearTime 而引发bug
  101.         if (JSTime_isFree == 1 && JSTime_arr[JSTime_i].id == JSTime_cacheId)
  102.         {
  103.           // setTimeout 执行完毕就销毁
  104.           JSTime_arr[JSTime_i].id = 0;
  105.         }
  106.       }
  107.     }
  108.   }
  109. }
  110. // 延时执行, delayTime单位为us
  111. unsigned long setTimeout_us(void (*callback)(), uint32 delayTime)
  112. {
  113.   unsigned char i = 0;
  114.   for (i = 0; i < JSTimeSize; i++)
  115.   {
  116.     // 找出失效的 结构体
  117.     if (JSTime_arr[i].id == 0)
  118.     {
  119.       JSTime_arr[i].callback = callback;
  120.       JSTime_arr[i].periodTime = delayTime;
  121.       JSTime_arr[i].startTime = micros();
  122.       if (JSTime_createTimeId > 0xfffffff0)
  123.       {
  124.         JSTime_createTimeId = 0x80000000;
  125.       }
  126.       JSTime_createTimeId++;
  127.       JSTime_arr[i].id = JSTime_createTimeId;
  128.       return JSTime_createTimeId;
  129.     }
  130.   }
  131.   return 0;
  132. }
  133. // 延时执行, delayTime单位为ms
  134. unsigned long setTimeout(void (*callback)(), uint32 delayTime)
  135. {
  136.   return setTimeout_us(callback, delayTime * 1000);
  137. }
  138. // 间隔时间执行, intervalTime单位为us
  139. unsigned long setInterval_us(void (*callback)(), uint32 intervalTime)
  140. {
  141.   unsigned char i = 0;
  142.   for (i = 0; i < JSTimeSize; i++)
  143.   {
  144.     // 找出失效的 结构体
  145.     if (JSTime_arr[i].id == 0)
  146.     {
  147.       JSTime_arr[i].startTime = micros();
  148.       JSTime_arr[i].callback = callback;
  149.       JSTime_arr[i].periodTime = intervalTime;
  150.       if (JSTime_createIntervalTimeId > 0x7ffffff0)
  151.       {
  152.         JSTime_createIntervalTimeId = 1;
  153.       }
  154.       JSTime_createIntervalTimeId++;
  155.       JSTime_arr[i].id = JSTime_createIntervalTimeId;
  156.       return JSTime_createIntervalTimeId;
  157.     }
  158.   }
  159.   return 0;
  160. }
  161. // 间隔时间执行, intervalTime单位为ms
  162. unsigned long setInterval(void (*callback)(), uint32 intervalTime)
  163. {
  164.   return setInterval_us(callback, intervalTime * 1000);
  165. }
  166. // 停止软件定时器计时
  167. void clearTime(unsigned long timeId)
  168. {
  169.   unsigned char i = 0;
  170.   for (i = 0; i < JSTimeSize; i++)
  171.   {
  172.     if (timeId == JSTime_arr[i].id)
  173.     {
  174.       JSTime_arr[i].id = 0;
  175.     }
  176.   }
  177. }
  178. // 停止所有软件定时器计时
  179. void clearAllTime()
  180. {
  181.   unsigned char i = 0;
  182.   for (i = 0; i < JSTimeSize; i++)
  183.   {
  184.     JSTime_arr[i].id = 0;
  185.   }
  186. }
  187. //========================================================================
  188. // ---------------------- 类javascript定时器  结束-------------------------
  189. //========================================================================
复制代码

使用方法:
  1. unsigned long timeId = 0;
  2. void task1()
  3. {
  4.   // todo
  5. }
  6. void task2()
  7. {
  8.   // todo
  9. }
  10. void task3()
  11. {
  12.   // todo
  13. }
  14. void task4()
  15. {
  16.   // 允许嵌套调用
  17.   setTimeout(task2, 1000); // 1秒后执行一次task2
  18.   setTimeout(task3, 2000); // 2秒后执行一次task3
  19. }
  20. void task5()
  21. {
  22.   // 先清除定时器
  23.   // 再设置定时器, 用于防抖延时执行
  24.   clearTime(timeId);
  25.   timeId = setInterval(task1, 500); // 每隔1秒执行一次task1
  26. }
  27. void setup()
  28. {
  29.   //1: 初始化JSTime
  30.   JSTime_init();
  31.   //2: 设置定时器
  32.   timeId = setInterval(task1, 1000); // 每隔1秒执行一次task1
  33.   setTimeout(task2, 2000); // 2秒后执行一次task2
  34.   setTimeout(task3, 3000); // 3秒后执行一次task3
  35.   setTimeout(task4, 4000); // 4秒后执行一次task4
  36.   setTimeout(task5, 5000); // 5秒后执行一次task5
  37. }
  38. void main(void)
  39. {
  40.   setup();
  41.   while (1)
  42.   {
  43.     // 3: 刷新JSTime
  44.     JSTime_refresh();
  45.   }
  46. }
复制代码




回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-1 19:07 , Processed in 0.107967 second(s), 45 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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