我用一个串口类操作串口,用了2、3年没有问题 
最近一个项目,电脑通过串口不停查询外设状态,
外设接收到指令字符串后会立即返回相应信息字符串
软件收到返回的字符串后再发送指令字符串 , 就这样循环当查询次数较多后读写操作均失败
如果两次查询间无间隔,最多几百次后就会失败
如果加10ms左右延时,能坚持到几千次,然后也不可避免读写都失败发送的命令字符串不到20字节
返回的状态字节约10字节我以前用同样的类完成接收几十k数据都没出过问题
当时时每十几秒一次数据发送接收,来回交互数次
没有这次这样频繁读写各位大虾帮忙分析下看看下面是我用的串口类简单代码m_hCom=CreateFile(m_sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);
DWORD CSerialPort::ReadComm(char *buf,DWORD dwLength)
{
DWORD length=0;
COMSTAT ComStat;
DWORD dwErrorFlags;
ClearCommError(m_hCom,&dwErrorFlags,&ComStat);

length=min(dwLength, ComStat.cbInQue);
if(0==length) return length;

ReadFile(m_hCom,buf,length,&length,&m_osRead);

return length;
}DWORD CSerialPort::WriteComm(char *buf,DWORD dwLength)
{
BOOL fState;
DWORD length=dwLength;
COMSTAT ComStat;
DWORD dwErrorFlags;
// PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR);
ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
fState=WriteFile(m_hCom,buf,dwLength,&length,&m_osWrite);
if(!fState)
{
if(GetLastError()==ERROR_IO_PENDING)
GetOverlappedResult(m_hCom,&m_osWrite,&length,TRUE);// 等待
else
length=0;
}
return length;
}
BOOL CSerialPort::SendStr(CString cmdStr)
{
int len = WriteComm(cmdStr.GetBuffer(cmdStr.GetLength()),cmdStr.GetLength());
cmdStr.ReleaseBuffer();
if(len != cmdStr.GetLength())
{
logComStr(cmdStr,"send failed");
return FALSE;
}
else
{
logComStr(cmdStr,"send ok");
return TRUE;
}
}BOOL CSerialPort::ReadStr(CString &resStr,DWORD timeout)
{
DWORD st = GetTickCount();
resStr = "";
do
{
char chtmp=0;
if(ReadComm(&chtmp,1) != 0)
{
resStr += chtmp;
if('\n' == chtmp)
break;
}
if(GetTickCount()-st>timeout)
{
CString errStr.Format("Read timeout,%d",GetTickCount()-st);
logComStr(resStr,errStr);
return FALSE;
}
}while(1); logComStr(resStr,"Read ok");
return TRUE;
}
我的循环基本就是for(;;)
{
CString cmdstr,resstr;
cmdstr="xxxx";
if(SendStr(cmdstr))
{
if(ReadStr(resStr,1000))
{
//处理resStr
}
}
// sleep(10);
}

解决方案 »

  1.   

    m_hCom=CreateFile(m_sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);
    是否执行了多次
      

  2.   

    只CreateFile了一次
    后来我把FILE_FLAG_OVERLAPPED去掉,也只是延缓了操作失败出现的时间
      

  3.   

    CString在频繁调用的时候可能会出现内存问题,而且你在函数
    SendStr(CString  cmdStr) 
    中传入的时CString对象,最好改成引用,效率可以高一些,内存占用可以少一些。
      

  4.   

    波特率为115200
    电脑串口连接一个rs485转接到外设谢谢 Mackz(在相互) 的建议,我会试一下我想不是外设的及连接线等的问题,如果是的话应该是read不到或read得到错误结果
    实际是发送也会失败,即便没有接线发送也应该是可以的
      

  5.   

    算一下:
    波特率为115200bps,即14400字节/秒,来回通讯一次30个字节的话,只能达到480次/秒的通讯次数。这只是理论上的,实际上因为波特率设得太高(波特率为115200bps已经算高的了)了,能传输的距离就缩短了,而且传输错误的可能性大增,导致发送、接收数据失败,这又会大大降低实际的通讯次数。
    综上,波特率在满足速度的前提下,尽量设低些。数据量可以自己估算一下约多少次/秒,再算出所需速率。
      

  6.   

    最近又有一个项目
    工控机要和PLC频繁通讯
    再次碰到上述问题。
    这次我做了一个实验,写了一个小程序,只循环发送字符串
    电脑串口不接外设
    在115200波特率下,问题电脑大多数情况下不出10秒即出现写串口失败,
    少数时候能挺到半分钟
    而当波特率降到9600后,实验一个多小时都没有出现异常也许lfchen说的有点道理我的通讯方式由于只是一个循环,无任何线程,
    每次write之前都会purge,我想不应该存在堵塞问题
    GetOverlappedResult(m_hCom,&m_osWrite,&length,TRUE)在超时后居然返回TRUE -_-
    这时GetLastError()基本是ERROR_IO_INCOMPLETE,也出现过几次ERROR_IO_PENDING
    有人能解释一下吗?
      

  7.   

    没人关注?昨天又做了些实验,
    弄了块串口卡插在问题电脑上
    实验结果串口卡上的几个串口一点问题都没有
    跑了几个小时一切ok, 应该是硬件问题倒是我用串口调试助手接受我的小程序发送的数据
    在接收一小段时间后(约一分钟或更短),
    点串口调试助手界面上的关闭串口,没用,助手继续接收数据
    再点打开串口,助手死了......
    或者重选一下波特率啊、数据位啊这些也会死
    haha