程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 多線程,多接收模式串口類LsComm之二

多線程,多接收模式串口類LsComm之二

編輯:關於VC++

描述:一個串口通訊類

應用平台:Windows

版本:v1.2

上次我做的“多線程,多接收模式串口類LsComm”,說實在的有不少的問題。好不容易有一段空閒的時間,把以前發現的Bugs修改了一下。

一、Bugs修正

1.ERR : 修改了98下 AutoReceiveBySignal 模式不能正常執行的bug

原因: CcomPort::m_WriteOverlapped.hEvent 沒有設置事件!!!!粗心,害人阿。導致在Win98下發送數據異常,不過奇怪在

Win2K正常,而且測試的時候忽略了測試環境平台的影響。

修改: 相應的代碼

if(this->IsOverlapped())
  {
    this->m_hWriteEvent= ::CreateEvent(NULL,true,false,NULL);
    if(this->m_hCloseEvent==NULL)    return false;
    this->m_WriteOverlapped.hEvent = this->m_hWriteEvent;
  }

2.ERR : 修改了 ManualReceiveByQuery 模式下,發送會出現不動的情況。

原因: 在dwWriteBytes= this->m_pPort->Write(pBuf,Count);

前,串口已經設置中斷,所以需要等待中斷事件發生。

修改: 去掉中斷設置的代碼 this->m_pPort->GetSerialPort()->SetMask(dwStoredFlags);

3.ERR : 打開一個計算機上不存在的串口的時候沒有異常捕獲。

原因: 沒有捕獲 CserialPort 拋出的 CserialException 異常

修改: 不過對於異常的處理改為不拋出異常,不知道是否妥當?

try
{
  this->m_pPort->Open(nPort,dwBaud,spParity,DataBits,spStopbits,spFC,m_IsOverlapped);
}
catch(CSerialException* pE)
{
  //AfxMessageBox(pE->GetErrorMessage());
  pE->Delete();
    return false;
}

4.ERR : 感覺 AutoReceiveByBreak 意義不大應該去掉

原因: 全部的事件都可以用AutoReceiveBySignal方式實現

修改: 暫時保留:DWORD dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |EV_RLSD | EV_RXCHAR | EV_RXFLAG ;

//??| EV_TXEMPTY 添加後在首次執行時總是接收不到全部數據 ,以後就正常了。現在還搞不清楚是什麼原因。

5. ERR : 感覺 ManualReceiveByConst 意義不大應該去掉

原因: 實現方式不太好

修改: 暫時保留

二、遺留問題

1.ERR : 流控制模式下可能不正確,自己在這方面沒有經驗,沒有測試。

2.ERR : 結構問題,把 this->m_ComPort.GetSerialPort() 獲取 CserialPort 的指針好像不妥,如果類的使用者在程序中這樣用

this->m_ComPort.GetSerialPort()->Close();

收發數據的時候就會產生異常。但是由於使用別人的CserialPort類 ,比較

穩定,但有不能破壞別人代碼的完整性。

3.ERR : ManualReceiveByConst 方式受 CommTimeOUts 的影響可能不太准確。

其它問題:我的計算機上只有一個串口可用,所以是2-3口短接進行的測試,其它測試還不太完全。

三、由於前一段時間確實比較忙,有好多網友提出的問題,都沒有回復,實在非常抱歉,在這裡簡單的回復一下

1.風也飄飄:你好,我感覺這個類做的很好,但我想實現兩台電腦之間的實時數據傳輸(為字符型),不知道怎麼用,可否指點一二?

答: 感覺可以這樣寫: (1)首先:定義一個接收函數:

void OnReceiveData(LPVOID pSender,void* pBuf,DWORD InBufferCount)
{//在此處理要接收的數據
}

(2)然後,打開串口,監聽Com2this->m_ComPort.Open(2,LsComm::CComPort::AutoReceiveBySignal );
  this->m_ComPort.SetReceiveFunc((FOnReceiveData)OnReceiveData,this);

