我执行,超过一个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
对象是否在指定的超时期限内更新。所以每个消息对象都需要实现自己的超时(因为它们根据消息而不同)。
所有消息由电机控制器定期发送的,但也有一些想要获取其内容改变传输(但他们也将定期,如果内容不改变发送)。这意味着以超过标称速率接收消息是可以的,但它应该在最大超时时间内至少出现一次。
的USB设备提供时间戳与消息一起,所以我有机会获得这些信息。时间戳不反映当前时间,它是一个unsigned long
数字,分辨率为微秒,设备每次收到消息时都会更新。我怀疑该设备从我调用其初始化函数的时间开始,从0
开始递增。一对夫妇不同的方式我能想到实现这个的是:
每个报文对象启动运行无限等待(WaitForSingleObject的)的超时时间的线程。在超时之后,它检查一个计数器变量(在等待之前被缓存了)是否增加了。如果不是,它将标记该消息的标志设置为陈旧。每次
rxThread()
更新该消息对象时,计数器都会递增。rxThread()
除填充消息外,还遍历消息列表并检查每个消息的最后一次更新的时间戳。如果时间戳超过超时时间,则将该消息标记为陈旧。此方法可能会遇到所需处理量的问题。在大多数机器上它可能不会成为问题,但是这些代码需要在一台速度很慢的“工业计算机”上运行。
我真的很感激你的想法和建议,如何实现这一点。除了我刚才提到的两个之外,我都接受了其他想法。我使用的是Visual Studio 2005,因为USB设备驱动程序仅适用于Windows,所以跨平台可移植性不是什么大问题。目前我正在监控大约8条消息,但如果解决方案足够轻便,我可以添加多个(也许是另外8个)更多,而不会遇到处理马力限制的情况,那将会很不错。
在此先感谢, Ashish。
时间戳不是当前时间,它只是一个具有微秒分辨率的'unsigned long'计数器,它将继续滚动。因此,确定超时的唯一方法是取两个时间戳的差值或缓存现有时间戳,然后等待超时期限并查看时间戳是否已更新。 'getSpeed()'本身并不是周期性的调用,所以它不知道消息什么时候通过查看时间戳数字来更新。我会用时间戳的详细信息更新描述。 – Praetorian 2010-09-29 02:36:34
您可以根据收到的值存储自己的时间戳。这与您的第二个实现想法的工作方式大致相同。 – Hasturkun 2010-09-29 02:47:49
@ Hasturkun在那里有个好主意。我只在消息上存储自己的时间戳,然后在'getSpeed()'中检查'now - timestamp'。注意:如果你的超时值需要很小和/或精确,实现可能会很费力。在Windows下可以依赖的最佳精度是按照gettickcount()〜〜16ms(因为QueryPerformanceCounter通常遭受核心错误同步问题,MS责备BIOS/HAL实现者,可能容易上百或上千毫秒)。 – 2010-09-29 04:10:26