stc里没有32位的定时器获取系统us的定时太麻烦了, 还要安全取值才行, 要不然会出现时间回退,
使用定时器0来进行系统us计时, 系统运行在40Mhz,8位预分频器设置0x27, 自动重装载值为0, 溢出时间为65536us,
然后再设置一个变量来记录溢出次数, 这样就可以实时获取系统的us计时了
受javascript定时器的启发, 可以实现这种软件定时器跟js的语法一样
- //========================================================================
- // ---------------------- 类javascript定时器 开始-------------------------
- //========================================================================
- #define JSTimeSize 10 // 初始化定时的个数, 数量越多, 运行效率越低, 够用就好
-
- unsigned long globeTime = 0; // 定时器0溢出次数
- unsigned long system_us = 0; // 系统微秒计时
- unsigned long tempGlobeTime = 0; // 临时存储globeTime
- unsigned char tempTH0 = 0; // 临时存储TH0
- unsigned char tempTL0 = 0; // 临时存储TL0
- struct JSTimeStruct
- {
- unsigned long id; // 定时器id,用来取消定时器, id>0x80000000是setTimeout的id, id<0x80000000是setInterval的id
- unsigned long startTime; // 开始执行的时间, 单位us
- unsigned long periodTime; // 延时的时间 或者 间隔执行的时间, 单位us
- void (*callback)(); // 回调函数
- };
- struct JSTimeStruct JSTime_arr[JSTimeSize];
- // 获取系统微秒计时
- unsigned long micros()
- {
- // 系统微秒计时, 保持严格单调递增, 禁止出现时间倒退, 32位溢出时间为71分钟
- // globeTime*65536+(TH0-0)*256+(TL0-0)
- do
- {
- // 如果在读取过程中发生溢出,重新读取
- tempTH0 = TH0;
- tempTL0 = TL0;
- tempGlobeTime = globeTime;
- } while (tempTH0 != TH0 || tempTL0 != TL0 || tempGlobeTime != globeTime);
-
- // 计算当前时间
- system_us = (tempGlobeTime << 16) + (tempTH0 << 8 | tempTL0);
- return system_us;
- }
- // 定时器0中断
- void T_IRQ0(void) interrupt 1 using 1
- {
- globeTime++; // 定时器0溢出次数
- }
- // 定时器0初始化
- void Timer0_Init(void) // 65536微秒@40.000MHz
- {
- TM0PS = 0x27; // 设置定时器时钟预分频
- AUXR |= 0x80; // 定时器时钟1T模式
- TMOD &= 0xF0; // 设置定时器模式
- TL0 = 0x00; // 设置定时初始值
- TH0 = 0x00; // 设置定时初始值
- TF0 = 0; // 清除TF0标志
- TR0 = 1; // 定时器0开始计时
- ET0 = 1; // 打开定时器0中断
- IPH |= 0x02; // 设置定时器0的中断的优先级为高
- IP |= 0x02; // 设置定时器0的中断的优先级为高
- }
- // 定时器初始化函数
- void JSTime_init()
- {
- unsigned char i = 0;
- for (i = 0; i < JSTimeSize; i++)
- {
- JSTime_arr[i].callback = 0;
- JSTime_arr[i].periodTime = 0;
- JSTime_arr[i].startTime = 0;
- JSTime_arr[i].id = 0;
- }
- Timer0_Init();
- }
- unsigned long JSTime_createTimeId = 0x80000000; // `setTimeout`的id
- unsigned long JSTime_createIntervalTimeId = 1; // `setInterval`的id
- // loop循环中不断刷新定时器, JSTime_refresh中的局部变量变成全局变量
- unsigned long JSTime_cacheId = 0; // 缓存id
- unsigned long JSTime_currentTime = 0;
- unsigned char JSTime_i = 0;
- unsigned char JSTime_isFree = 0;
- void JSTime_refresh()
- {
- JSTime_currentTime = micros();
- for (JSTime_i = 0; JSTime_i < JSTimeSize; JSTime_i++)
- {
- if (JSTime_arr[JSTime_i].id != 0)
- {
- if (JSTime_currentTime - JSTime_arr[JSTime_i].startTime >=
- JSTime_arr[JSTime_i].periodTime)
- {
- JSTime_cacheId = JSTime_arr[JSTime_i].id;
- if (JSTime_cacheId >= 0x80000000)
- {
- // setTimeout 执行完毕就销毁
- JSTime_isFree = 1;
- }
- else
- {
- JSTime_isFree = 0;
- // setInteval 不断进行
- JSTime_arr[JSTime_i].startTime = JSTime_currentTime;
- }
- if (JSTime_arr[JSTime_i].callback)
- {
- JSTime_arr[JSTime_i].callback();
- JSTime_currentTime = micros();
- }
- // 防止在回调函数里调用了 clearTime 而引发bug
- if (JSTime_isFree == 1 && JSTime_arr[JSTime_i].id == JSTime_cacheId)
- {
- // setTimeout 执行完毕就销毁
- JSTime_arr[JSTime_i].id = 0;
- }
- }
- }
- }
- }
- // 延时执行, delayTime单位为us
- unsigned long setTimeout_us(void (*callback)(), uint32 delayTime)
- {
- unsigned char i = 0;
- for (i = 0; i < JSTimeSize; i++)
- {
- // 找出失效的 结构体
- if (JSTime_arr[i].id == 0)
- {
- JSTime_arr[i].callback = callback;
- JSTime_arr[i].periodTime = delayTime;
- JSTime_arr[i].startTime = micros();
- if (JSTime_createTimeId > 0xfffffff0)
- {
- JSTime_createTimeId = 0x80000000;
- }
- JSTime_createTimeId++;
- JSTime_arr[i].id = JSTime_createTimeId;
- return JSTime_createTimeId;
- }
- }
- return 0;
- }
- // 延时执行, delayTime单位为ms
- unsigned long setTimeout(void (*callback)(), uint32 delayTime)
- {
- return setTimeout_us(callback, delayTime * 1000);
- }
- // 间隔时间执行, intervalTime单位为us
- unsigned long setInterval_us(void (*callback)(), uint32 intervalTime)
- {
- unsigned char i = 0;
- for (i = 0; i < JSTimeSize; i++)
- {
- // 找出失效的 结构体
- if (JSTime_arr[i].id == 0)
- {
- JSTime_arr[i].startTime = micros();
- JSTime_arr[i].callback = callback;
- JSTime_arr[i].periodTime = intervalTime;
- if (JSTime_createIntervalTimeId > 0x7ffffff0)
- {
- JSTime_createIntervalTimeId = 1;
- }
- JSTime_createIntervalTimeId++;
- JSTime_arr[i].id = JSTime_createIntervalTimeId;
- return JSTime_createIntervalTimeId;
- }
- }
- return 0;
- }
- // 间隔时间执行, intervalTime单位为ms
- unsigned long setInterval(void (*callback)(), uint32 intervalTime)
- {
- return setInterval_us(callback, intervalTime * 1000);
- }
- // 停止软件定时器计时
- void clearTime(unsigned long timeId)
- {
- unsigned char i = 0;
- for (i = 0; i < JSTimeSize; i++)
- {
- if (timeId == JSTime_arr[i].id)
- {
- JSTime_arr[i].id = 0;
- }
- }
- }
- // 停止所有软件定时器计时
- void clearAllTime()
- {
- unsigned char i = 0;
- for (i = 0; i < JSTimeSize; i++)
- {
- JSTime_arr[i].id = 0;
- }
- }
- //========================================================================
- // ---------------------- 类javascript定时器 结束-------------------------
- //========================================================================
复制代码
使用方法:
- unsigned long timeId = 0;
-
- void task1()
- {
- // todo
- }
-
- void task2()
- {
- // todo
- }
-
- void task3()
- {
- // todo
- }
-
- void task4()
- {
- // 允许嵌套调用
- setTimeout(task2, 1000); // 1秒后执行一次task2
- setTimeout(task3, 2000); // 2秒后执行一次task3
- }
-
- void task5()
- {
- // 先清除定时器
- // 再设置定时器, 用于防抖延时执行
- clearTime(timeId);
- timeId = setInterval(task1, 500); // 每隔1秒执行一次task1
- }
-
- void setup()
- {
- //1: 初始化JSTime
- JSTime_init();
-
- //2: 设置定时器
- timeId = setInterval(task1, 1000); // 每隔1秒执行一次task1
- setTimeout(task2, 2000); // 2秒后执行一次task2
- setTimeout(task3, 3000); // 3秒后执行一次task3
- setTimeout(task4, 4000); // 4秒后执行一次task4
- setTimeout(task5, 5000); // 5秒后执行一次task5
- }
-
- void main(void)
- {
- setup();
- while (1)
- {
- // 3: 刷新JSTime
- JSTime_refresh();
- }
- }
复制代码
|