chengxindang
驱动牛犊
驱动牛犊
  • 注册日期2004-08-16
  • 最后登录2011-07-24
  • 粉丝0
  • 关注0
  • 积分157分
  • 威望35点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
阅读:2336回复:3

多媒体定时器涉及到什么 ?? 急急 给200分!

楼主#
更多 发布于:2005-07-15 22:00
  多媒体定时器涉及到什么 ?? 急急 给200分!
爱,使人死亡,情,让人疯狂!
caesun
驱动小牛
驱动小牛
  • 注册日期2001-12-10
  • 最后登录2006-12-01
  • 粉丝0
  • 关注0
  • 积分290分
  • 威望30点
  • 贡献值393点
  • 好评度21点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-07-16 08:32
...?

Platform SDK Doc -> Graphics and Multimedia Services -> Windows Multimedia -> Multimedia Input -> multimedia timers

或者搜一下 timeSetEvent
driverlanser
驱动牛犊
驱动牛犊
  • 注册日期2005-07-19
  • 最后登录2005-10-30
  • 粉丝0
  • 关注0
  • 积分39分
  • 威望8点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2005-07-23 17:19
timeSetEvent?
wyq521003
驱动小牛
驱动小牛
  • 注册日期2005-05-28
  • 最后登录2008-11-19
  • 粉丝0
  • 关注0
  • 积分406分
  • 威望53点
  • 贡献值10点
  • 好评度26点
  • 原创分0分
  • 专家分0分
地板#
发布于: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 啸峰工作室


 
看看这些对你有没有什么帮助。上网一查,就能查到一大堆,不用给分就可以了。我现在也是新手,我也正在搞这些事情。但愿我们能常交流。
付出多少就会收获多少
游客

返回顶部