我正在实现一个通过USB设备与电机控制器通信的类。 我有一切工作,除了一个方式来表明通过通信链接获取的参数是否“新鲜”。 我到目前为止:
class MyCommClass { public: bool getSpeed( double *speed ); private: void rxThread(); struct MsgBase { /* .. */ }; struct Msg1 : public MsgBase { /* .. */ }; struct Msg2 : public MsgBase { /* .. */ }; /* .. */ struct MsgN : public MsgBase { /* .. */ }; Msg1 msg1; Msg2 msg2; /* .. */ MsgN msgn; std::map< unsigned long id, MsgBase *msg > messages; };
rxThead()
是在单独的线程中运行的无限循环,检查USB设备的可用消息。 每条消息都有一个唯一的标识符, rxThread()
用它来将它粘贴到正确的msgx
对象中。 我需要的是,当用户调用getSpeed()
函数时,需要能够判断当前速度值是否为“新鲜”或“过时”,即包含速度值的msgx
对象是否在指定的超时时间。 所以每个消息对象都需要实现自己的超时(因为每个消息都不相同)。
所有信息都由电机控制器周期性地传送,但也有一些信息在其内容发生变化时立即传送(但是如果内容不变则也会周期性传送)。 这意味着接收超过标称速率的消息是可以的,但是在最大超时期限内应至less出现一次。
USB设备提供时间戳和消息,所以我可以访问这些信息。 时间戳不反映当前时间,它是一个unsigned long
整数,分辨率为微秒,设备每次收到消息时都会更新。 我怀疑设备只是从我从它的初始化函数的时间开始递增。 我可以想到实现这个的几种不同的方式是:
每个消息对象启动一个无限期等待的线程(WaitForSingleObject)超时期限。 在超时之后,它检查一个计数器variables(在等待之前caching了)是否增加了。 如果没有,则将标记该消息的标志设置为陈旧。 每次rxThread()
更新消息对象时,计数器都会增加。
除填充消息之外, rxThread()
还遍历消息列表并检查每个上次更新的时间戳。 如果时间戳超过超时,则将该消息标记为陈旧。 这种方法可能在处理所需的数量上有问题。 在大多数机器上这可能不是问题,但是这个代码需要在一台速度很慢的“工业计算机”上运行。
我真的很感激你的想法和build议如何实现这一点。 除了上面提到的两个之外,我对这些想法都是开放的。 我正在使用Visual Studio 2005,跨平台的可移植性不是一个大问题,因为USB设备驱动程序只有Windows。 目前我正在监视大约8条消息,但是如果解决scheme足够轻便,我可以添加几个(也许是另外8个)更多,而不会遇到处理马力限制的情况。
在此先感谢,Ashish。
如果您不需要在邮件过期时立即执行某些操作,则我认为如果您在每条邮件中同时存储计算机的时间和设备的时间戳,则可以跳过使用计时器:
#include <ctime> #include <climits> class TimeStamps { public: std::time_t sys_time() const; // in seconds unsigned long dev_time() const; // in ms /* .. */ }; class MyCommClass { /* .. */ private: struct MsgBase { TimeStamps time; /* .. */ }; TimeStamps most_recent_time; bool msg_stale(MsgBase const& msg, unsigned long ms_timeout) const { if (most_recent_time.sys_time() - msg.time.sys_time() > ULONG_MAX/1000) return true; // device timestamps have wrapped around // Note the subtraction may "wrap". return most_recent_time.dev_time() - msg.time.dev_time() >= ms_timeout; } /* .. */ };
当然,如果您愿意,TimeStamps可以是MyCommClass中的另一个嵌套类。
最后,每次收到消息时,rxThread()应该设置适当的消息的TimeStamps对象和most_recent_time成员。 如果在接收到任何其他类型的最后一条消息之后,所有这些都不会检测到过时的消息,但是在问题中您的第二个可能的解决方案会有同样的问题,所以也许没关系。 如果它确实很重要,如果msg_stale()也比较当前时间,这样的东西仍然可以工作。
如何在邮件中存储时间戳,并getSpeed()
检查时间戳?