在vc串口通讯程序中,当4个com口同时通信时表现串口很不稳定,请问各位应怎么处理?

时间:2021-02-23 20:38:44
在vc串口通讯程序中,当4个com口同时通信时表现串口很不稳定,请问各位应怎么处理?
谢谢各位

14 个解决方案

#1


那应该是你自己的线程设计不够好,或是共享资源没有互斥吧

#2


谢谢,能够说详细一点吗 
我用的是CreateFile()ReadFile() WriteFile() 同步实现的

#3


现在就是串口不稳定,一会正常一会丢失 ,很急 求大侠帮忙

#4


4个com口同时通信时,降低 波特率 试试。

#5


你用多线程做的吗?每个线程处理一个串口?

#6


降低波特率 不行呀

#7


这个我读串口的程序
HANDLE CComRW::CreateCom()
{
DWORD dwError;
// TODO: Add extra validation here
/*
// m_hCom=INVALID_HANDLE_VALUE;
if (m_hCom!=INVALID_HANDLE_VALUE)
{
CloseHandle(m_hCom);
HANDLE m_hCom =INVALID_HANDLE_VALUE;
}
*/
// DWORD dwError=0;
dwError=0;
BOOL fSuccess=FALSE;


char com[100];
//sprintf(com,"\\\.\\COM%d",m_nComSel);
sprintf(com,"COM%d",m_nComSel);
HANDLE hCom = CreateFile(com,
GENERIC_READ | GENERIC_WRITE,
0,    // comm devices must be opened w/exclusive-access 
NULL, // no security attributes 
OPEN_EXISTING, // comm devices must use OPEN_EXISTING 
0,    // not overlapped I/O 
NULL  // hTemplate must be NULL for comm devices 
);

if (hCom == INVALID_HANDLE_VALUE) 
{
dwError = GetLastError();
LOGINFO(0,"%s 无法打开! 错误码=%d",com,dwError);
return INVALID_HANDLE_VALUE;
    // handle error 
}

// Omit the call to SetupComm to use the default queue sizes.
// Get the current configuration.
DCB dcb;
fSuccess = GetCommState(hCom, &dcb);

if (!fSuccess) 
{
dwError = GetLastError();
LOGINFO(0,"%s GetCommState erorr code=%d",com,dwError);
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
    // Handle the error. 
}

// Fill in the DCB: baud=9600, 8 data bits, no parity, 1 stop bit. 

dcb.BaudRate = m_nBPS;
// dcb.BaudRate = CBR_57600;
dcb.ByteSize = 8;
// dcb.Parity = ODDPARITY;
dcb.Parity = checka[m_nParity];
// dcb.Parity = NOPARITY;
dcb.StopBits = stopa[m_nStopBit];
// dcb.StopBits = ONESTOPBIT;
fSuccess = SetCommState(hCom, &dcb);

if (!fSuccess) 
{
dwError = GetLastError();
LOGINFO(0,"%s SetCommState code=%d",com,dwError);
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
    // Handle the error. 
}

COMMTIMEOUTS CommTimeouts;

fSuccess = GetCommTimeouts(hCom,&CommTimeouts);
if (!fSuccess) 
{
dwError = GetLastError();
LOGINFO(0,"%s GetCommTimeouts code=%d",com,dwError);
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
    // Handle the error. 
}
CommTimeouts.ReadIntervalTimeout=MAXDWORD;
CommTimeouts.ReadTotalTimeoutConstant=0; //0.3 seconds
CommTimeouts.ReadTotalTimeoutMultiplier=0;
fSuccess = SetCommTimeouts(hCom,&CommTimeouts);
if (!fSuccess) 
{
dwError = GetLastError();
LOGINFO(0,"%s SetCommTimeouts code=%d",com,dwError);
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
    // Handle the error. 
}

LOGINFO(0,"%s open bps=%d handle=%x",com,dcb.BaudRate,hCom);
// m_hCom=hCom;
ResetRunData();

m_hCom=hCom;
return hCom;

}


void CComRW::CloseCom()
{
if (m_hCom!=INVALID_HANDLE_VALUE)
{
CloseHandle(m_hCom);
m_hCom=INVALID_HANDLE_VALUE;
}
ResetRunData();
}

void CComRW::FlushRead()
{
if (m_hCom==INVALID_HANDLE_VALUE)
{
return;
}

BYTE tmp[1024];
BOOL ret;
for(;;)
{
DWORD rn=0;
ret=ReadFile(m_hCom,tmp,sizeof(tmp),&rn,NULL);
if (!ret || !rn)
{
return;
}
}
}

