搜索
bottom↓
回复: 32

状态机调用的函数有延时怎么处理?

[复制链接]

出0入296汤圆

发表于 2013-1-8 12:45:42 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2013-1-8 12:49 编辑

延时函数也要用状态机来写:软件延时还是定时器延时都无所谓的,都有具体写法。

对于延时,其实不推荐写成函数来调用,而推荐做成资源,我记得我有一个很老的帖子里面有提到过,具体接口是这样的:
1、有一个申请延时的函数request_delay(),然后把延时时间传递进去,这个函数会返回一个句柄
2、如果句柄有效,则可以通过is_time_out()函数利用传入的句柄来查询是否所需的延时已经到时间了

可以看出,这个接口是把延时当成后台资源的,这并不难做,用一个定时器维护一个计数器就可以做到。并且非常适合
状态机环境使用。但是需要注意的是,句柄是有生命周期的,一旦一个句柄代表的延时到达时间了,或者说timeout了,
则查询的过程会自动注销这个句柄。

你可以自己根据这个思路来设计下这种结构,如果有问题,我找找看能不能找到过去的那个代码……

厄……居然找到代码了……单击这里下载

下面是接口部分的定义——貌似是我2年前的风格……呵呵……凑合着用吧

  1. #ifndef _USE_MULTI_DELAY_H_
  2. #define _USE_MULTI_DELAY_H_

  3. /*-----------------------------*
  4. *  include head files         *
  5. *----------------------------*/
  6. #include "..\..\..\utils\compiler.h"
  7. #include "Multi-Delay_cfg.h"

  8. /*-----------------------------*
  9. *  Macros for constants       *
  10. *----------------------------*/

  11. /*-----------------------------*
  12. *  Macros for others          *
  13. *----------------------------*/

  14. /*-----------------------------*
  15. *  type definitions           *
  16. *----------------------------*/
  17. typedef enum DelayState
  18. {
  19.     DELAY_DOWN_COUNTING,
  20.     DELAY_TIME_OUT,
  21.     DELAY_ERROR
  22. }ES_DELAY_STATE;

  23. /*-----------------------------*
  24. *  public functions prototypes*
  25. *----------------------------*/
  26. extern void MutiDelay_INIT(void);
  27. extern uint16_t Add_Delay_Item(uint16_t hwTime);
  28. extern ES_DELAY_STATE If_Time_Out(uint16_t hwDHandl);
  29. extern void Cancel_Delay_Item(uint16_t hwDHandl);

  30. #endif
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入296汤圆

发表于 2013-1-9 10:41:50 | 显示全部楼层
xivisi 发表于 2013-1-9 08:51
你就当两个线程  定时器中断去更新状态,  正常程序做状态迁移,     傻孩子是大师多看他的帖子 ...

谢谢说明。
如果你有调度器或者操作系统,那么就在中断里面设置信号量,在状态机里面等待信号量。
如果你是裸机,就在中断里面设置一个标志位,在状态机里面等标志位就可以了。

出0入296汤圆

发表于 2013-1-10 15:07:01 | 显示全部楼层
wuqiushan741826 发表于 2013-1-9 16:59
傻孩子,人代码意图,没有看懂,可否详细分析一下。。。

不好意思哈,暂时可能没有时间来进行详细分析。但是我可以说以下基本思路,然后你就着这个思路
尝试去看代码,有问题的话我们再进一步具体讨论,好不?

首先,我说说这个模块的基本功能。
    这个代码利用一个定时器维护一个32位的计数器,并通过这个计数器同时提供若干路延时的标定
服务。所谓标定服务是指,在你需要延时的时候,你通过接口函数Add_Delay_Item()申请一个你想要延时
的时间,这个时候,系统就会在后台分配一个标定名额给你,这个标定实际上就是一个时间预测,比如,
当前的32位计数器数值是x,你要延时300ms(假设定时器产生1ms中断),则这个预测的标定值就是
(x+300)。那么我们怎么知道延时到了呢?实际上你就要不停的通过接口函数If_Time_Out()来查询刚刚
你登记的那个标定是否到了,也就是检查现在的32位计数器是不是超过了原本的x+300,如果超过了,说明
延时到了,返回true,并注销当前的标定,如果没有超过,直接返回false。

这个服务实际上也可以叫做并行延时服务。最大的标定个数是可以通过宏来设定的,你可以从代码里面找到,
另外,每个标定在使用的时候都会获得一个不同的ID,或者叫句柄,用于查询。这个句柄一定要每次都不同,
以防止别人用过期的句柄破坏了当前有效的标定——我想你能理解,就相当于火车票上的日期能有效地防止
别人用过期的票做同班次的列车。

有一个函数是用来插入到定时器的毫秒中断处理程序里面的。其实延时的单位并不是固定的1ms,如果定时器
中断是10ms,那么这个延时最小单位就是10ms,以此类推。

出0入296汤圆

发表于 2013-1-12 00:57:19 | 显示全部楼层
ele_eye 发表于 2013-1-11 22:39
这个思路不错

以前在TI 的代码里面也是看到的类似的处理方法,不过更具有操作性

消息机制会增加系统的复杂度。如果要做消息,其实可以做的更彻底。现在的延时是基于查询的,
如果要做成消息驱动的,就可以做成真阻塞的地,状态机在等待延时的时候,实际上不仅注册延时,
注册的时候将状态机自己的任务本身也作为TAG注册到里面去了,同时这个任务也从系统的就绪队列
里面删除了——这个任务就真正的阻塞了,当timeout消息被推送出来的时候,实际上会先把TAG里面
保存的任务重新加入到就绪队列里面。

出0入296汤圆

发表于 2013-12-17 10:23:35 | 显示全部楼层
卖菜老汉 发表于 2013-12-16 22:07
傻孩子 可否介绍本消息驱动方面的书籍

看深入浅出MFC的头6章

出0入296汤圆

发表于 2014-9-15 21:22:20 | 显示全部楼层
黄晨0410 发表于 2014-9-15 20:59
在这个程序中会不会产生计时回绕问题,如果产生怎样避免,例如:linux中jiffies回绕 ...

我计算过这个时间,基本上是天文数字,另外,你没有注意到,我代码另外一个地方,如果判断当前没有任何延时,就自动让
计数器清0。这段代码意思就是说,在天文数字的时间范围内,只要有一小段时间没有任何延时,那么就会从头开始,这是一种
用大概率避免绕回的方式。

出0入296汤圆

发表于 2014-9-16 10:22:27 | 显示全部楼层
黄晨0410 发表于 2014-9-15 21:44
1:因为wTimer为uint32_t 范围为:0xffffffff = 4294967295 就算时钟节拍为1ms计数一次,也要计算到 49天才 ...

是的,49天……
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-28 17:46

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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