以前没弄过串口编程,所以问题可能会比较白痴,我把问题描述的详细点。
从串口接收数据,串口会一直返回这样格式的数据:02001401018200000C334455660000000000000000421E,02: 数据头
00 14:全数据长度
01 01:特殊含义的字段
82 00:特殊含义的字段
00 0C:需要得到的数据的长度
334455660000000000000000 需要得到的数据
421E:CRC校验问题,我需要接收到的数据应该是02001401018200000C334455660000000000000000421E一整条,
但结果却是半条,或者一条半,两条半为什么会这样,该怎样解决,最好详细点。
代码如下:我接受数据的函数:
读串口:DWORD CCESeries::ReadThreadFunc(LPVOID lparam)
{
CCESeries *ceSeries = (CCESeries*)lparam;
DWORD evtMask;
BYTE * readBuf = NULL;//读取的字节
DWORD actualReadLen=0;//实际读取的字节数
DWORD willReadLen;
DWORD dwReadErrors;
COMSTAT cmState;
// 清空缓冲,并检查串口是否打开。
ASSERT(ceSeries->m_hComm !=INVALID_HANDLE_VALUE);
//清空串口
PurgeComm(ceSeries->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR );
SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );
while (TRUE)
{
if (WaitCommEvent(ceSeries->m_hComm,&evtMask,0))
{
SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );
//表示串口收到字符
if (evtMask & EV_RXCHAR)
{
ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);
willReadLen = cmState.cbInQue ;
if (willReadLen <= 0)
{
continue;
}
//分配内存
readBuf = new BYTE[willReadLen];
ZeroMemory(readBuf,willReadLen);
//读取串口数据
ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);
//如果读取的数据大于0,
if (actualReadLen>0)
{
//触发读取回调函数
if (ceSeries->m_OnSeriesRead)
{
ceSeries->m_OnSeriesRead(ceSeries->m_pOwner,readBuf,actualReadLen);
}
} //释放内存
delete[] readBuf;
readBuf = NULL;
}
}
//如果收到读线程退出信号,则退出线程
if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500) == WAIT_OBJECT_0)
{
break;
}
//Sleep(1000);
}
return 0;
}
串口响应函数:void CALLBACK MyDlg::OnSerialRead(void * pOwner,BYTE* buf,DWORD bufLen)
{
BYTE *pRecvBuf = NULL; //接收缓冲区
//得到父对象指针
MyDlg* pThis = (MyDlg*)pOwner;
//将接收的缓冲区拷贝到pRecvBuf种
pRecvBuf = new BYTE[bufLen];
CopyMemory(pRecvBuf,buf,bufLen);
//发送异步消息,表示收到串口数据,消息处理完,应释放内存
pThis->PostMessage(WM_RECV_SERIAL_DATA,WPARAM(pRecvBuf),bufLen);
}数据处理函数:LONG MyDlg::OnRecvSerialData(WPARAM wParam,LPARAM lParam)
{
CString strRecv = L"";
//串口接收到的BUF
BYTE *pBuf = (BYTE*)wParam;
//串口接收到的BUF长度
DWORD dwBufLen = lParam;
CString temp;
for(int i=0;i<lParam;i++)
{
temp.Format(L"%02x",pBuf[i]);
strRecv+=temp;
} //将新接收到的文本添加到接收框中
m_table.InsertItem(0,strRecv); //释放内存
delete[] pBuf;
pBuf = NULL;
return 0;
}
从串口接收数据,串口会一直返回这样格式的数据:02001401018200000C334455660000000000000000421E,02: 数据头
00 14:全数据长度
01 01:特殊含义的字段
82 00:特殊含义的字段
00 0C:需要得到的数据的长度
334455660000000000000000 需要得到的数据
421E:CRC校验问题,我需要接收到的数据应该是02001401018200000C334455660000000000000000421E一整条,
但结果却是半条,或者一条半,两条半为什么会这样,该怎样解决,最好详细点。
代码如下:我接受数据的函数:
读串口:DWORD CCESeries::ReadThreadFunc(LPVOID lparam)
{
CCESeries *ceSeries = (CCESeries*)lparam;
DWORD evtMask;
BYTE * readBuf = NULL;//读取的字节
DWORD actualReadLen=0;//实际读取的字节数
DWORD willReadLen;
DWORD dwReadErrors;
COMSTAT cmState;
// 清空缓冲,并检查串口是否打开。
ASSERT(ceSeries->m_hComm !=INVALID_HANDLE_VALUE);
//清空串口
PurgeComm(ceSeries->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR );
SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );
while (TRUE)
{
if (WaitCommEvent(ceSeries->m_hComm,&evtMask,0))
{
SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );
//表示串口收到字符
if (evtMask & EV_RXCHAR)
{
ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);
willReadLen = cmState.cbInQue ;
if (willReadLen <= 0)
{
continue;
}
//分配内存
readBuf = new BYTE[willReadLen];
ZeroMemory(readBuf,willReadLen);
//读取串口数据
ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);
//如果读取的数据大于0,
if (actualReadLen>0)
{
//触发读取回调函数
if (ceSeries->m_OnSeriesRead)
{
ceSeries->m_OnSeriesRead(ceSeries->m_pOwner,readBuf,actualReadLen);
}
} //释放内存
delete[] readBuf;
readBuf = NULL;
}
}
//如果收到读线程退出信号,则退出线程
if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500) == WAIT_OBJECT_0)
{
break;
}
//Sleep(1000);
}
return 0;
}
串口响应函数:void CALLBACK MyDlg::OnSerialRead(void * pOwner,BYTE* buf,DWORD bufLen)
{
BYTE *pRecvBuf = NULL; //接收缓冲区
//得到父对象指针
MyDlg* pThis = (MyDlg*)pOwner;
//将接收的缓冲区拷贝到pRecvBuf种
pRecvBuf = new BYTE[bufLen];
CopyMemory(pRecvBuf,buf,bufLen);
//发送异步消息,表示收到串口数据,消息处理完,应释放内存
pThis->PostMessage(WM_RECV_SERIAL_DATA,WPARAM(pRecvBuf),bufLen);
}数据处理函数:LONG MyDlg::OnRecvSerialData(WPARAM wParam,LPARAM lParam)
{
CString strRecv = L"";
//串口接收到的BUF
BYTE *pBuf = (BYTE*)wParam;
//串口接收到的BUF长度
DWORD dwBufLen = lParam;
CString temp;
for(int i=0;i<lParam;i++)
{
temp.Format(L"%02x",pBuf[i]);
strRecv+=temp;
} //将新接收到的文本添加到接收框中
m_table.InsertItem(0,strRecv); //释放内存
delete[] pBuf;
pBuf = NULL;
return 0;
}
解决方案 »
- 刚刚发布的程序:通用端口测控程序PortMaster
- 我用的VS2005,用到了MFC的csocket.编译的程序在XP下没问题.到2000下出现"无法定位程序输入点getaddrinfo于动态链接库WS2_32.dll上"的错误
- 用Skinmagic时,为什么不能响应Slider控件的消息
- Wrapper methods for error-handling"和"Raw methods provided by interface"?
- 急,有没有好用的excel控件!
- 关于多线程的问题
- 急!!怎样让webbrowser控件支持cookie?
- 请 aben456 (风轻扬) 来领分,十分感谢!(4)
- VC6项目转到VC2005,运行时对话框的控件还是显示VC6。0下的样子,有什么办法让它显示VC2005的样子?VC2005下的比较好看。。
- 我现在想学习COM,请各位COM高手推荐几本书,从入门到高级,还有学习体会,谢谢!
- vc++文件内容读入变量问题
- 哪个数据库最好用?
你都知道定长了,还不好办,检查strRecv长度,到这么多时就处理显示
当然要注意CRC效验正确才处理,不然这一条就丢掉,等下一条
我以前的做法是接收线程将接收到的数据一直追加到buf后面,由另一个子程序去分析处理该buf的内容。不过要注意线程同步问题,避免接收线程和数据处理线程同时操作buf.
好像有个地方是跟不上,不过不是上面这里,这里是没问题的,
跟不上的那个地方,我把POST改成了SEND,经过实践测试,还是不错的。