串口通信如何一次读指定数目长的帧 只要有数据串口的EV_RXCHAR消息就会到达,而我的ReadCom(void* buf,int length)想要在收到EV_RXCHAR时就读取指定长度的帧(包含我想要的完整的帧),如何做到? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 DWORD dwErrorFlags;COMSTAT ComStat ;WaitCommEvent( hComDev, &dwEvtMask, &osWait);if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) ClearCommError( hComDev, &dwErrorFlags, &ComStat ) ;//ComStat.cbInQue 指定长度的帧 DWORD dwErrorFlags;COMSTAT ComStat ;WaitCommEvent( hComDev, &dwEvtMask, &osWait);if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) ClearCommError( hComDev, &dwErrorFlags, &ComStat ) ;//ComStat.cbInQue 指定长度的帧ReadCom(buf,ComStat.cbInQue) 每当下位机发送一帧(n字节)时,只会触发一次EV_RXCHAR吗,还是会分多次触发,我怎么去组合一帧呢(我可能接到好多中格式的帧) 既然你通过EV_RXCHAR来得到数据到达的通知,你必然需要read了,read后放入缓冲区然后判断不就行了?这一小段程序就是读取串口的,每次数据到达向主窗口发送数据到达消息。DWORD CUpgraderDlg::ThreadProc(LPVOID lpParam){ CUpgraderDlg *pThis = (CUpgraderDlg *)lpParam; DWORD dwEvents, dwBytesRead, dwError; while(pThis->m_bCommOpen) { if(WaitCommEvent(pThis->m_hComm, &dwEvents, NULL)) { if(dwEvents == EV_RXCHAR) { dwBytesRead = pThis->ReadCommBlock(pThis->m_szRecvBuffer, 1024); if(dwBytesRead) { ResetEvent(pThis->m_hEvBufferEmpty); ::PostMessage(pThis->m_hWnd, UM_DATAARRIVAL, 0, dwBytesRead); WaitForSingleObject(pThis->m_hEvBufferEmpty, INFINITE); } } } else { dwError = GetLastError(); if(dwError != 995) pThis->ShowError(); return 0; } } return 1;}--------------------------------------------------------------------这是把新读入信息放到缓冲区(这里是文本框)中LRESULT CUpgraderDlg::OnDataArrival(WPARAM wParam, LPARAM lParam){// UpdateData(); m_szRecvBuffer[lParam] = 0; m_strOutput.SetSel( 10000, 10000 ); m_strOutput.ReplaceSel( m_szRecvBuffer ); SetEvent(m_hEvBufferEmpty); //if(m_strOutPut.Right(1) == "\n") //if(m_strOutPut.GetLength() > 1000) // UpdateData(FALSE); return 0;}------------------------------------------------------------------这是分析缓冲区的,根据信息判断,我的程序每完成一项功能,返回的字符不一样DWORD CUpgraderDlg::UpgradeThread(LPVOID lpParam){ CUpgraderDlg *pThis = (CUpgraderDlg *)lpParam; CString msg; BYTE bb[2]; bb[0] = 0x8B; bb[1] = 'u'; //Start to upgrade pThis->WriteCommBlock(bb, 2); pThis->m_strOutput.GetWindowText( msg ); while( msg.Find("Programming") < 0) { pThis->m_strOutput.GetWindowText( msg ); Sleep(10); } for(int i = 0; i < 512; i++) { if(!pThis->WriteCommBlock(pThis->m_byteBuffer + i * 128, 128)) { pThis->m_ctlProgress.SetPos(0); pThis->EnableButtons(); pThis->CloseComm(); pThis->m_bUpgrading = false; return -1; } pThis->m_ctlProgress.SetPos(i); } pThis->m_strOutput.GetWindowText( msg ); while(msg.Find("Verifying") < 0){ pThis->m_strOutput.GetWindowText( msg ); Sleep(10); } UINT nChecksum = pThis->CheckSum(); RevBO32((BYTE *)&nChecksum); pThis->WriteCommBlock(&nChecksum, 4); pThis->m_strOutput.GetWindowText( msg ); while(msg.Find("Complete.") < 0){ pThis->m_strOutput.GetWindowText( msg ); Sleep(10); } pThis->EnableButtons(); pThis->CloseComm(); pThis->m_ctlProgress.SetPos(0); pThis->m_bUpgrading = false; return 0;}串口程序最重要的就是缓冲区,合理使用才能正确。 开始先读取一个字节,然后读到这个字节制定的长度的数据,下次再度取一个字节,再度取指定字节长度的数据; 或者:开一个缓冲区队列(FIFO),读取的数据都加入缓冲区。分析程序测试队列的长度,如果有一定的数据,且长度大于等于第一个字节的长度,从队列中取出第一个字节指定的长度的数据。 使用vc读入外部文件中的函数的问题 输入法编程是导出19个函数就行了吗? 请教 我想得到非顶层某个窗体的点的顔色 请问:VC++2005 int到CString的转换 char转换为int怎么是负数? 如果我想动态改变一个菜单的标题,应该怎么做? OnSize问题? 关于网络爬虫的设计 想买两个手机。请大家推荐一下。价格大约在一千至两千。 保存从服务器端广播下来的流媒体? 一个BSTR 的CLSID 怎样转换为GUID 有没有金蝶的人呀?我要去金蝶了,里面怎么样呀?
COMSTAT ComStat ;
WaitCommEvent( hComDev, &dwEvtMask, &osWait);
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
ClearCommError( hComDev, &dwErrorFlags, &ComStat ) ;
//ComStat.cbInQue 指定长度的帧
COMSTAT ComStat ;
WaitCommEvent( hComDev, &dwEvtMask, &osWait);
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
ClearCommError( hComDev, &dwErrorFlags, &ComStat ) ;
//ComStat.cbInQue 指定长度的帧ReadCom(buf,ComStat.cbInQue)
这一小段程序就是读取串口的,每次数据到达向主窗口发送数据到达消息。DWORD CUpgraderDlg::ThreadProc(LPVOID lpParam)
{
CUpgraderDlg *pThis = (CUpgraderDlg *)lpParam; DWORD dwEvents, dwBytesRead, dwError; while(pThis->m_bCommOpen) {
if(WaitCommEvent(pThis->m_hComm, &dwEvents, NULL)) {
if(dwEvents == EV_RXCHAR) {
dwBytesRead = pThis->ReadCommBlock(pThis->m_szRecvBuffer, 1024);
if(dwBytesRead) {
ResetEvent(pThis->m_hEvBufferEmpty);
::PostMessage(pThis->m_hWnd, UM_DATAARRIVAL, 0, dwBytesRead);
WaitForSingleObject(pThis->m_hEvBufferEmpty, INFINITE);
}
}
}
else {
dwError = GetLastError();
if(dwError != 995)
pThis->ShowError();
return 0;
}
}
return 1;
}
--------------------------------------------------------------------
这是把新读入信息放到缓冲区(这里是文本框)中
LRESULT CUpgraderDlg::OnDataArrival(WPARAM wParam, LPARAM lParam)
{
// UpdateData(); m_szRecvBuffer[lParam] = 0;
m_strOutput.SetSel( 10000, 10000 );
m_strOutput.ReplaceSel( m_szRecvBuffer ); SetEvent(m_hEvBufferEmpty); //if(m_strOutPut.Right(1) == "\n")
//if(m_strOutPut.GetLength() > 1000)
// UpdateData(FALSE);
return 0;
}
------------------------------------------------------------------
这是分析缓冲区的,根据信息判断,我的程序每完成一项功能,返回的字符不一样
DWORD CUpgraderDlg::UpgradeThread(LPVOID lpParam)
{
CUpgraderDlg *pThis = (CUpgraderDlg *)lpParam;
CString msg; BYTE bb[2]; bb[0] = 0x8B;
bb[1] = 'u'; //Start to upgrade
pThis->WriteCommBlock(bb, 2);
pThis->m_strOutput.GetWindowText( msg ); while( msg.Find("Programming") < 0) {
pThis->m_strOutput.GetWindowText( msg );
Sleep(10);
} for(int i = 0; i < 512; i++) {
if(!pThis->WriteCommBlock(pThis->m_byteBuffer + i * 128, 128)) {
pThis->m_ctlProgress.SetPos(0);
pThis->EnableButtons();
pThis->CloseComm();
pThis->m_bUpgrading = false;
return -1;
}
pThis->m_ctlProgress.SetPos(i);
} pThis->m_strOutput.GetWindowText( msg );
while(msg.Find("Verifying") < 0){
pThis->m_strOutput.GetWindowText( msg );
Sleep(10);
} UINT nChecksum = pThis->CheckSum();
RevBO32((BYTE *)&nChecksum);
pThis->WriteCommBlock(&nChecksum, 4); pThis->m_strOutput.GetWindowText( msg );
while(msg.Find("Complete.") < 0){
pThis->m_strOutput.GetWindowText( msg );
Sleep(10);
} pThis->EnableButtons();
pThis->CloseComm();
pThis->m_ctlProgress.SetPos(0);
pThis->m_bUpgrading = false;
return 0;
}串口程序最重要的就是缓冲区,合理使用才能正确。
开一个缓冲区队列(FIFO),读取的数据都加入缓冲区。分析程序测试队列的长度,如果有一定的数据,且长度大于等于第一个字节的长度,从队列中取出第一个字节指定的长度的数据。