今天热门
热点:

cserialport类定时200ms发送数据,有时定时混乱,不是200ms而是420ms,选用多媒体定时器一样出现此问题解,cserialport420ms


PC用cserialport类setTimer定时200ms发送数据给MCU,有时定时混乱,不是200ms而是420ms,下一个数据又间隔十几毫秒发送,导致数据接收出现乱码,选用多媒体定时器一样出现此问题。求解

解决方案

定时器消息级别比较低  延时很正常  你要很精确的话 还是自己实现吧...

引用
Quote: 引用

定时器消息级别比较低  延时很正常  你要很精确的话 还是自己实现吧...

谢谢这位兄弟提醒。但多媒体定时器精度很高

windows定时器精度都不高,要看主机,每个主机延时不一样,还有界面的一些操作占用时间比较多,都有影响

估计你用了阻塞式操作

恐怕是系统 线程 调度 问题,发送程序 不能按时 进行。

“PC用cserialport类setTimer定时200ms发送数据给MCU,有时定时混乱,不是200ms而是420ms,下一个数据又间隔十几毫秒发送,导致数据接收出现乱码,选用多媒体定时器一样出现此问题。”

总觉得 windows 下 ,要 按时 做些事是困难的,定时器 误差 不是 问题, 问题是 定时器 消息 可能 丢失, 200ms 定时, 丢一个 ,就是 200 到 400 ms。

提高 线程的 优先度 到 ‘实时’级, 可能 会 解决这个问题, 但 别的程序 的 响应 就会 有问题。

其实不用怀疑精度的问题,精度在差也都不会超过几个ms吧。

如果直接调试很难找问题

你可以在各个步骤之间打印出执行时间,看看哪个步骤耗时过长,影响了执行

找到问题 出在哪里  就应该很好解决了 



引用
Quote: 引用

Quote: 引用

Quote: 引用

使用 异步方式 比较好 (重叠IO)

这位兄弟,我就是用Remon的串口类,他是开辟一个线程,然后发数据,

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,超时则放弃)。这个笨方法我还想找机会看看咋改进的说。。。

我使用CSerialPort类每个350ms发送一条报文,接收都没问题,发送报文我是重新开辟一条线程的。
我的从站也是一个表计,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);
}
}

不是定时器的问题,是串口发送速度不够。你让它200MS发送一次,可是发送数据本身需要400MS,不就延时了吗。要是用SetTimer还好,系统会移除多余的WM_TIMER消息,只留一个在消息队列。要是用timeSetEvent,那就完了,随时间推迟越来越堵。
你不妨把缓冲区大小、波特率等等增大或缩小试试,或者设法提高发送数据本身的速度。

引用
Quote: 引用

Sleep是为了使不同从站地址发报文的时间间隔,其实使用GetTickCount再得个350ms间隔也行,当时为了方便就写了个Sleep。

350ms貌似不行了。还得改改


这个问题还没解决啊

不应该是发送时间的问题吧,哪里需要那么长时间啊,最多也就是发几十个字节的数据。

比如波特率是9600,那1ms都要发1.2个字节,你这里才发14个字节,能耗多少时间啊 

这个发送速度不会错的

看看 ontimer 里面哪里耗时多了吧,还是

多媒体定时器timeSetEvent()函数,定时精度为ms级。
对于精确度要求更高的定时操作,可以试试QueryPerformanceFrequency()
和 QueryPerformanceCounter()函数。

引用
Quote: 引用

如果不是 ontimer里面耗时过多的话 ,就是你的串口类有问题。

兄弟我这问题一测试就要好几个小时,程序改改,拖拖拉拉,一天测试最多也就两回。你串口中断的问题我之前看了,我也不知道怎么弄。ontimer现在不用了。到底哪里出问题,现在我也不敢下定论。

刚才仔细看代码的时候发现之前测试TimerProc函数被调用的时间间隔有问题(详细代码请看17楼),就是当EndTime.QuadPart < BeginTime.QuadPart的情况没写出来。这样的话实际有两个时间间隔,而我只写出其中一个时间间隔。


你不如先把循环中的其它代码全部注释掉,再一段一段的添加上,看看添上哪段后出问题,这样还可能快一点。

或者 
 一段 接一段的注释掉,看看注释掉哪一段就正常了,都可以尝试一下

这样也不用该代码什么的,不停的测试就好了

 在接收完一帧报文立即使用:PurgeComm(mycom.m_hComm, PURGE_RXCLEAR);//清空接收缓冲区,
  我就是这么干的 

使用 异步方式 比较好 (重叠IO)

windows 定时器 就是 dos 的 定时 中断 18/每秒。
因为优先度比较 低 ,所以 总是有 误差 的,但 不 会 几百 ms。

“AccessPort137”会不会有别的问题。
会不会 过度 包装。

微软自带的 MScomm 不能用 ?

我是 不喜欢用 串口控件的 , 从 CreateFile 起 就可以了。

"木已成舟" 难办了。

我搜索了一下“Remon的串口”
好像 有 好多年了 反应也 可以。
那就 重起炉灶 搞一个 最简单的 程序 试试。

即:
m_pThread->SetThreadPriority(THREAD_PRIORITY_TIME_CRITICAL);//
发送完毕后,在线程中 Sleep(200);

www.zrccd.nettrue/topics/20180106/6319.htmlTechArticlecserialport类定时200ms发送数据,有时定时混乱,不是200ms而是420ms,选用多媒体定时器一样出现此问题解,cserialport420ms PC用cserialport类setTimer定时200ms发送数据给MCU,有时定时混乱,不是...

相关文章

    暂无相关文章

用户评论

大家都在看