代码改变世界

关于串口数据读取的几个问题

2008-06-13 11:40  ubunoon  阅读(4701)  评论(5编辑  收藏  举报
串口COM数据读取可以采用MSCOMM控件,或者采用CSerialPort类进行控制,CSerialPort类可以从下面网址获取:http://www.codeguru.com/network/serialport.shtml。具体可以参考龚建伟的个人网页,非常感谢他提供了串口方面的书籍。

在进行串口数据读写的程序编写过程中,遇到了下面几个问题:
1、采用MSCOMM控件编写时,采用下面代码:
        CString strTemp;
        strTemp.Format(TEXT("CTestSDCardDlg::OnOnCommTestMscomm comEvent=%d, count=%d\n"),
        m_COMTest.GetCommEvent(),m_COMTest.GetInBufferCount());
        TRACE(strTemp);
        
        if( m_COMTest.GetCommEvent() == 2 && 0 != m_COMTest.GetInBufferCount())  // 表明有数据传送过来
        {
            strTemp.Format(TEXT("in Buffer count = %d\n", m_COMTest.GetInBufferCount()));
            TRACE(strTemp);
        }
结果第一个strTemp输出的是comEvent = 2, count = 8
第二个strTemp输出的却为:in Buffer count = 0
这个让我实在是难以明白,我并没有获取过数据,两行代码也基本类似,为什么会出现这样的情况,很费解,不得以,用CSerialPort类进行程序编写

如果您知道如何解决这个问题,请发邮件或者在底下回复告诉我,请您写信的时候标题注明串口,我将非常谢谢您,!我的邮箱:
    ubunoon@163.com

2、CSerialPort类进行程序编写时遇到:
 a. CSerialPort类并没有定义串口关闭函数,显然,很多时候我们是需要关闭串口的,因此,采用在CSerialPort类中添加了ClsoePort函数
具体定义如下:
   VOID CSerialPort::ClosePort()
{
     do
     {
          SetEvent(m_hShutdownEvent);
          Sleep(10);
     } while (m_bThreadAlive);
}
其实就是把CSerailPort的析构函数的前面部分取了过来
  b. 这期间,碰到一个问题,就是我启动了串口监控,在关闭的时候等待了好长时间都没有关闭,后来运行编写时才明白,是由于将大量获取的串口数据写出到CEdit控件上,而串口发送数据又是非常频繁的,导致系统响应出现问题,后来,将这些写到CEdit控件的数据给注释后,关闭非常迅速。

  c. 在将数据写到CEdit的时候,发现数据怎么也不正确,用串口调试助手获取的数据与自己获取的数据始终不能够对上号,后来,在仔细核对源代码的时候发现,我常用TEXT宏来确定是否采用Unicode代码,当我在CString的Format函数中将TEXT去掉后,发现数据正确显示,而且获得的数据也是正确的。 这让我明白,串口数据是最好以纯的unsigned char来读取,这也是编写硬件相关软件的一个重要要求!

对于硬件方面的软件编写,需要学习的东西很多,现在仅将工作遇到的问题记录下来,也可以使自己或者他人能够避免出现这些错误或者问题。

// 下面内容为2008-08-28日添加:
龚建伟修改了CSerailPort的方法,使得能够一次性输出多个字符,这本身没有错,但是,里面隐含了一个重要的bug,那就是,如果你在差不多相同的时间内,两次调用WriteToPort来进行多个字符输出,那么,后来的数据将覆盖前面的数据,而你得到的并不是正确的数据!

因为这个隐含的bug,差不多花去了我一天的时间进行调试,因为我两次输出基本上相同的字符流,但含义不一样,在串口监测看到只有一次输出,而在调用日志上却又有两次输出,因此,我就非常纳闷,仔细查看了CSerailPort源代码,才发现两次WriteToProt的调用时间实在是太短了,没有线程间切换的时间那么长,因此,无论怎么处理CSerialPort均不可能得到正确的两次输出,为此,我只好在调用之前先做一些处理,使得一次性输出整个流!

这个问题这是冤枉啊!

后记:
    这也难怪同事一个劲的劝我转入到.net领域中去,我想哪儿应该不存在这些问题的,毕竟人家是经过上百次的测试的,而C++中开源代码虽然由大家维护,也是具有很强的健壮性的,但修改后的代码,是否还有那样的健壮性,是很难肯定的。因此在不清楚整个构架的情况下,不清楚每一个细节的情况下,对开源源代码进行修改反而容易出现更多隐含的bug,这些bug一旦暴露出来,其后患无穷。而如果开源代码不进行修改,则与商业库的区别便在于价格以及调试方便。相反,开源的代码更多的是需要修改后才能够更加适合某个工程,而商业库则更易定制。因此,虽然商业库受制于他人,但转入一个更为健全的商业库对于写程序是更为有利的事情,工程时间也将更加紧凑!