美国国家仪器公司为用户提供了许多高性能、高速度、高分辨率的数据采集卡,而与之接口的软件大多采用

 

Labview,Labview是一种图形化编程软件,你只需拖动控件到容器,使用起来确实比较方便。但用户无法知

 

道底层的东西,这样针对具体的应用,还要自己去理解封装得很深的函数或程序,费时、费力。因此,

c++/MFC还是一种

 

比较好的选择。如何在MFC中实现实时数据采集呢? 首先,得有定时器,定时器在指定的时间内向窗口发送

 

WM_TIMER消息,用户在消息处理函数里面完成数据采集和直观的图形或数值实现。设置定时器很简单,只需

 

简单的调用Settimer(1,100,NULL),消息映射为OnTimer()函数。但实际上,大型的程序设计一般不会采用

 

这样的方法,而是把数据采集和图形显示放到一个DLL里面,

,但如何在采集完数据后,发消息给视图类,以便视图类把数据以需要的格式显示出来,

 

曾经尝试发送用户自定义消息,但发现在视图类接收不到该用户自定义消息。因此,眼前要解决的问题关键

 

在于文档对象需要定时连续地采集数据,然后通知多个视图类以不的格式处理和显示这些数据。在文档要实

 

现有规律连续数据采集,需要有个定时器事件。

定时器事件通常通过调用UINT SetTimer(
  HWND
 hWnd,              // handle of window for timer messages
  UINT nIDEvent,          // timer identifier
  UINT uElapse,           // time-out value
  TIMERPROC lpTimerFunc   // address of timer procedure
);函数来实现,

其中, hWnd是与定时器相关联的窗口句柄,此窗口为调用线程所拥有。nIDEvent是定时器标志符,也就是

 

标识定时器的唯一性,如果要定义多个定时器,就需要用这个参数来区别该定时器。 uElapse是指隔多长时

 

间来执行后面的第四个参数所指向的函数,lpTimerFunc 是uElapse流逝后系统再次调用的函数的指针。

 

在我们对这个API函数有些认识,如要设计一个时间间隔为100毫秒的定时器事件,如SetTimer

 

(NULL,1,100,lpTimerFunc); 第一个参数为NULL是指没有与定时器相关联的窗口,因而第二个参数也被忽略

 

了,也意味着在没有窗口的文档类中,不可以实现多个定时器.

 

回调函数说明如下,VOID CALLBACK TimerProc(
  HWND
 hwnd,     // handle of window for timer messages
  UINT uMsg,     // WM_TIMER message
  UINT idEvent // timer identifier
  DWORD dwTime   // current system time
);

 

该Windows 定时器是IBM PC硬件和ROM BIOS构造的定时器的简单扩充。计算机的ROM初始化8523定时器使

 

其产生硬件中断08H,而该中断的频率为18.2Hz,即每隔54.9ms产生一次中断。也就是说该Windows定时器的

 

时间精度是54.9ms,基本上能满足数据采集的要求,因为计算机显示屏的刷新频率最快为50Hz-60Hz。

 

该定时器的优点是初始化简单,容易实现,然而缺点也显而易见,因为WM_TIMER消息的优先级比较低,只有

 

应用程序队列中的所有其他消息被处理完后,才能处理该WM_TIMER消息,不能保证数据采集的一致性。而且

 

定时器的分辨率不高,不能满足工业上日益增长德高精度的实时采集的需要。因此,这里提出了一种新的

 

多媒体定时器,该定时器的相关说明如下:

  MMRESULT timeSetEvent( UINT uDelay,
                               UINT uResolution,
                               LPTIMECALLBACK lpTimeProc,
                               WORD dwUser,
                               UINT fuEvent )

该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数, 成功后返回事件的标识符代码,否则返回NULL。函数的参数说明如下:

 uDelay:以毫秒指定事件的周期。 Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。 LpTimeProc:指向一个回调函数。 DwUser:存放用户提供的回调数据。 FuEvent:指定定时器事件类型: TIME_ONESHOT:uDelay毫秒后只产生一次事件 TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件

  具体应用时,可以通过调用timeSetEvent()函数,将需要周期性执行的任务定义在LpTimeProc回调函数 中(如:定时采样、控制等),

 

从而完成所需处理的事件。需要注意的是,任务处理的时间不能大于周期间隔时间。另外,在定时器使用完毕后, 应及时调用

 

timeKillEvent()将之释放。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