(3)發送:char a[10000];//字符數組
  BYTE b[10000];//字節數組
  memset(a,''''a'''',sizeof(a));
  memset(b,0x0b,sizeof(b));
  this->m_ComPort.Output(a,sizeof(a)); //發送字符數組
  this->m_ComPort.Output(b,sizeof(b)); //發送字節數組

感覺在C裡面是不分 char 和字節的,像 char c=’a’;和char c=0x61;是一樣的,只不過 char 只能取字符類型范圍,超過就被截短。

2. zkf00:中斷接收函數OnComBreak怎麼用? 答:試驗了一下

void OnComBreak(LPVOID pSender,DWORD dwMask,COMSTAT stat)
{
  //deal with the break of com here
  switch(dwMask)
  {
  case EV_BREAK:
  {
    break;
  }
  case EV_CTS: //在這裡處理CTS信號
  {
    break;
  }
  }
}

3. greatim:DataWaiting 是有什麼用的??在例子程序裡沒有引用到。而且在 Open 的函數裡,CreateEvent 被屏蔽了,是否代表 DataWaiting 這函數不能使用呢? DataWaiting 和 Attech 有什麼關系?

答:因為 DataWaiting 是 PJ Naughter 寫的,請仔細看他的源碼:

BOOL CSerialPort::DataWaiting(DWORD dwTimeout)
  {
    ASSERT(IsOpen());
    ASSERT(m_hEvent);
    //Setup to wait for incoming data
    DWORD dwOldMask;
    GetMask(dwOldMask);
    SetMask(EV_RXCHAR);//1.設置接收中斷事件

    //Setup the overlapped structure
    OVERLAPPED o;
    o.hEvent = m_hEvent;
    //Assume the worst;
    BOOL bSuccess = FALSE;
    DWORD dwEvent;
    bSuccess = WaitEvent(dwEvent, o);//2. 設置監聽
    if (!bSuccess)
    {//3.dwTimeOut為所等待的時間,有數據收到,返回發現數據
      if (WaitForSingleObject(o.hEvent, dwTimeout) == WAIT_OBJECT_0)
      {
       DWORD dwBytesTransferred;
       GetOverlappedResult(o, dwBytesTransferred, FALSE);
       bSuccess = TRUE;
      }
    }
    //Reset the event mask
    SetMask(dwOldMask);
    return bSuccess;
    }

這好像與 Attach 沒什麼關系吧?

4. Sander:在win2000下能用no overlapped嗎?

答:查看了一下 MSDN 中 CreateFile 的說明,沒有在 Win2K 下的使用限制,應該是可以的。

5. Sander:當用 ExecuteByAutoSignalRecvMode,

BOOL bSuccess = ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, &overlapped);
dwSignaledHandle=::WaitForMultipleObjects(3,WaitHandles,false,INFINITE);

this->m_pPort->GetSerialPort()->GetOverlappedResult(overlapped,this->m_InBufferCount,false)

這個兩個函數

WaitForMultipleObject

GetOverlappedResult)

它會以 COMMTIMEOUTS 中設置的 timeout 來返回嗎?也就是說 Overlapped 中的 Event 是在什麼時候激活的?

答:這個問題我以前沒有仔細考慮,真是不好意思。好像 COMMTIMEOUTS的TimeOut 僅對 ReadFile,WriteFile 起作用,具體可以看 MSDN 中 COMMTIMEOUTS 的描述。

WaitForSingleObject(m_ReadOverlapped.hEvent,dwMilliseconds)==WAIT_OBJECT_0)

會等待 m_ReadOverlapped.hEvent 事件置信號標志的時候返回。那麼讀取 時間什麼時候返回呢,找了下面的一段話:

When reading from a communications device, the behavior of ReadFile is governed by the current
communication time-outs as set and retrieved using the SetCommTimeouts and GetCommTimeouts
functions. Unpredictable results can occur if you fail to set the time-out values. For more
information about communication time-outs, see COMMTIMEOUTS.

可見 SetCommTimeouts 對這 ReadFile 起作用,也就是對 m_ReadOverlapped.hEvent 起作用。因此定時間接收模式在 COMMTIMEOUTS 時也會置讀事件的 hEvent,所以等待 時間的限制就有可能不太准確。

6. Hi_nihaoma:為什麼我使用重疊方式打開串口,根據示例:

for(int j= 0; j< 10; j++)
{
  if (!port2.Write(pBuf, 10000, overlapped))
  {
    DWORD dwBytesWritten;
    WaitForSingleObject(event, INFINITE);
    port2.GetOverlappedResult(overlapped, dwBytesWritten, TRUE);
  }
  if (!port2.Read(pBuf, 10, overlapped))
  {
    DWORD dwBytesRead;
    if (WaitForSingleObject(event,1000) == WAIT_OBJECT_0)
    {
      TRACE(_T("Data was read from the serial port\n"));
      port2.GetOverlappedResult(overlapped,dwBytesRead,FALSE);
    }
    else
      TRACE(_T("No data was read from the serial port\n"));
  }

  port2.SetMask(EV_TXEMPTY);
  port2.WaitEvent(dwMask,overlapped);
}
port2.GetOverlappedResult(overlapped,dwBytesRead,FALSE);
dwByteRead= 4啊???急急急!!!

答:感覺可能是接收的問題,不能所有容納發送的全部數據,而引發異常吧。看你這行port2.Write(pBuf, 10000, overlapped);一次發送這麼大的數據量 ,是不是這的問題, 我的計算機上只有一個串口,把2,3口連接後收發數據測試了一下。一次發送超過100個就會發生讀地址錯誤,但是低於這個速率就沒問題。可能是接收的速度跟不上吧 。具體問題正在找。

結束語:

本來早就想要改一下,可實在是沒有時間,不是開玩笑,大概3個月沒有時間上網看看新聞了。寫程序,就是要認真仔細的面對自己寫的每一行代碼 ,不放過自己的每一個Bug。誰都希望自己的程序不出一個Bug,可這實在是說起來容易做起來難。希望大家看到Bugs要貼在下面,有時間我會努力改的。上面的一些問題自己的水平實在是太有限了 ,搞得還不是太清楚,希望如果誰知道,就告訴偶。有些問題就得擺出來,然後再一點點搞清楚才會有提高。如果只是默許的認為簡單,容易,不求甚解,相反會害了自己。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved