裸机程序多级函数调用内部的非阻塞延时怎么实现?
如题~~有兄弟研究过吗?
这标题读起来很费力。
或许是用 tick 算,到指定时间,执行指定的动作吧。 这种只能用状态机来实现了 状态机+1 状态机+1 状态机+1 aammoo 发表于 2021-3-22 12:47
状态机+1
状态机肯定是状态机,主要是这样很别扭,特别是延时的位置在几层函数调用的下层,
不知道我描述得对不对? prince2010 发表于 2021-3-22 15:45
状态机肯定是状态机,主要是这样很别扭,特别是延时的位置在几层函数调用的下层,
不知道我描述得对不对 ...
很短的话,就直接死等吧,
不短的话,只能是那样,想不难看的话,就得想法子,减少嵌套吧。
对于 OS 而言,这种情况的延时,就是转去执行其他任务,时间到了,再回来。
本质上,就类似于裸奔的拆分状态,用 tick 计时,然后等待时间到来,再执行,所谓的时间触发模式吧。 定时器分时复用不行吗? 本帖最后由 chensi007 于 2021-3-23 13:32 编辑
jiulong855@.163 发表于 2021-3-22 16:35
定时器分时复用不行吗?
是个好主意。 jiulong855@.163 发表于 2021-3-22 16:35
定时器分时复用不行吗?
怎么复用?求教 nanfang2000 发表于 2021-3-23 14:08
怎么复用?求教
我来谈下我的理解,理解有误的地方,还请各位指教!
额,这玩意我感觉有点类似Linux底半部机制的思想。
备注:这里所说的所有任务都是非阻塞的,如果有阻塞的任务,确保拆分成非阻塞的任务。
实时性要求最高的任务:
当然是放在硬件中断服务程序里执行。
实时性要求次高的任务:
通过硬件定时器实现软件一个软件定时器,软件定时器可以实现每间隔10ms或者100ms等调用一次任务。
实时性要求最低的任务:
直接放在大循环中,听天由命吧! 多级状态机就行了,结构也能很清晰 chensi007 发表于 2021-3-23 13:30
是个好主意。
现身说法一下吧,
怎么个好主意法,来解决楼主的问题。 prince2010 发表于 2021-3-22 15:45
状态机肯定是状态机,主要是这样很别扭,特别是延时的位置在几层函数调用的下层,
不知道我描述得对不对 ...
直接上伪代码算了,算不算状态机我不知道,但是是异步调用。伪代码采用C++11,要不然的话没法满足“不别扭”。当然,用了后依然别扭就是了void dosomething() {
随便干点啥;
if(...) {
for(...) {
乱七八糟的嵌套一大堆;
await(1000, []{
1秒后执行的内容,而且可以循环,可以指定次数;
await(100, []{
延时1秒后再延时100ms执行的内容;
想嵌套多深就嵌套多深;
});
});
}
await(250, []{
250ms后执行的内容;
});
...await函数很简单,类似JavaScript的setTimeout函数,就是把需要延时的时间和需要执行的函数加入链表。然后使用ProtoThread的方法处理链表,主函数大循环查找就绪的函数,就绪了就调用并从链表中移除。 在 win32 结构下,多层的用户循环,可以主动调用全局 MessagePump,避免外部消息阻塞。 takashiki 发表于 2021-3-23 19:19
直接上伪代码算了,算不算状态机我不知道,但是是异步调用。伪代码采用C++11,要不然的话没法满足“不别 ...
await 的实现,本质上和 Win32 的 SetTimer 一样吧。
或许也正是楼上几位同学,所说的定时器分时复用法。
但如果是这样,感觉应该不是楼主想要的。
楼主想要的应该就是很直观的串行化执行流,但又不能阻塞。
对于裸奔,这不好实现,除了在延时中,加入对关键消息的监控外(例如楼上同学所提的 MessagePump),另外的办法就是得拆分状态了,避免在此处死等。
如果上 OS 的话,则没有这问题了。 security 发表于 2021-3-24 09:58
await 的实现,本质上和 Win32 的 SetTimer 一样吧。
或许也正是楼上几位同学,所说的定时器分时复用法。 ...
await的实现是和SetTimer类似。但是“很直观的串行化执行流,但又不能阻塞”是使用了C++11开始的lambda表达式,函数实现看起来是串行化写的,但实际上回调延迟执行了 takashiki 发表于 2021-3-24 10:25
await的实现是和SetTimer类似。但是“很直观的串行化执行流,但又不能阻塞”是使用了C++11开始的lambda表 ...
这对于楼主来说,可能过于先进了。{:lol:} security 发表于 2021-3-24 09:58
await 的实现,本质上和 Win32 的 SetTimer 一样吧。
或许也正是楼上几位同学,所说的定时器分时复用法。 ...
你说得对,定时器分时复用确实是这么用的,和楼上说的await 还有ucos里的软timer都差不多一个实现方法。实时性非常高的单独用一个定时器,其他不太高的可以复用一个定时器,查询哪个状态已经就绪 所以上个RTOS就得了,就是干这活的 RTOS 或者 状态机 规范点用状态机
随意点用systick
static int time_bak=HAL_GetTick();
if((HAL_GetTick()-time_bak) > 1000){
time_bak = HAL_GetTick();
} 状态机 定时查Flag 状态机,但系统复杂了状态机需要很全面的考虑和设计,远不如os来的方便。资源不紧张的情况下,宁可上个os。 jiulong855@.163 发表于 2021-3-24 13:17
你说得对,定时器分时复用确实是这么用的,和楼上说的await 还有ucos里的软timer都差不多一个实现方法。 ...
那么其它函数不是在定时器中断函数里面执行了吗? 楼主想要的效果,还是上OS 吧 状态机加时间标志位,系统维护一个时间标志,本地用一个时间的快照来做对比,时间到就执行,不到就跳过就可以了 avr_sz 发表于 2021-3-25 18:50
楼主想要的效果,还是上OS 吧
确实{:lol:}
页:
[1]