阅读:2407回复:3
多媒体定时器涉及到什么 ?? 急急 给200分!
多媒体定时器涉及到什么 ?? 急急 给200分!
|
|
|
沙发#
发布于:2005-07-16 08:32
...?
Platform SDK Doc -> Graphics and Multimedia Services -> Windows Multimedia -> Multimedia Input -> multimedia timers 或者搜一下 timeSetEvent |
|
板凳#
发布于:2005-07-23 17:19
timeSetEvent?
|
|
地板#
发布于:2005-07-25 15:11
高速串口数据实时采集的解决方案和例程
李斌 由于工作的需要,要用VC实现通过串口波特率为115200的实时数据采集任务,然后我便开始在网上查找关于串口通讯的文章,最终的结果是一般的串口通讯文章很多,但关于实时串口通讯的文章几乎没有。完成该工作以后,我便想把自己所采用的方法和应用心得写出来,以供大家参考。 一、 串口通讯 在这一部分中我并不系统地介绍串口通讯,而只是结合该例来介绍串口通讯。 1. 打开通讯资源句柄 使用CreateFile函数,该函数原形如下: HANDLE CreateFile( LPCTSTR lpFileName, // pointer to name of the file DWORD dwDesiredAccess, // access (read-write) mode DWORD dwShareMode, // share mode LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes DWORD dwCreationDistribution, // how to create DWORD dwFlagsAndAttributes, // file attributes HANDLE hTemplateFile // handle to file with attributes to copy ); 当使用CreateFile打开通讯资源时,必须指定以下该值: 。dwShareMode参数必须是零,打开独占访问的资源 。dwCreationDistribution参数必须指定为OPEN_EXISTING标志 。hTemplateFile参数必须是NULL 2. 指定并初始化读写缓冲 程序通过调用SetupComm函数来指定读写缓冲的大小,该函数执行重新分配内部输入和输出缓冲的任务,而对输入和输出缓冲初始化时,用到PurgeComm函数。 3. DCB结构配置 当用CreateFile完成串口打开操作时,继承了设备控制块(DCB结构)设置和I/O操作的超时值。可用GetCommTimeouts来得到当前配置,如要修改此配置,需要调用SetCommTimeouts函数。 4. 设置超时值 关于超时值有一个结构COMMTIMEOUTS和两个相关的函数GetCommTimeouts和SetCommTimeouts。 注意:为完成实时串口通信必须把COMMTIMEOUTS结构的读超时参数设为MAXDWORD,而且两个读超时参数设0。只有在这种设置情况下,当读完输入缓冲器就完成读操作,而不管你得到什么字符,即使读缓冲为空。即:保证读操作立即返回!这是实现串口实时通讯的要点。 二、 多媒体定时器 基于WM_TIMER消息的定时器是低精度的,它最多可以精确到54.915毫秒,大约每秒18.2次,并且WM_TIMER消息的优先级比较低,它可能造成WM_TIMER消息的"丢失",从精度和优先级的考虑,在本例中不能使用该定时器完成任务,因此我用到了Windows多媒体服务中提供的多媒体定时器。 1. 确定最大和最小周期 可以用timeGetDevCaps函数确定定时器服务提供的最大和最小定时器事件周期,这些数值对不同的计算机是变化的,也与Windows运行方式有关。 2. 建立最小时间精度 在启动定时器事件前,应用程序必须建立想要使用的最小定时器精度,在定时器服务事件结束之后,必须清除该精度。用户可以使用timeBeginPeriod和timeEndPeriod函数来设置和清除最小定时器精度,每个timeBeginPeriod调用都必须有一个timeEndPeriod与之对应,且两个函数必须指定相同的最小精度。 3. 启动定时器事件 与该步骤相关的两个函数为timeSetEvent和timeKillEvent,读者可以查阅这两个函数,有两个值得注意的地方:一是启动定时器事件就一定要把它清楚,因为小于100ms 的定时器对CPU 的消耗是非常大的;二是在timeSetEvent调用中设置定时器回调函数时要遵循其规则。读者可以参考下面的例程。 三、 例程 本例程提供了串口类(CCOM)和多媒体定时器操作类(CMMTimer)的完整代码,有兴趣的读者可以直接把它们应用于您的程序中。 //COM.h class CCOM { public: CCOM(); virtual ~CCOM(); BOOL InitCOM(); BOOL SendCOMCode(unsigned _int8 chCode[], int nNum); DWORD GetCOMData(unsigned char *pchBuffer); void CloseCOM(); HANDLE hCOM; }; //COM.cpp CCOM::CCOM() { } CCOM::~CCOM() { } BOOL CCOM::InitCOM()//初始化串口 { DCB dCB; COMMTIMEOUTS ct; //得到打开串口,并得到串口句柄 hCOM = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(hCOM == INVALID_HANDLE_VALUE) return FALSE; //初始化串口,READBUFFER和WRITEBUFFER是用户自己定义的两个宏 SetupComm(hCOM, READBUFFER, WRITEBUFFER); PurgeComm(hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR); //设置DCB结构 if(!GetCommState(hCOM, &dCB)) { CloseHandle(hCOM); return FALSE; } dCB.BaudRate = 38400; dCB.ByteSize = 8; dCB.Parity = NOPARITY; dCB.StopBits = ONESTOPBIT; if(!SetCommState(hCOM, &dCB)) { CloseHandle(hCOM); return FALSE; } //设置超时值 ct.ReadIntervalTimeout = MAXDWORD; ct.ReadTotalTimeoutConstant = 0; ct.ReadTotalTimeoutMultiplier = 0; ct.WriteTotalTimeoutConstant = 0; ct.WriteTotalTimeoutMultiplier = 0; if(!SetCommTimeouts(hCOM, &ct)) { CloseHandle(hCOM); return FALSE; } return TRUE; } BOOL CCOM::SendCOMCode(unsigned _int8 chCode[], int nNum)//写串口 { DWORD dwWritenNum; return WriteFile(hCOM, chCode, nNum, &dwWritenNum, NULL); } DWORD CCOM::GetCOMData(unsigned char *pchBuffer)//读串口 { DWORD dwReadNum; ReadFile(hCOM, pchBuffer, READBUFFER, &dwReadNum, NULL); return dwReadNum; } void CCOM::CloseCOM() { CloseHandle(hCOM); } //MMTimer.h class CMMTimer { public: CMMTimer(); virtual ~CMMTimer(); BOOL SetMMTimer(UINT nInterval, UINT nResolution); void KillMMTimer(); UINT nTimerRes, nTimerID; }; //MMTimer.cpp //回调函数声明 void PASCAL MMTimerProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2); CMMTimer::CMMTimer() { } CMMTimer::~CMMTimer() { } BOOL CMMTimer::SetMMTimer(UINT nInterval, UINT nResolution)// 装载多媒体时钟 { //得到定时器精度 TIMECAPS tc; nTimerRes = nResolution; if (timeGetDevCaps(&tc, sizeof(TIMECAPS))==TIMERR_NOERROR) { if(nTimerRes!=min(max(tc.wPeriodMin, nTimerRes), tc.wPeriodMax)) return FALSE; } if(timeBeginPeriod(nTimerRes)==TIMERR_NOERROR)//启动定时器精度 { nTimerID = timeSetEvent(nInterval, nTimerRes, MMTimerProc, NULL, TIME_PERIODIC);//启动定时器 if(!nTimerID) return TRUE; else return FALSE; } else return FALSE; } void CMMTimer::KillMMTimer()//卸载多媒体时钟 { if(nTimerID) { timeKillEvent(nTimerID); nTimerID = 0; } timeEndPeriod(nTimerRes); } void PASCAL MMTimerProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) { //在该例中为读串口数据,您可替换为您的多媒体时钟任务 static unsigned char chData[READBUFFER]; static DWORD dwNum; dwNum = c_com.GetCOMData(chData);//串口读数 } 啸峰工作室 龚建伟制作维护 转载本站内容 请注明作者 并说明来自 http://roaringwind.best.163.com 啸峰工作室 看看这些对你有没有什么帮助。上网一查,就能查到一大堆,不用给分就可以了。我现在也是新手,我也正在搞这些事情。但愿我们能常交流。 |
|
|