串口通讯问题

时间:2021-03-11 17:57:40
我写的串口通讯程序与一般的迷你USB串口,虚拟串口以及串口卡的串口通讯都没有问题,今天用标准USB串口进行通讯时发现数据包发送了一遍(通过监控工具发现数据发送完全),但是没有任何数据返回,同时接着发送第二遍时通过监控工具就看不到有数据发送了,应该是串口死掉,重启串口再次发送,又与上面情况一致。
请问这是什么原因呢?麻烦大家给分析提供个解决思路,谢谢了

13 个解决方案

#1


帮顶,程序执行没报错吗?

#2


没有报错,调试时发现在监听串口时,发现串口线程进入了死锁状态,就是一直在死等返回消息。代码如下:

unsigned long WINAPI TSerialPort::CommThread(LPVOID Param)
{
TSerialPort *Port = (TSerialPort *)Param;
if (NULL == Port)
{
        ExitThread(0);
}

if (INVALID_HANDLE_VALUE == Port->m_Comm)
{
ExitThread(0);
}

Port->m_ThreadAlive = true;

unsigned long Event = 0;
unsigned long CommEvent = 0;
unsigned long Error = 0;
COMSTAT Comstate;
bool Result = true;

PurgeComm(Port->m_Comm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
while(1)
{
Result = WaitCommEvent(Port->m_Comm, &Event, &Port->m_Overlapped);
if (Result)
{
Result = ClearCommError(Port->m_Comm, &Error, &Comstate);
if (Comstate.cbInQue == 0)
{
continue;
}
}
else
{
 Error = GetLastError();
        }

Event = WaitForMultipleObjects(3, Port->m_EventArray, false, INFINITE);
switch(Event)
{
case 0:
         Port->m_ThreadAlive = false;
         ExitThread(0);
break;
case 1:
GetCommMask(Port->m_Comm, &CommEvent);
if (CommEvent & EV_RXCHAR)
{
ReceiveChar(Port, Comstate);
}
break;
case 2:
SendChar(Port);
break;
}
}
return 0;
}

#3


如果我是用其他方式操作串口的话,即使没有读到数据,也不会使串口线程死锁;很奇怪为什么会出现这样的问题。

#4


while循环怎么退出来呢?
是不是应该写成
while(Port->m_ThreadAlive)

#5


谢谢亲们的热心回复,我这个串口线程在平时工作都好好的,即使没有捕获到串口数据线程也会退出。楼上说我的while循环需要更改为while(Port->m_ThreadAlive),但是问题是,串口一直都是打开的,线程我也加了个判断,更改如下:

unsigned long WINAPI TSerialPort::CommThread(LPVOID Param)
{
TSerialPort *Port = (TSerialPort *)Param;
if (NULL == Port)
{
        ExitThread(0);
}

if (INVALID_HANDLE_VALUE == Port->m_Comm)
{
ExitThread(0);
}

Port->m_ThreadAlive = true;

unsigned long Event = 0;
unsigned long CommEvent = 0;
unsigned long Error = 0;
COMSTAT Comstate;
bool Result = true;

    if( Port->m_Comm )
PurgeComm(Port->m_Comm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
while(1)
{
Result = WaitCommEvent(Port->m_Comm, &Event, &Port->m_Overlapped);
if (Result)
{
Result = ClearCommError(Port->m_Comm, &Error, &Comstate);
if (Comstate.cbInQue == 0)
{
continue;
}
}
else
{
 switch (Error = GetLastError())
            {   
            case ERROR_IO_PENDING:    
                {   
                    // This is a normal return value if there are no bytes  
                    // to read at the port.  
                    // Do nothing and continue  
                    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:  
{
                    // All other error codes indicate a serious error has  
                    // occured.  Process this error.  
                    Port->ProcessErrorMessage("WaitCommEvent()");  
                    break;  
}
}
}

Event = WaitForMultipleObjects(3, Port->m_EventArray, false, INFINITE);
switch(Event)
{
case 0:
         Port->m_ThreadAlive = false;
         ExitThread(0);
break;
case 1:
GetCommMask(Port->m_Comm, &CommEvent);//-------1
if (CommEvent & EV_RXCHAR)  //如果屏蔽这句,用标准串口能接收到数据,但
{                           //即使接收到了,依旧在“1”中死循环。
ReceiveChar(Port, Comstate);
}
break;
case 2:
SendChar(Port);
break;
}
}
return 0;
}

#6


顶顶更健康~~

#7


顶顶更健康,期待热心专家

#8


把串口接收和发送端短接在一起测试

#9


你是和谁通信的,谁返回你?会不会是通信的另一方有问题,或者就是你发送的数据类型有问题。应该先检查下第一次没成功的问题。
应该不是串口线程的问题

#10


引用 8 楼 Wang471981125 的回复:
把串口接收和发送端短接在一起测试

以前的通讯工装都是通过九针的串口接头来连接,这样可以通过短接的方式进行自发自收的测试。我们现在的工装就是直接用普通的USB接口连接电脑,方形的标准usb接口连接通讯工装,无需电源,通过MBUS通讯方式直接与被检设备连接。

引用 9 楼 jichao1010 的回复:
你是和谁通信的,谁返回你?会不会是通信的另一方有问题,或者就是你发送的数据类型有问题。应该先检查下第一次没成功的问题。
应该不是串口线程的问题

我用低版本的串口助手也出现与我同样的问题,高版本的就没事了,估计还是串口线程的问题,可是一直找不到问题点所在

#11


最近忙于其他项目,忘记这件事情了,惜乎还是没有解决,求帮助

#12


引用 9 楼 jichao1010 的回复:
你是和谁通信的,谁返回你?会不会是通信的另一方有问题,或者就是你发送的数据类型有问题。应该先检查下第一次没成功的问题。
应该不是串口线程的问题

赞成。
有可能不是你的程序死掉了。而是在漫长的等待中。INFINITE这个可是不小的一个数,而且你没有超时响应。

#13


我估计可能是USB转串口的问题,性能不太稳定

#1


帮顶,程序执行没报错吗?

#2


没有报错,调试时发现在监听串口时,发现串口线程进入了死锁状态,就是一直在死等返回消息。代码如下:

unsigned long WINAPI TSerialPort::CommThread(LPVOID Param)
{
TSerialPort *Port = (TSerialPort *)Param;
if (NULL == Port)
{
        ExitThread(0);
}

if (INVALID_HANDLE_VALUE == Port->m_Comm)
{
ExitThread(0);
}

Port->m_ThreadAlive = true;

unsigned long Event = 0;
unsigned long CommEvent = 0;
unsigned long Error = 0;
COMSTAT Comstate;
bool Result = true;

PurgeComm(Port->m_Comm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
while(1)
{
Result = WaitCommEvent(Port->m_Comm, &Event, &Port->m_Overlapped);
if (Result)
{
Result = ClearCommError(Port->m_Comm, &Error, &Comstate);
if (Comstate.cbInQue == 0)
{
continue;
}
}
else
{
 Error = GetLastError();
        }

Event = WaitForMultipleObjects(3, Port->m_EventArray, false, INFINITE);
switch(Event)
{
case 0:
         Port->m_ThreadAlive = false;
         ExitThread(0);
break;
case 1:
GetCommMask(Port->m_Comm, &CommEvent);
if (CommEvent & EV_RXCHAR)
{
ReceiveChar(Port, Comstate);
}
break;
case 2:
SendChar(Port);
break;
}
}
return 0;
}

#3


如果我是用其他方式操作串口的话,即使没有读到数据,也不会使串口线程死锁;很奇怪为什么会出现这样的问题。

#4


while循环怎么退出来呢?
是不是应该写成
while(Port->m_ThreadAlive)

#5


谢谢亲们的热心回复,我这个串口线程在平时工作都好好的,即使没有捕获到串口数据线程也会退出。楼上说我的while循环需要更改为while(Port->m_ThreadAlive),但是问题是,串口一直都是打开的,线程我也加了个判断,更改如下:

unsigned long WINAPI TSerialPort::CommThread(LPVOID Param)
{
TSerialPort *Port = (TSerialPort *)Param;
if (NULL == Port)
{
        ExitThread(0);
}

if (INVALID_HANDLE_VALUE == Port->m_Comm)
{
ExitThread(0);
}

Port->m_ThreadAlive = true;

unsigned long Event = 0;
unsigned long CommEvent = 0;
unsigned long Error = 0;
COMSTAT Comstate;
bool Result = true;

    if( Port->m_Comm )
PurgeComm(Port->m_Comm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
while(1)
{
Result = WaitCommEvent(Port->m_Comm, &Event, &Port->m_Overlapped);
if (Result)
{
Result = ClearCommError(Port->m_Comm, &Error, &Comstate);
if (Comstate.cbInQue == 0)
{
continue;
}
}
else
{
 switch (Error = GetLastError())
            {   
            case ERROR_IO_PENDING:    
                {   
                    // This is a normal return value if there are no bytes  
                    // to read at the port.  
                    // Do nothing and continue  
                    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:  
{
                    // All other error codes indicate a serious error has  
                    // occured.  Process this error.  
                    Port->ProcessErrorMessage("WaitCommEvent()");  
                    break;  
}
}
}

Event = WaitForMultipleObjects(3, Port->m_EventArray, false, INFINITE);
switch(Event)
{
case 0:
         Port->m_ThreadAlive = false;
         ExitThread(0);
break;
case 1:
GetCommMask(Port->m_Comm, &CommEvent);//-------1
if (CommEvent & EV_RXCHAR)  //如果屏蔽这句,用标准串口能接收到数据,但
{                           //即使接收到了,依旧在“1”中死循环。
ReceiveChar(Port, Comstate);
}
break;
case 2:
SendChar(Port);
break;
}
}
return 0;
}

#6


顶顶更健康~~

#7


顶顶更健康,期待热心专家

#8


把串口接收和发送端短接在一起测试

#9


你是和谁通信的,谁返回你?会不会是通信的另一方有问题,或者就是你发送的数据类型有问题。应该先检查下第一次没成功的问题。
应该不是串口线程的问题

#10


引用 8 楼 Wang471981125 的回复:
把串口接收和发送端短接在一起测试

以前的通讯工装都是通过九针的串口接头来连接,这样可以通过短接的方式进行自发自收的测试。我们现在的工装就是直接用普通的USB接口连接电脑,方形的标准usb接口连接通讯工装,无需电源,通过MBUS通讯方式直接与被检设备连接。

引用 9 楼 jichao1010 的回复:
你是和谁通信的,谁返回你?会不会是通信的另一方有问题,或者就是你发送的数据类型有问题。应该先检查下第一次没成功的问题。
应该不是串口线程的问题

我用低版本的串口助手也出现与我同样的问题,高版本的就没事了,估计还是串口线程的问题,可是一直找不到问题点所在

#11


最近忙于其他项目,忘记这件事情了,惜乎还是没有解决,求帮助

#12


引用 9 楼 jichao1010 的回复:
你是和谁通信的,谁返回你?会不会是通信的另一方有问题,或者就是你发送的数据类型有问题。应该先检查下第一次没成功的问题。
应该不是串口线程的问题

赞成。
有可能不是你的程序死掉了。而是在漫长的等待中。INFINITE这个可是不小的一个数,而且你没有超时响应。

#13


我估计可能是USB转串口的问题,性能不太稳定