void CComRW::ReadCom()
{
if (m_hCom==INVALID_HANDLE_VALUE)
{
return;
}

DWORD dw=0;
BOOL ret=ReadFile(m_hCom,m_abyComData+m_nTotalRead,sizeof(m_abyComData)-m_nTotalRead,&dw,NULL);
if (!ret)
{
LOGINFO(0,"com read error=%d",GetLastError());
return;
}

if (dw==0)
{
m_nIdleNbr++;
if (m_nIdleNbr>=m_nProcessAfterIdleNbr)
{
if (m_nTotalRead>0)
{
ProcessMsg();
}
m_nIdleNbr=0;
}
return;
}
else
{
LOGSIG(LL_UDP,m_abyComData+m_nTotalRead,dw,"READ COM %d bytes",dw);
m_nTotalRead+=dw;
m_nIdleNbr=0;
}

}


void CComRW::WriteCom(void* p,int len)
{
DWORD wn=0;
BOOL ret=WriteFile(m_hCom,p,len,&wn,NULL);
LOGSIG(LL_UDP,p,len,"WRIT COM %d bytes ret=%d wn=%d",len,ret,wn);
if (!ret)
{
LOGINFO(0,"write error=%d",GetLastError());
return;
}
if (wn!=len)
{
LOGINFO(0,"write error1=%d",GetLastError());
}
}

#8


BOOL ret=ReadFile(m_hCom,m_abyComData+m_nTotalRead,sizeof(m_abyComData)-m_nTotalRead,&dw,NULL);
阻塞式的读?
BOOL ret=WriteFile(m_hCom,p,len,&wn,NULL);
如何区分4个 com?

#9


先问楼主1个问题:
你读取串口数据的机制是怎样设计的?是主程序中设计好了固定的时间间隔,然后定时到串口的缓存中取数;还是主程序中的串口通信控件响应接收事件,当检测到有数据发过来之后再去取数?

#10


1.每个串口都有一个ID
2.采用固定时间间隔去轮询

#11


关注一下    我们马上也要用到。

#12


你的timeout好像有点短,
我的一个案例:
COMMTIMEOUTS timeout;
timeout.ReadIntervalTimeout=2;
timeout.ReadTotalTimeoutMultiplier=2;
timeout.ReadTotalTimeoutConstant=50;
timeout.WriteTotalTimeoutMultiplier=1;
timeout.WriteTotalTimeoutConstant=50;
另外DCB的XonLim和XoffLim也检查一下

#13


还是使用事件触发吧!

#14


谢谢大家 已经解决

#1


那应该是你自己的线程设计不够好,或是共享资源没有互斥吧

#2


谢谢,能够说详细一点吗 
我用的是CreateFile()ReadFile() WriteFile() 同步实现的

#3


现在就是串口不稳定,一会正常一会丢失 ,很急 求大侠帮忙

#4


4个com口同时通信时,降低 波特率 试试。

#5


你用多线程做的吗?每个线程处理一个串口?

#6


降低波特率 不行呀

#7


这个我读串口的程序
HANDLE CComRW::CreateCom()
{
DWORD dwError;
// TODO: Add extra validation here
/*
// m_hCom=INVALID_HANDLE_VALUE;
if (m_hCom!=INVALID_HANDLE_VALUE)
{
CloseHandle(m_hCom);
HANDLE m_hCom =INVALID_HANDLE_VALUE;
}
*/
// DWORD dwError=0;
dwError=0;
BOOL fSuccess=FALSE;


char com[100];
//sprintf(com,"\\\.\\COM%d",m_nComSel);
sprintf(com,"COM%d",m_nComSel);
HANDLE hCom = CreateFile(com,
GENERIC_READ | GENERIC_WRITE,
0,    // comm devices must be opened w/exclusive-access 
NULL, // no security attributes 
OPEN_EXISTING, // comm devices must use OPEN_EXISTING 
0,    // not overlapped I/O 
NULL  // hTemplate must be NULL for comm devices 
);

if (hCom == INVALID_HANDLE_VALUE) 
{
dwError = GetLastError();
LOGINFO(0,"%s 无法打开! 错误码=%d",com,dwError);
return INVALID_HANDLE_VALUE;
    // handle error 
}

// Omit the call to SetupComm to use the default queue sizes.
// Get the current configuration.
DCB dcb;
fSuccess = GetCommState(hCom, &dcb);

if (!fSuccess) 
{
dwError = GetLastError();
LOGINFO(0,"%s GetCommState erorr code=%d",com,dwError);
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
    // Handle the error. 
}

// Fill in the DCB: baud=9600, 8 data bits, no parity, 1 stop bit. 

dcb.BaudRate = m_nBPS;
// dcb.BaudRate = CBR_57600;
dcb.ByteSize = 8;
// dcb.Parity = ODDPARITY;
dcb.Parity = checka[m_nParity];
// dcb.Parity = NOPARITY;
dcb.StopBits = stopa[m_nStopBit];
// dcb.StopBits = ONESTOPBIT;
fSuccess = SetCommState(hCom, &dcb);

if (!fSuccess) 
{
dwError = GetLastError();
LOGINFO(0,"%s SetCommState code=%d",com,dwError);
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
    // Handle the error. 
}

COMMTIMEOUTS CommTimeouts;

fSuccess = GetCommTimeouts(hCom,&CommTimeouts);
if (!fSuccess) 
{
dwError = GetLastError();
LOGINFO(0,"%s GetCommTimeouts code=%d",com,dwError);
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
    // Handle the error. 
}
CommTimeouts.ReadIntervalTimeout=MAXDWORD;
CommTimeouts.ReadTotalTimeoutConstant=0; //0.3 seconds
CommTimeouts.ReadTotalTimeoutMultiplier=0;
fSuccess = SetCommTimeouts(hCom,&CommTimeouts);
if (!fSuccess) 
{
dwError = GetLastError();
LOGINFO(0,"%s SetCommTimeouts code=%d",com,dwError);
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
    // Handle the error. 
}

LOGINFO(0,"%s open bps=%d handle=%x",com,dcb.BaudRate,hCom);
// m_hCom=hCom;
ResetRunData();

m_hCom=hCom;
return hCom;

}


