改进CSDN Norains 老兄的虚拟串口

//------------------------------------------------------------------------------------------------------------------------------

// Topic:改进CSDN Norains 老兄的虚拟串口(作者:gooogleman)

// 作者:goooglemanwogoyixikexie@gliet

// 论坛账号:gooogleman (经常在CSDN出没)

// 版权:桂林电子科技大学一系科协goooglemanwogoyixikexie@gliet

// 平台:wince5.0.0 OK2440-III 5.0 BSP

// 发布日期:2010-05-22

// 最后修改:

// 注意事项:未经作者同意,商业网站不能转载,并且不得在转载的时候擅自修改、删除文章的任何部分

//------------------------------------------------------------------------------------------------------------------------------

     从去年的年末,开始参考Norains 老兄wince虚拟串口去做一串口转接口(原帖地址是http://blog.csdn.net/norains/archive/2009/03/28/4032257.aspx)——主要是不想修改物理串口驱动以及导航软件源码,还有第三方也不想把他们的算法暴露给我们,所以Norains老兄的这个wince虚拟串口模板就成了我的救命稻草。经过一番学习,并且我把这个串口驱动弄到EVC下面的去编译(因为客户不懂使用PB,我们也不想把我们PDA的BSP暴露给客户,具体方法请在我的CSDN 博客搜索。),证实的确能收到GPS数据了,我就把这个wince虚拟串口交给老外去开发他们的处理算法了,我真的很天真,结果客户和我们应用程序开发了几个月,有一天突然发现,这个虚拟串口会丢失数据,后来经过排查测试,居然发现这个虚拟串口在不加入处理算法的时候就不稳定,每秒接收数据500多byte 的时候就有严重的丢失数据现象。我真的太大意了,掉汗!

       经过几天的摸索,发现这个虚拟串口存在比较隐患的问题,首先是在串口监视线程MonitorCommEventProc里面放了个sleep(100);这个原本用意是让别的线程进来参与共享这个虚拟串口的读取,可是加入后就存在了比较严重的隐患了,比如造成ReadFile物理串口数据延迟了,足足100个ms 啊,要知道,这个GPS是1s就上来了几百byte的数据的,所以这个会导致物理串口上来的数据没有被读到,丢失数据是必然的了。我把这个sleep(100)屏蔽,扩大缓存,这个丢数据的现象就少一些了,还有提高MonitorCommEventProc线程到97,貌似效果的确会好一些,嘿嘿。不过后来又有了新问题,真是晕倒——就是一串数据发送过去,2440 跑的wince串口调试助手没有接收完,可是下一次发送一串,上次没有出来的数据又出来了,总体来说,数据没有丢失,后来几经查找,发现PulseEvent(g_hEventComm);被执行了三次之后这个应用程序才会被触发去读虚拟串口的数据——就是去调用虚拟串口的COM_Read函数,真是晕倒了,不懂为什么会这样,PulseEvent函数要三次才有效吗?不会这么搞笑吧,先看看PB帮助先吧。

This function provides a single operation that sets to signaled the state of the specified event object and then resets it to nonsignaled after releasing the appropriate number of waiting threads.

BOOL PulseEvent(

  HANDLE hEvent

);

Parameters

hEvent

[in] Handle to the event object. The CreateEvent function returns this handle.

       从PB帮助上看,貌似这个函数没有这么变态啊,晕倒。之所以会有数据延迟的现象,就是有时候这个PulseEvent没有被执行到三次造成的,所以这个是要解决的关键,我想到在COM_IOControl函数的case IOCTL_SERIAL_WAIT_ON_MASK: 中加入如下语句

If(g_bReaded = = FALSE)

       PulseEvent(g_hEventComm);

这样就变成,只要这个数据没有被读过,那么就触发一下应用程序的读虚拟串口数据的线程,不过我现在觉得这个还不合理,这样会造成一个现象,极有可能是应用程序多次读取虚拟串口数据,这样会造成读到的数据不完整,断断续续的现象,因为满足If(g_bReaded = = FALSE)

这个条件的时候大多数都是虚拟串口没有读完物理串口数据的时候。那怎么办?我想下面的条件比较合适If((g_bReaded = = FALSE)&& (等待g_hEventComm超时的情况))这样应该不会导致读数据不完整了吧,试试看,等下来报告结果。

       晕倒,这样不行,因为(g_bReaded初始化的值是FALSE,所以这样会造成应用程序会不停的读虚拟串口,所以这个方法再次暴毙!

       我真的很粗心大意,要发三次数据,应用程序才会去调用虚拟串口的COM_Read的原因不是PulseEvent,因为PulseEvent压根没有执行三次,这个是我在串口监视线程多次使用了WaitCommEvent函数,这个函数需要物理串口触发,如果没有数据来就会在那里无限等待。数据量小的时候只执行了一个WaitCommEvent,所以会造成发三次数据才开始接收数据的现象,纠结!一切都是我的错!

       不过我多次使用WaitCommEvent函数这个是好的出发点,因为加了几个WaitCommEvent之后,能够保证虚拟串口把物理串口的数据完整的读入缓存,实测的效果标明,发送大量数据1K字节的时候,即使500ms间隔发送也不会丢数据,没有加之前512字节都会丢数据,所以这点我要自恋一下,并且今天我已经把多次加入WaitCommEvent带入的缺点(小量数据滞后性)解决了,嘿嘿,下面就来说说我的土鳖方法吧。

一、              在MonitorCommEventProc里面多次重复判断WaitCommEvent,并作相应处理(详细见源码)

二、              定义一个解决数据滞后性的全局变量g_ReadFlag,放在在每次的调用WaitCommEvent之后,并赋值,在COM_IOControl中他会有重要表现。

三、              参考g_hEventComm定义一个事件handler ——g_hEventCommTimeOut用于监视串口中是否有数据,并防止滞后性。

  嘿嘿,貌似就这么多了,仅仅这点改变,耗费了我四五天的心力,纠结!在这几天曾经有不断的尝试各种方法,但是都失败了,最终就照着上述修改,测试结果表明,数据无滞后性,每隔800ms 发送1024 字节,测试三个小时没有一个字节丢失,比以前有很大的提升,并且测试的时候还打印了多个debug信息(O(∩_∩)O哈哈哈~,以前没有输出debug信息都丢失了)。

通过这次虚拟串口的纠结经历,让我更加了解了,wince串口驱动的一些原理,结构,以前搞过4.2/5.0/6.0的物理串口驱动,前段日子还移植了外部串口驱动,把外部串口驱动的性能弄到相当的完美,这次再次把虚拟串口弄成这样可靠,哎,我这个土鳖也算是对串口的认识有点半桶水了。

  快下班了,发博!This is it!

 

 

 

转载于:https://www.cnblogs.com/gooogleman/archive/2010/05/21/1741073.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值