我正在编写一个半双工通信的c ++应用程序,用于从设备下载数据。以下是我用于串行通信的课程。
class CSerialCommHelper
{
HANDLE m_pPortHandle; //Handle to the COM port
HANDLE m_hReadThread; //Handle to the Read thread
HANDLE m_hPortMutex; //Handle to Port Mutex
std::wstring m_strPortName; //Portname
COMMTIMEOUTS m_CommTimeouts; //Communication Timeout Structure
_DCB dcb; //Device Control Block
DWORD m_dwThreadID; //Thread ID
string m_strBuffer;
public:
CSerialCommHelper();
HRESULT Open();
HRESULT ConfigPort();
static void * ReadThread(void *);
HRESULT Write(const unsigned char *,DWORD);
string GetFrameFromBuffer();
HRESULT Close();
~CSerialCommHelper(void);
};
ReadThread和Write函数如下:
void * CSerialCommHelper::ReadThread(void * pObj)
{
CSerialCommHelper *pCSerialCommHelper =(CSerialCommHelper *)pObj;
DWORD dwBytesTransferred =0;
DWORD byte=0;;
while (pCSerialCommHelper->m_pPortHandle != INVALID_HANDLE_VALUE)
{
pCSerialCommHelper->m_strBuffer.clear();
pCSerialCommHelper->m_usBufSize=0;
WaitForSingleObject(pCSerialCommHelper->m_hPortMutex,INFINITE);
do
{
dwBytesTransferred = 0;
ReadFile (pCSerialCommHelper->m_pPortHandle,&byte,1,&dwBytesTransferred,NULL);
if (dwBytesTransferred == 1)
{
pCSerialCommHelper->m_strBuffer.push_back((char)byte);
pCSerialCommHelper->m_usBufSize++;
continue;
}
}
while ((dwBytesTransferred == 1) && (pCSerialCommHelper->m_pPortHandle != INVALID_HANDLE_VALUE));
ReleaseMutex(pCSerialCommHelper->m_hPortMutex);
Sleep(2);
}
ExitThread(0);
return 0;
}
写入函数等待readthread释放互斥锁并将数据写入端口。 将从使用SerialCommhelper的应用程序调用GetFrameFromBuffer 并返回m_strBuffer字符串。
我的问题是每当我尝试下载大量数据时。 我丢失了一些数据框。 我正在从.0468到.1716秒之间获得设备的响应。
在分析了不同的错误情景后,我发现随着时间的推移不会出现问题,因为其他帧会以相同的时间间隔下载。
调用getframebuffer的函数是连续调用它,直到得到一个填充的字符串。
答案 0 :(得分:2)
似乎这两个陈述不应该在你的外while
循环中:
pCSerialCommHelper->m_strBuffer.clear();
pCSerialCommHelper->m_usBufSize=0;
你的内部while循环只要它们立即可用就会读取字节,而外部循环在内部循环没有给你一个字节时会执行Sleep(2)
。
如果您要等到整个数据包可用,那么您似乎应该继续循环,直到获得所有字节,而不会在整个过程中进行清除。
我真的不知道ReadFile
API,但我猜测ReadFile
如果没有立即可用的字节可能会返回0,或者至少可以通过您在打开时指定的任何超时时间返回0串口设备。
答案 1 :(得分:2)
ReleaseMutex(pCSerialCommHelper->m_hPortMutex);
Sleep(2);
Sleep()调用隐藏了真正的问题。在线程代码中永远不会正确,永远是时间错误的创可贴。
你当然似乎有一个,m_hPortMutex也是如此。如果你确实有多个线程试图从串口读取,那么他们将开始争夺该互斥锁。结果将非常糟糕,每个线程将从端口获得少量字节。但显然你想要阅读 frame 的数据。没有希望你可以将每个线程重新组合在一起的少量字节粘合到一个帧中,你已经丢失了它们的序列。所以睡觉一段时间似乎就像一个变通办法,它注入了延迟,可以让你更好地阅读框架。通常,并非总是如此。你也把它写在了错误的地方。
此代码刚刚破解。删除睡眠()。在你读完整个画面之前,不退出循环。