prince2010 发表于 2021-3-22 11:00:18

裸机程序多级函数调用内部的非阻塞延时怎么实现?

如题~~


有兄弟研究过吗?

security 发表于 2021-3-22 11:14:53

这标题读起来很费力。
或许是用 tick 算,到指定时间,执行指定的动作吧。

hameyou 发表于 2021-3-22 12:10:30

这种只能用状态机来实现了

aammoo 发表于 2021-3-22 12:47:21

状态机+1      

kebaojun305 发表于 2021-3-22 14:24:22

状态机+1

panda1985 发表于 2021-3-22 14:51:27

状态机+1

prince2010 发表于 2021-3-22 15:45:18

aammoo 发表于 2021-3-22 12:47
状态机+1

状态机肯定是状态机,主要是这样很别扭,特别是延时的位置在几层函数调用的下层,

不知道我描述得对不对?

security 发表于 2021-3-22 16:18:52

prince2010 发表于 2021-3-22 15:45
状态机肯定是状态机,主要是这样很别扭,特别是延时的位置在几层函数调用的下层,

不知道我描述得对不对 ...

很短的话,就直接死等吧,
不短的话,只能是那样,想不难看的话,就得想法子,减少嵌套吧。

对于 OS 而言,这种情况的延时,就是转去执行其他任务,时间到了,再回来。
本质上,就类似于裸奔的拆分状态,用 tick 计时,然后等待时间到来,再执行,所谓的时间触发模式吧。

jiulong855@.163 发表于 2021-3-22 16:35:29

定时器分时复用不行吗?

chensi007 发表于 2021-3-23 13:30:49

本帖最后由 chensi007 于 2021-3-23 13:32 编辑

jiulong855@.163 发表于 2021-3-22 16:35
定时器分时复用不行吗?

是个好主意。

nanfang2000 发表于 2021-3-23 14:08:10

jiulong855@.163 发表于 2021-3-22 16:35
定时器分时复用不行吗?

怎么复用?求教

擦鞋匠 发表于 2021-3-23 14:29:57

nanfang2000 发表于 2021-3-23 14:08
怎么复用?求教

我来谈下我的理解,理解有误的地方,还请各位指教!

额,这玩意我感觉有点类似Linux底半部机制的思想。
备注:这里所说的所有任务都是非阻塞的,如果有阻塞的任务,确保拆分成非阻塞的任务。
实时性要求最高的任务:
当然是放在硬件中断服务程序里执行。
实时性要求次高的任务:
通过硬件定时器实现软件一个软件定时器,软件定时器可以实现每间隔10ms或者100ms等调用一次任务。
实时性要求最低的任务:
直接放在大循环中,听天由命吧!

初音之恋 发表于 2021-3-23 14:36:33

多级状态机就行了,结构也能很清晰

security 发表于 2021-3-23 14:37:42

chensi007 发表于 2021-3-23 13:30
是个好主意。

现身说法一下吧,
怎么个好主意法,来解决楼主的问题。

takashiki 发表于 2021-3-23 19:19:01

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的方法处理链表,主函数大循环查找就绪的函数,就绪了就调用并从链表中移除。

t3486784401 发表于 2021-3-23 19:33:19

在 win32 结构下,多层的用户循环,可以主动调用全局 MessagePump,避免外部消息阻塞。

security 发表于 2021-3-24 09:58:49

takashiki 发表于 2021-3-23 19:19
直接上伪代码算了,算不算状态机我不知道,但是是异步调用。伪代码采用C++11,要不然的话没法满足“不别 ...

await 的实现,本质上和 Win32 的 SetTimer 一样吧。
或许也正是楼上几位同学,所说的定时器分时复用法。

但如果是这样,感觉应该不是楼主想要的。
楼主想要的应该就是很直观的串行化执行流,但又不能阻塞。
对于裸奔,这不好实现,除了在延时中,加入对关键消息的监控外(例如楼上同学所提的 MessagePump),另外的办法就是得拆分状态了,避免在此处死等。
如果上 OS 的话,则没有这问题了。

takashiki 发表于 2021-3-24 10:25:37

security 发表于 2021-3-24 09:58
await 的实现,本质上和 Win32 的 SetTimer 一样吧。
或许也正是楼上几位同学,所说的定时器分时复用法。 ...

await的实现是和SetTimer类似。但是“很直观的串行化执行流,但又不能阻塞”是使用了C++11开始的lambda表达式,函数实现看起来是串行化写的,但实际上回调延迟执行了

security 发表于 2021-3-24 10:36:00

takashiki 发表于 2021-3-24 10:25
await的实现是和SetTimer类似。但是“很直观的串行化执行流,但又不能阻塞”是使用了C++11开始的lambda表 ...

这对于楼主来说,可能过于先进了。{:lol:}

jiulong855@.163 发表于 2021-3-24 13:17:44

security 发表于 2021-3-24 09:58
await 的实现,本质上和 Win32 的 SetTimer 一样吧。
或许也正是楼上几位同学,所说的定时器分时复用法。 ...

你说得对,定时器分时复用确实是这么用的,和楼上说的await 还有ucos里的软timer都差不多一个实现方法。实时性非常高的单独用一个定时器,其他不太高的可以复用一个定时器,查询哪个状态已经就绪

nanfang2000 发表于 2021-3-24 13:59:34

所以上个RTOS就得了,就是干这活的

dykwai1 发表于 2021-3-25 08:52:25

RTOS 或者 状态机

jjj 发表于 2021-3-25 09:14:55

规范点用状态机
随意点用systick
static int time_bak=HAL_GetTick();
if((HAL_GetTick()-time_bak) > 1000){
        time_bak = HAL_GetTick();
}

一夕nandy 发表于 2021-3-25 09:19:34

状态机 定时查Flag

flamma 发表于 2021-3-25 09:19:51

状态机,但系统复杂了状态机需要很全面的考虑和设计,远不如os来的方便。资源不紧张的情况下,宁可上个os。

avr_sz 发表于 2021-3-25 18:49:32

jiulong855@.163 发表于 2021-3-24 13:17
你说得对,定时器分时复用确实是这么用的,和楼上说的await 还有ucos里的软timer都差不多一个实现方法。 ...

那么其它函数不是在定时器中断函数里面执行了吗?

avr_sz 发表于 2021-3-25 18:50:38

楼主想要的效果,还是上OS 吧

lhj200304 发表于 2021-7-2 10:20:48

状态机加时间标志位,系统维护一个时间标志,本地用一个时间的快照来做对比,时间到就执行,不到就跳过就可以了

prince2010 发表于 2021-11-25 07:57:15

avr_sz 发表于 2021-3-25 18:50
楼主想要的效果,还是上OS 吧

确实{:lol:}
页: [1]
查看完整版本: 裸机程序多级函数调用内部的非阻塞延时怎么实现?