主題:串口通訊線程問題 共有43908人關注過本帖 |
---|
bingdongcha |
1樓 信息 | 搜索 | 郵箱 |
加好友 發短信 |
串口通訊線程問題 Post By:2013-5-21 22:30:00 [只看該作者]
DWORD WINAPI CCESerial::ReceiveThreadFunc(LPVOID lparam) {
CCESerial *lpSerial = (CCESerial*)lparam;
DWORD dwEvtMask, dwReadError;
COMSTAT
cmStat;
ULONG nWillLen;
SetCommMask( lpSerial->m_hSer, EV_RXCHAR|EV_ERR );
for( ; ; )
{
printf( "WRITE WRITE WRITE WRITE CHAR \r\n"); /************************************************************************************************ //
if( WaitCommEvent( lpSerial->m_hSer, &dwEvtMask, NULL ) ) //
{ //
SetCommMask( lpSerial->m_hSer, EV_RXCHAR|EV_ERR ); //
// get how many data available in receive buffer //
if( dwEvtMask & EV_RXCHAR ) //
{ //
ClearCommError( lpSerial->m_hSer, &dwReadError, &cmStat );
//取接收數據長度信息 //
nWillLen = cmStat.cbInQue; //
if( nWillLen <=0 ) //
continue; // //
lpSerial->m_lDatLen = 0; //
ReadFile( lpSerial->m_hSer, lpSerial->DatBuf, nWillLen, &lpSerial->m_lDatLen, 0 ); //
//
if( lpSerial->m_lDatLen>0 ) //
{ //
// 調用回調函數處理接收到的數據 //
lpSerial->OnReceive( ); //
} //
} //
else if( dwEvtMask & EV_ERR ) //
{ //
// 清錯誤標志 //
ClearCommError( lpSerial->m_hSer, &dwReadError, &cmStat ); //
lpSerial->OnError( ); //
} // //
} // //
if( WaitForSingleObject( lpSerial->m_hKillRxThreadEvent, 0 ) == WAIT_OBJECT_0) //
{ //
SetEvent( lpSerial->m_hReceiveCloseEvent ); //
break; //
} *************************************************************************************************/
}
return 0; } 上邊這個線程 可以循環打印,但是把注釋的部分打開,只能運行一次打印。好像是線程只運行了一次。 在if( WaitCommEvent( lpSerial->m_hSer, &dwEvtMask, NULL ) )設置斷點,暫停后也不能單步運行。按單步也直接就啟動了。 是和WaitCommEvent( lpSerial->m_hSer, &dwEvtMask, NULL ) 這個函數有關系么?? 串口打開時是異步通信方式-非阻塞方式打開的。 m_hComm = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
// 異步通信方式-非阻塞方式 或者有跟好的方法實現在線程內實現收發數據。主要想做循環式通訊規約。 [此貼子已經被作者于2013-5-21 22:39:56編輯過]
|
單帖管理 | 引用 | 回復 |
lqk |
2樓 信息 | 搜索 | 郵箱 |
加好友 發短信 |
Post By:2013-5-22 9:41:00 [只看該作者]
WINCE不支持重疊I/O模式,所以不能使用FILE_FLAG_VOERLAPPED參數。
WaitCommEvent總是阻塞等待數據接收。 通訊規約一般有固定的格式,需要根據通訊規約將接收數據在本地緩存處理,然后根據接收數據的內核,做相應的應答。
|
單帖管理 | 引用 | 回復 |
bingdongcha |
3樓 信息 | 搜索 | 郵箱 |
加好友 發短信 |
Post By:2013-5-24 11:27:00 [只看該作者]
現在是這樣實現的,把代碼貼出來,童鞋們可以借鑒,老鳥們批判下。我繼續改正。 電力規約循環發送CDT報文,串口沒有用重疊I/O模式,線程啟動前先發送一個字節,觸發EV_TXEMPTY事件。以后就可以循環發送了,串口有數據來時,也可以接受處理。 最后的一句Sleep();加上它,報文會有卡頓。不加Sleep();這個線程一直在運行,不知道長時間運行對其他線程是否會有影響。暫時測試沒有影響,所以把Sleep();封掉了。 DWORD WINAPI CDTSend(PVOID lparam) {
PVOID lpflag;
lpflag = lparam;
DWORD
dwEvtMask, dwReadError;
COMSTAT
cmStat;
ULONG
nWillLen;
unsigned char buf = 0xff;
BOOL
bReadStatus;
cdt_tx0.OpenPort(CDTA_Port,CDTA_Bate,CDTA_Pn,8,1);
SetCommMask(cdt_tx0.m_hComm, EV_RXCHAR|EV_ERR|EV_TXEMPTY);
cdt_tx0.WritePort(&buf,1);
while(TRUE)
{
// 阻塞串口時間 一直等待事件發生。
if(WaitCommEvent(cdt_tx0.m_hComm, &dwEvtMask, NULL))
{
SetCommMask(cdt_tx0.m_hComm, EV_RXCHAR|EV_ERR|EV_TXEMPTY);
if( dwEvtMask & EV_RXCHAR )
{
printf( "CDT_TX0 RECV RECV SUCCESS \r\n");
ClearCommError( cdt_tx0.m_hComm, &dwReadError, &cmStat );
//取接收數據長度信息
nWillLen = cmStat.cbInQue;
// cbInQue:表示接收緩沖區中存儲的待ReadFile讀取的字節數。
// cbOutQue:表示發送緩沖區中存儲的待發送的字節數。
if( nWillLen <=0 )
continue;
cdt_tx0.RecvLen = 0;
bReadStatus = ReadFile(cdt_tx0.m_hComm, cdt_tx0.AcceBuf, nWillLen, &cdt_tx0.RecvLen, NULL);
if(cdt_tx0.RecvLen > 0)
cdt_tx0.Acces(cdt_tx0.AcceBuf,cdt_tx0.RecvLen);
}
if(dwEvtMask & EV_TXEMPTY)
{
cdt_tx0.WritePort(cdt_tx0.SendBuf,cdt_tx0.SendLen);
}
else if(dwEvtMask & EV_ERR)
{
// 清錯誤標志
ClearCommError(cdt_tx0.m_hComm, &dwReadError, &cmStat);
}
} //
Sleep(99);
// 線程掛起時間99MS 調度時間1MS 線程重新運行時間100MS
}
return 0; }
|
單帖管理 | 引用 | 回復 |
lqk |
4樓 信息 | 搜索 | 郵箱 |
加好友 發短信 |
Post By:2013-5-24 13:12:00 [只看該作者]
數據的接收和發送完全可以由兩個線程來分別完成,在我們網站上有一篇基于RS485的電力系統DL645協議規約的實現方法http://www.huochepiao123.com.cn/article/article2009326.html,可以做為一個例子參考。
如果需要源碼,請留下郵箱。
|
單帖管理 | 引用 | 回復 |
bingdongcha |
5樓 信息 | 搜索 | 郵箱 |
加好友 發短信 |
Post By:2013-5-24 15:35:00 [只看該作者]
我們也做645規約。
gyangchina@163.com這是我的郵箱,感謝共享源碼。 萬分感謝!!
|
單帖管理 | 引用 | 回復 |
lqk |
6樓 信息 | 搜索 | 郵箱 |
加好友 發短信 |
Post By:2013-5-24 17:16:00 [只看該作者]
例程已發到你郵箱,請查收。
|
單帖管理 | 引用 | 回復 |