为何我的串口线程读数据时总是慢一拍呢,郁闷啊!!!

时间:2022-12-18 23:29:54
// 写函数
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;
}

#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

#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;
}

#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