void CComRW::CloseCom()
{
if (m_hCom!=INVALID_HANDLE_VALUE)
{
CloseHandle(m_hCom);
m_hCom=INVALID_HANDLE_VALUE;
}
ResetRunData();
}

void CComRW::FlushRead()
{
if (m_hCom==INVALID_HANDLE_VALUE)
{
return;
}

BYTE tmp[1024];
BOOL ret;
for(;;)
{
DWORD rn=0;
ret=ReadFile(m_hCom,tmp,sizeof(tmp),&rn,NULL);
if (!ret || !rn)
{
return;
}
}
}

void CComRW::ReadCom()
{
if (m_hCom==INVALID_HANDLE_VALUE)
{
return;
}

DWORD dw=0;
BOOL ret=ReadFile(m_hCom,m_abyComData+m_nTotalRead,sizeof(m_abyComData)-m_nTotalRead,&dw,NULL);
if (!ret)
{
LOGINFO(0,"com read error=%d",GetLastError());
return;
}

if (dw==0)
{
m_nIdleNbr++;
if (m_nIdleNbr>=m_nProcessAfterIdleNbr)
{
if (m_nTotalRead>0)
{
ProcessMsg();
}
m_nIdleNbr=0;
}
return;
}
else
{
LOGSIG(LL_UDP,m_abyComData+m_nTotalRead,dw,"READ COM %d bytes",dw);
m_nTotalRead+=dw;
m_nIdleNbr=0;
}

}


void CComRW::WriteCom(void* p,int len)
{
DWORD wn=0;
BOOL ret=WriteFile(m_hCom,p,len,&wn,NULL);
LOGSIG(LL_UDP,p,len,"WRIT COM %d bytes ret=%d wn=%d",len,ret,wn);
if (!ret)
{
LOGINFO(0,"write error=%d",GetLastError());
return;
}
if (wn!=len)
{
LOGINFO(0,"write error1=%d",GetLastError());
}
}

#8


BOOL ret=ReadFile(m_hCom,m_abyComData+m_nTotalRead,sizeof(m_abyComData)-m_nTotalRead,&dw,NULL);
阻塞式的读?
BOOL ret=WriteFile(m_hCom,p,len,&wn,NULL);
如何区分4个 com?

#9


先问楼主1个问题:
你读取串口数据的机制是怎样设计的?是主程序中设计好了固定的时间间隔,然后定时到串口的缓存中取数;还是主程序中的串口通信控件响应接收事件,当检测到有数据发过来之后再去取数?

#10


1.每个串口都有一个ID
2.采用固定时间间隔去轮询

#11


关注一下    我们马上也要用到。

#12


你的timeout好像有点短,
我的一个案例:
COMMTIMEOUTS timeout;
timeout.ReadIntervalTimeout=2;
timeout.ReadTotalTimeoutMultiplier=2;
timeout.ReadTotalTimeoutConstant=50;
timeout.WriteTotalTimeoutMultiplier=1;
timeout.WriteTotalTimeoutConstant=50;
另外DCB的XonLim和XoffLim也检查一下

#13


还是使用事件触发吧!

#14


谢谢大家 已经解决