谢谢这位兄弟提醒。但多媒体定时器精度很高
windows定时器精度都不高,要看主机,每个主机延时不一样,还有界面的一些操作占用时间比较多,都有影响
windows定时器精度都不高,要看主机,每个主机延时不一样,还有界面的一些操作占用时间比较多,都有影响
解决方案 »
- ActiveX控件属性页名称问题
- 怎么打包软件啊?
- SMTP 密码验证错误
- 关于获得本机器IP的问题!
- 有人编译过apache么?我想问一下,如何去掉那个恼人的apache2.0.52(win32)字样?哪里可以去掉?
- ddk软件包在哪些网站有下载?
- 如何把源代码里面的相对地址转换成绝对地址?
- 如何在拆分窗口中得到拖动分割条的事件或消息什么的??
- !!!!!!!!!!!!!为什么delete一个对象会导致stack overflow,而且没法跟踪?
- 怎么使 动态创建的radiobutton 有效 急急!!!!
- 安装钩子的程序退出前未卸载钩子,那么程序退出后,这个钩子是不是还留在系统中?还起着作用?
- 为什么ATL在添加方法的时候,参数选项里面没有SAFEARRAY?
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices可以看到他用的也是重叠IO
windows定时器精度都不高,要看主机,每个主机延时不一样,还有界面的一些操作占用时间比较多,都有影响
谢谢这位兄弟,你的话里界面操作用时比较多,这点到时提醒我,我思考思考。
因为优先度比较 低 ,所以 总是有 误差 的,但 不 会 几百 ms。
{
MessageBox(_T("定时器启动失败"), _T("错误"), MB_OK|MB_ICONWARNING);
}#define SENDTIME 200 //间隔时间郁闷中
会不会 过度 包装。
void CALLBACK TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
static bool bBenginEnd = false;
if (QueryPerformanceFrequency(&Frequency))
{
//*
bBenginEnd = !bBenginEnd;
if (bBenginEnd)
{
QueryPerformanceCounter(&BeginTime);
}
else
{
QueryPerformanceCounter(&EndTime);
}
//*/ /*
QueryPerformanceCounter(&BeginTime);
//*/ CtestDlg* testdlg = (CtestDlg*)dwUser;
testdlg->SendMessage(MYTIMER_MSG, (WPARAM)uID, (LPARAM)0); /*
QueryPerformanceCounter(&EndTime);
//*/ if (EndTime.QuadPart > BeginTime.QuadPart)
{
TRACE("using time is %lu us\n", ((1000000*(EndTime.QuadPart - BeginTime.QuadPart))/ Frequency.QuadPart));
}
}
}
根据woshi_hujunjun的思路,在多媒体定时器回调函数TimerProc中进行两项简单测试,一个测试TimerProc函数被调用的时间间隔;一个测试自定义定时消息MYTIMER_MSG的处理时间(详细代码如上),两项测试分别单独进行直到检测到数据错误。经几个小时测试发现回调函数TimerProc函数被调用的时间间隔一直在200ms左右,自定义定时消息MYTIMER_MSG的处理时间不超过10ms,SendMessage发送消息之后要等待消息返回才进行下一步操作,所以可以粗略测试,在测试过程中还发现鼠标点击最小化、最大化网页,数据发送都会有一定的延迟。因此我怀疑我用的串口类有问题,我用的串口类是Remon Spekreijse的串口类(刚学串口,不会写,网上有源码,所以..),可能是在设置写事件(SetEvent(m_hWriteEvent);)之后,由于某个原因串口类没收到这个写事件,所以就有了如标题一样的结果。这是我的猜测,我感觉一个人的脑袋瓜不够,各位兄弟给点思路或见解啊,求解求指导。(顺便说下我用这个串口类遇到一个比较郁闷的问题,就是它在win7下定时发送数据不行,但在window xp却可以,后来弄了好久才解决这个问题,求吐血)。以下是部分测试数据
1、TimerProc函数被调用的时间间隔
using time is 200005 us
using time is 200061 us
using time is 200054 us
using time is 200011 us
using time is 200070 us
using time is 200130 us
using time is 200074 us
using time is 199945 us
using time is 200003 us2、定时消息MYTIMER_MSG的处理时间
using time is 4540 us
using time is 3540 us
using time is 4418 us
using time is 3476 us
using time is 4061 us
using time is 4621 us
using time is 7818 us
using time is 4457 us
using time is 2843 us3、点击IE网页最大化按钮时数据发送的延迟时间(捕捉到一组数据)
16:07:56.432(时间格式:分:秒:毫秒)
16:07:56.632
16:07:56.953
16:07:57.114
16:07:57.233
16:07:57.433
16: 07:57.632
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices可以看到他用的也是重叠IO
虽然还不清楚阻塞是不是导致你的问题的原因,不过单纯就上面这个问题,打开串口时使用OVERLAPPED(话说WindowsNT以后都不支持非OL了)不一定意味着操作过程的效果是非阻塞的。比如要是LastError是IOPending时就一直while下去的话、或者WaitForXXXObject里用了INFINATE,这种跟阻塞比起来没太大优势。
个人理解哈,学习关注中...
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices可以看到他用的也是重叠IO
虽然还不清楚阻塞是不是导致你的问题的原因,不过单纯就上面这个问题,打开串口时使用OVERLAPPED(话说WindowsNT以后都不支持非OL了)不一定意味着操作过程的效果是非阻塞的。比如要是LastError是IOPending时就一直while下去的话、或者WaitForXXXObject里用了INFINATE,这种跟阻塞比起来没太大优势。
个人理解哈,学习关注中...嗯!兄弟,照你这样说,不用while,不用INFINATE,如何实现非阻塞式操作?定期检测?超时设定或其他?我现在使用的CSerialPort串口类就是设定超时的方式。有没有在串口接收到数据之后有个回调函数通知我们,这样的话我们就不必等了。
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices可以看到他用的也是重叠IO
虽然还不清楚阻塞是不是导致你的问题的原因,不过单纯就上面这个问题,打开串口时使用OVERLAPPED(话说WindowsNT以后都不支持非OL了)不一定意味着操作过程的效果是非阻塞的。比如要是LastError是IOPending时就一直while下去的话、或者WaitForXXXObject里用了INFINATE,这种跟阻塞比起来没太大优势。
个人理解哈,学习关注中...嗯!兄弟,照你这样说,不用while,不用INFINATE,如何实现非阻塞式操作?定期检测?超时设定或其他?我现在使用的CSerialPort串口类就是设定超时的方式。有没有在串口接收到数据之后有个回调函数通知我们,这样的话我们就不必等了。这个,咱还真不知道。
话说咱其实水平也低——看咱滴等级就知道菜鸟跟菜鸟——但也干脆直接用WinAPI(这样才会经常出现各种意想不到的问题,但反过来想想也能多锻炼些吧),读数据的话然后开个线程死循环定期readfile到一个有临界区的buffer里,主线程需要时到临界区里取这个buffer。贼原始的法子。那个死循环的线程本身readfile是相当于阻塞的(Pending了就Sleep一小下,OVERLAPPED里的hEvent等到了就continue,超时则放弃)。这个笨方法我还想找机会看看咋改进的说
http://www.cnblogs.com/EdmundDwyane/p/3443074.html
串口助手这个对我来说没多大用,试了一下,貌似很多bug。而且同样出现如标题描述一样的现象。以下是捕捉到的一组数据。
早上看了你写的那个CxComm类,个人感觉要是同一时刻同一串口有读写操作那就悲剧了。你能写出这串口类很不错,还是感谢你的帮助。
我的从站也是一个表计,350ms是我测试出来大致较小的时间,在小可能会出现报文不完整等情况
部分代码:
while(m_bSend==TRUE)
{
for(int i=0;i<IEDCount;i++)
{
Send_Yc(i+1);
// long t1,t2,t;
long t1=GetTickCount();//程序段开始前取得系统运行时间(ms)
while(1)
{
long t2=GetTickCount();//程序段结束后取得系统运行时间(ms)
long t=t2-t1;//前后之差即 程序运行时间 (ms)
if(t>350)
{
Send_Yx(i+1);//发送报文
break;
}
}
Sleep(350);
}
}
你不妨把缓冲区大小、波特率等等增大或缩小试试,或者设法提高发送数据本身的速度。
串口助手这个对我来说没多大用,试了一下,貌似很多bug。而且同样出现如标题描述一样的现象。以下是捕捉到的一组数据。
早上看了你写的那个CxComm类,个人感觉要是同一时刻同一串口有读写操作那就悲剧了。你能写出这串口类很不错,还是感谢你的帮助。把你发现的BUG都告诉我,谢了。
发送数据本身不需要400ms,看我之前贴的截图,正常情况下从发送数据到接收第一个数据之间都没有超过50ms的,非正常情况下就是我现在的问题。关于settimer和timeSetEvent没像你研究那么深,学习了。
关于bug,没有打开串口就点击自动发送会弹出提示,但是没有关闭定时器,所以提示就有N多个,关都来不及,只能杀进程。在200ms下发送数据,接收丢字节很多(用其他的串口调试助手没发现这种情况或一天丢一两个字节)。
对于精确度要求更高的定时操作,可以试试QueryPerformanceFrequency()
和 QueryPerformanceCounter()函数。
一段 接一段的注释掉,看看注释掉哪一段就正常了,都可以尝试一下这样也不用该代码什么的,不停的测试就好了
我就是这么干的
好像 有 好多年了 反应也 可以。
那就 重起炉灶 搞一个 最简单的 程序 试试。
m_pThread->SetThreadPriority(THREAD_PRIORITY_TIME_CRITICAL);//
发送完毕后,在线程中 Sleep(200);