int CRead_MaterDlg::WriteCom(DWORD m_length)
{
COMSTAT ComStat;
DWORD dwBytesSent=0;
DWORD dwErrorFlags;
DWORD dwBytesWrite;
DWORD dwError=0;
OVERLAPPED Write_Os;
Write_Os.Offset=0;
Write_Os.OffsetHigh=0;
Write_Os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
DWORD fWriteStat;
fWriteStat = WriteFile(hCom,lpSendBuffer,m_length,&dwBytesWrite,&Write_Os);
if (!fWriteStat)
{
if(GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(hCom,&Write_Os,
&dwBytesWrite,TRUE))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
{
dwBytesSent+=dwBytesWrite;
continue;
}
else
{
ClearCommError(hCom,&dwErrorFlags,&ComStat);
break;
}
}
dwBytesSent+=dwBytesWrite;
}
else
ClearCommError(hCom,&dwErrorFlags,&ComStat);
}
else
dwBytesSent+=dwBytesWrite;
CloseHandle(Write_Os.hEvent);
return dwBytesSent;
}
// 读串口数据函数
int CRead_MaterDlg::readcom()
{
ASSERT(hCom);
// 缓冲区中有数据到达
COMSTAT ComStat;
DWORD dwLength;
DWORD dwErrorFlags;
DWORD dwBytesRead=0;
DWORD dwError=0;
OVERLAPPED Read_Os;
Read_Os.Offset=0;
Read_Os.OffsetHigh=0;
Read_Os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
ClearCommError(hCom,&dwErrorFlags,&ComStat);
// 输入缓冲区有多少数据?
dwLength = ComStat.cbInQue;
if(dwLength > 0)
{
DWORD fReadStat;
//读数据
fReadStat = ReadFile(hCom,lpRecieveBuffer,dwLength,
&dwLength,&Read_Os);
if (!fReadStat)
{
if(GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(hCom,&Read_Os,
&dwLength,TRUE))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
{
dwBytesRead+=dwLength;
continue;
}
else
{
ClearCommError(hCom,&dwErrorFlags,&ComStat);
break;
}
}
dwBytesRead+=dwLength;
}
else
ClearCommError(hCom,&dwErrorFlags,&ComStat);
}
else
dwBytesRead+=dwLength;
}
else
ClearCommError(hCom,&dwErrorFlags,&ComStat);
CloseHandle(Read_Os.hEvent);
return dwBytesRead;
}
// 线程过程
UINT CRead_MaterDlg::CommWatchProc(LPVOID pParam)
{
DWORD dwEvtMask=0;
DWORD mError;
DWORD mwaitflags;
OVERLAPPED Os;
Os.Offset=0;
Os.OffsetHigh=0;
Os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
// 等待串口通信事件的发生
while(ThreadStop)
{
mwaitflags=WaitCommEvent(hCom,&dwEvtMask,&Os);
mError=GetLastError();
if(mError==ERROR_IO_PENDING)
mwaitflags=(WaitForSingleObject(Os.hEvent,0)
==WAIT_OBJECT_0);
if(mwaitflags>0)
ResetEvent(Os.hEvent);
}
CloseHandle(Os.hEvent);
PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR);
return 1;
}
线程我是在初始化时创建的(afxbeginthread());为何我写后,再读老是慢一拍呢????
读
this->WriteCom();
Sleep(100);
this->readcom();
为何啊!请多多指教。还有怎么能把cstring类型转换为float类型呢??多谢!!
7 个解决方案
#1
UINT CSerialPort::CommThread(LPVOID pParam)
{
CSerialPort *port = (CSerialPort*)pParam;
port->m_bThreadAlive = TRUE;
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;
DWORD ByteRead;
if (port->m_hComm) // check if the port is opened
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
for (;;)
{
bResult = WaitCommEvent(port->m_hComm, &CommEvent, &port->m_ov);
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
break;
}
case 87:
{
// Under Windows NT, this value is returned for some reason.
// I have not investigated why, but it is also a valid reply
// Also do nothing and continue.
break;
}
default:
{
port->ProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else
{
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
if (comstat.cbInQue == 0)
continue;
} // end if bResult
// Main wait function. This function will normally block the thread
// until one of nine events occur that require action.
Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
switch (Event)
{
case 0://exit
{
}
case 1://// read event
{
}
case 2: // write event
{
WriteChar(port);
break;
}
} // end switch
} // close forever loop
return 0;
}
{
CSerialPort *port = (CSerialPort*)pParam;
port->m_bThreadAlive = TRUE;
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;
DWORD ByteRead;
if (port->m_hComm) // check if the port is opened
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
for (;;)
{
bResult = WaitCommEvent(port->m_hComm, &CommEvent, &port->m_ov);
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
break;
}
case 87:
{
// Under Windows NT, this value is returned for some reason.
// I have not investigated why, but it is also a valid reply
// Also do nothing and continue.
break;
}
default:
{
port->ProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else
{
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
if (comstat.cbInQue == 0)
continue;
} // end if bResult
// Main wait function. This function will normally block the thread
// until one of nine events occur that require action.
Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
switch (Event)
{
case 0://exit
{
}
case 1://// read event
{
}
case 2: // write event
{
WriteChar(port);
break;
}
} // end switch
} // close forever loop
return 0;
}
#2
能否解释一下waitforsingleobject和WaitForMultipleObjects的区别和用法吗,我的写法哪个地方出错了,假如我不用该线程监视,只用异步读写,在异步读和写之间sleep(3000)后,它才能读写正确,怎么改善???又为何呢??我的外部设备没怎么慢啊????
#3
工作
#4
1200,n,8,1 方式下 58 字节要 1000ms 你的设置呢?
#5
但是我的是9600的啊,我想问一下,CString 转换到 Float是否要自己写转换函数啊???
#6
CString 转换到 Float: 不用自已写,用atof(str);
另外通讯慢可能是不一定是因为你程序慢,有可能是给你回送数据的设备慢!
另外通讯慢可能是不一定是因为你程序慢,有可能是给你回送数据的设备慢!
#7
三秒钟才能读出来,肯定是你的外部设备慢
根据我的经验,我使用斯赖得最烂的modicon neza plc,modbus协议,19200,n,8,1,一般的数据30byte之内,tx之后50ms就可以rx了,如果数据量很大(如100byte以上,当然,每次发送与接收的数据量都小于256byte,这是mosbus规约所限)200ms足够了。
我还测试过看这个plc最快什么时候能够反应过来,结果证实延时25ms的时候,通信开始不可靠,并不是每次发送之后plc都能回应。所以我使用50ms的延时,实践证明是可行的。
你用9600bps,速度也不会慢到那里去,单纯数据的发送与接收都是很快的,发送48个字节所需的时间为48*10/9600 = 50ms
根据我的经验,我使用斯赖得最烂的modicon neza plc,modbus协议,19200,n,8,1,一般的数据30byte之内,tx之后50ms就可以rx了,如果数据量很大(如100byte以上,当然,每次发送与接收的数据量都小于256byte,这是mosbus规约所限)200ms足够了。
我还测试过看这个plc最快什么时候能够反应过来,结果证实延时25ms的时候,通信开始不可靠,并不是每次发送之后plc都能回应。所以我使用50ms的延时,实践证明是可行的。
你用9600bps,速度也不会慢到那里去,单纯数据的发送与接收都是很快的,发送48个字节所需的时间为48*10/9600 = 50ms
#1
UINT CSerialPort::CommThread(LPVOID pParam)
{
CSerialPort *port = (CSerialPort*)pParam;
port->m_bThreadAlive = TRUE;
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;
DWORD ByteRead;
if (port->m_hComm) // check if the port is opened
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
for (;;)
{
bResult = WaitCommEvent(port->m_hComm, &CommEvent, &port->m_ov);
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
break;
}
case 87:
{
// Under Windows NT, this value is returned for some reason.
// I have not investigated why, but it is also a valid reply
// Also do nothing and continue.
break;
}
default:
{
port->ProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else
{
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
if (comstat.cbInQue == 0)
continue;
} // end if bResult
// Main wait function. This function will normally block the thread
// until one of nine events occur that require action.
Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
switch (Event)
{
case 0://exit
{
}
case 1://// read event
{
}
case 2: // write event
{
WriteChar(port);
break;
}
} // end switch
} // close forever loop
return 0;
}
{
CSerialPort *port = (CSerialPort*)pParam;
port->m_bThreadAlive = TRUE;
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;
DWORD ByteRead;
if (port->m_hComm) // check if the port is opened
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
for (;;)
{
bResult = WaitCommEvent(port->m_hComm, &CommEvent, &port->m_ov);
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
break;
}
case 87:
{
// Under Windows NT, this value is returned for some reason.
// I have not investigated why, but it is also a valid reply
// Also do nothing and continue.
break;
}
default:
{
port->ProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else
{
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
if (comstat.cbInQue == 0)
continue;
} // end if bResult
// Main wait function. This function will normally block the thread
// until one of nine events occur that require action.
Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
switch (Event)
{
case 0://exit
{
}
case 1://// read event
{
}
case 2: // write event
{
WriteChar(port);
break;
}
} // end switch
} // close forever loop
return 0;
}
#2
能否解释一下waitforsingleobject和WaitForMultipleObjects的区别和用法吗,我的写法哪个地方出错了,假如我不用该线程监视,只用异步读写,在异步读和写之间sleep(3000)后,它才能读写正确,怎么改善???又为何呢??我的外部设备没怎么慢啊????
#3
工作
#4
1200,n,8,1 方式下 58 字节要 1000ms 你的设置呢?
#5
但是我的是9600的啊,我想问一下,CString 转换到 Float是否要自己写转换函数啊???
#6
CString 转换到 Float: 不用自已写,用atof(str);
另外通讯慢可能是不一定是因为你程序慢,有可能是给你回送数据的设备慢!
另外通讯慢可能是不一定是因为你程序慢,有可能是给你回送数据的设备慢!
#7
三秒钟才能读出来,肯定是你的外部设备慢
根据我的经验,我使用斯赖得最烂的modicon neza plc,modbus协议,19200,n,8,1,一般的数据30byte之内,tx之后50ms就可以rx了,如果数据量很大(如100byte以上,当然,每次发送与接收的数据量都小于256byte,这是mosbus规约所限)200ms足够了。
我还测试过看这个plc最快什么时候能够反应过来,结果证实延时25ms的时候,通信开始不可靠,并不是每次发送之后plc都能回应。所以我使用50ms的延时,实践证明是可行的。
你用9600bps,速度也不会慢到那里去,单纯数据的发送与接收都是很快的,发送48个字节所需的时间为48*10/9600 = 50ms
根据我的经验,我使用斯赖得最烂的modicon neza plc,modbus协议,19200,n,8,1,一般的数据30byte之内,tx之后50ms就可以rx了,如果数据量很大(如100byte以上,当然,每次发送与接收的数据量都小于256byte,这是mosbus规约所限)200ms足够了。
我还测试过看这个plc最快什么时候能够反应过来,结果证实延时25ms的时候,通信开始不可靠,并不是每次发送之后plc都能回应。所以我使用50ms的延时,实践证明是可行的。
你用9600bps,速度也不会慢到那里去,单纯数据的发送与接收都是很快的,发送48个字节所需的时间为48*10/9600 = 50ms