求教串口通讯问题

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

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:
                {    
                    break;  
                }  
            case 87:  
                {   
                    break;  
                }
            default:  

                    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);
if (CommEvent & EV_RXCHAR)    //如果屏蔽掉这句,能够接收到完整的数据包;
{                             //但是接收完后还在这里死循环,不解。。。
                                                      //如果不屏蔽,就在这里死循环。
ReceiveChar(Port, Comstate);
}
break;
case 2:
SendChar(Port);
break;
}
}
return 0;
}

16 个解决方案

#1


以前通讯没问题不要先怀疑程序问题,先用串口调试工具试一下有反应吗?再确定问题在那儿。

#2


二楼说的对, 若程序以往没问题的话, 先用工具排查接口的问题, USB转串口硬件、驱动都有过不稳定的情况出现

#3


有的串口调试助手是出现和我一样的问题,比如龚建伟老师的;有的串口调试助手就没有问题,比如唐老鸭头像的那个串口工具。所以初步确定应该是线程处理方面的问题,但是不知道该从哪里着手,只要我把这句"GetCommMask(Port->m_Comm, &CommEvent);
            if (CommEvent & EV_RXCHAR)  "屏蔽掉,发现能接收到数据包,但是依旧会在此进入死循环,导致再次发送数据时因为线程死锁而数据无法发送的情况。只有将该串口重新打开后又会第一次发送成功,但是线程死锁又出现上述情况

#4


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

#5


冯华亮的一段源码, 用了近10年了,一直没问题,你参考一下
//线程执行函数
void __fastcall TComThread::Execute()
{
if(hComm==INVALID_HANDLE_VALUE)  //串口句柄有效
{
Application->MessageBox("串口句柄无效,串口监控线程无法工作.","错误",MB_ICONSTOP);
return;
}
//清空串口缓冲区,退出所有相关操作
PurgeComm(hComm, PURGE_RXCLEAR|PURGE_TXCLEAR|
PURGE_RXABORT|PURGE_TXABORT);

COMSTAT ComStat;        //串口状态
DWORD dwEvent,dwError,dwResult;
//进入无限循环,直到线程被关闭
while(!Terminated)
{
//调用WaitCommEvent().这一调用将立即返回,因为我用异步方式
//(FILE_FLAG_OVERLAPPED)打开串口,并且指定重叠操作结构,
//如果有一个字符到达串口,重叠结构中的事件将被置为有信号态
bool bResult=WaitCommEvent(hComm,&dwEvent,&ov_Read);
if (!bResult)
{
//如果WaitCommEvent()返回FALSE,调用GetLastError()判断原因
                        dwError=GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:      //重叠操作正在后台进行
{
//如果串口这时无字符,这是正常返回值,继续
break;
}
case 87:
{
//在WIN NT下这是一个可能结果,但我没有找到
//它出现的原因,我什么也不做,继续
break;
}
default:
{
//所有其它错误代码均显示串口出错,显示出错信息
ProcessErrorMessage("等待串口事件");
return;
}
}
}
else
{
//如果WaitCommEvent()返回true,检查输入缓冲区是否确实
//有字节可读,若没有,则继续下一循环
//ClearCommError()将更新串口状态结构并清除所有串口硬件错误
ClearCommError(hComm,&dwError,&ComStat);
if (ComStat.cbInQue==0)   //输入缓冲队列长为0,无字符
continue;
}

//等待串口事件产生
dwResult=WaitForSingleObject(ov_Read.hEvent,1000);
                if(dwResult==WAIT_OBJECT_0) //事件产生
                {
//获取串口事件掩码
GetCommMask(hComm,&dwEvent);
if (dwEvent & EV_RXCHAR) //有一个字符
    ReceiveAChar(); //接收一个字符

                }
}                                           
}

#6


求教串口通讯问题

#7


楼主搜一下串口调试助手的源程序,看看里面是怎么做的

#8


帮你顶起 求教串口通讯问题

#9


引用 5 楼 phder 的回复:
冯华亮的一段源码, 用了近10年了,一直没问题,你参考一下
//线程执行函数
void __fastcall TComThread::Execute()
{
if(hComm==INVALID_HANDLE_VALUE)  //串口句柄有效
{
Application->MessageBox("串口句柄无效,串口监控线程无法工作.","错误",MB_ICONSTOP);
return;
}
//清空串口缓冲区,退出所有相关操作
PurgeComm(hComm, PURGE_RXCLEAR|PURGE_TXCLEAR|
PURGE_RXABORT|PURGE_TXABORT);

COMSTAT ComStat;        //串口状态
DWORD dwEvent,dwError,dwResult;
//进入无限循环,直到线程被关闭
while(!Terminated)
{
//调用WaitCommEvent().这一调用将立即返回,因为我用异步方式
//(FILE_FLAG_OVERLAPPED)打开串口,并且指定重叠操作结构,
//如果有一个字符到达串口,重叠结构中的事件将被置为有信号态
bool bResult=WaitCommEvent(hComm,&dwEvent,&ov_Read);
if (!bResult)
{
//如果WaitCommEvent()返回FALSE,调用GetLastError()判断原因
                        dwError=GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:      //重叠操作正在后台进行
{
//如果串口这时无字符,这是正常返回值,继续
break;
}
case 87:
{
//在WIN NT下这是一个可能结果,但我没有找到
//它出现的原因,我什么也不做,继续
break;
}
default:
{
//所有其它错误代码均显示串口出错,显示出错信息
ProcessErrorMessage("等待串口事件");
return;
}
}
}
else
{
//如果WaitCommEvent()返回true,检查输入缓冲区是否确实
//有字节可读,若没有,则继续下一循环
//ClearCommError()将更新串口状态结构并清除所有串口硬件错误
ClearCommError(hComm,&dwError,&ComStat);
if (ComStat.cbInQue==0)   //输入缓冲队列长为0,无字符
continue;
}

//等待串口事件产生
dwResult=WaitForSingleObject(ov_Read.hEvent,1000);
                if(dwResult==WAIT_OBJECT_0) //事件产生
                {
//获取串口事件掩码
GetCommMask(hComm,&dwEvent);
if (dwEvent & EV_RXCHAR) //有一个字符
    ReceiveAChar(); //接收一个字符

                }
}                                           
}

谢谢您的参考源码。我的这段代码只是针对目前的标准USB接口时出现了问题,一直接收不到数据,串口线程进入了死等(一直认为数据在回收状态)

#10


都是同样的,USB上面的金手指不也是四个管脚吗,5V、GND、IN和OUT

#11


还得从程序上找问题

#12


你使用串口调试助手能收能发吗?

#13


引用 11 楼 sunxingzhesun 的回复:
还得从程序上找问题

谢谢您的思想指导,我正在寻找程序上的问题

#14


没有什么思想上的哈,你在程序中几个关键节点添加断点试试,看看一些关键变量的值,就能知道能不能收到,希望你尽快解决问题

#15


能确定不是驱动或者是其他别的原因造成的么? 还是要通过串口监听看数据到底是否有效发送。有没有其他的类似设备试试?如果是设备本身硬件原因造成的话,会走弯路。

#16


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

#1


以前通讯没问题不要先怀疑程序问题,先用串口调试工具试一下有反应吗?再确定问题在那儿。

#2


二楼说的对, 若程序以往没问题的话, 先用工具排查接口的问题, USB转串口硬件、驱动都有过不稳定的情况出现

#3


有的串口调试助手是出现和我一样的问题,比如龚建伟老师的;有的串口调试助手就没有问题,比如唐老鸭头像的那个串口工具。所以初步确定应该是线程处理方面的问题,但是不知道该从哪里着手,只要我把这句"GetCommMask(Port->m_Comm, &CommEvent);
            if (CommEvent & EV_RXCHAR)  "屏蔽掉,发现能接收到数据包,但是依旧会在此进入死循环,导致再次发送数据时因为线程死锁而数据无法发送的情况。只有将该串口重新打开后又会第一次发送成功,但是线程死锁又出现上述情况

#4


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

#5


冯华亮的一段源码, 用了近10年了,一直没问题,你参考一下
//线程执行函数
void __fastcall TComThread::Execute()
{
if(hComm==INVALID_HANDLE_VALUE)  //串口句柄有效
{
Application->MessageBox("串口句柄无效,串口监控线程无法工作.","错误",MB_ICONSTOP);
return;
}
//清空串口缓冲区,退出所有相关操作
PurgeComm(hComm, PURGE_RXCLEAR|PURGE_TXCLEAR|
PURGE_RXABORT|PURGE_TXABORT);

COMSTAT ComStat;        //串口状态
DWORD dwEvent,dwError,dwResult;
//进入无限循环,直到线程被关闭
while(!Terminated)
{
//调用WaitCommEvent().这一调用将立即返回,因为我用异步方式
//(FILE_FLAG_OVERLAPPED)打开串口,并且指定重叠操作结构,
//如果有一个字符到达串口,重叠结构中的事件将被置为有信号态
bool bResult=WaitCommEvent(hComm,&dwEvent,&ov_Read);
if (!bResult)
{
//如果WaitCommEvent()返回FALSE,调用GetLastError()判断原因
                        dwError=GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:      //重叠操作正在后台进行
{
//如果串口这时无字符,这是正常返回值,继续
break;
}
case 87:
{
//在WIN NT下这是一个可能结果,但我没有找到
//它出现的原因,我什么也不做,继续
break;
}
default:
{
//所有其它错误代码均显示串口出错,显示出错信息
ProcessErrorMessage("等待串口事件");
return;
}
}
}
else
{
//如果WaitCommEvent()返回true,检查输入缓冲区是否确实
//有字节可读,若没有,则继续下一循环
//ClearCommError()将更新串口状态结构并清除所有串口硬件错误
ClearCommError(hComm,&dwError,&ComStat);
if (ComStat.cbInQue==0)   //输入缓冲队列长为0,无字符
continue;
}

//等待串口事件产生
dwResult=WaitForSingleObject(ov_Read.hEvent,1000);
                if(dwResult==WAIT_OBJECT_0) //事件产生
                {
//获取串口事件掩码
GetCommMask(hComm,&dwEvent);
if (dwEvent & EV_RXCHAR) //有一个字符
    ReceiveAChar(); //接收一个字符

                }
}                                           
}

#6


求教串口通讯问题

#7


楼主搜一下串口调试助手的源程序,看看里面是怎么做的

#8


帮你顶起 求教串口通讯问题

#9


引用 5 楼 phder 的回复:
冯华亮的一段源码, 用了近10年了,一直没问题,你参考一下
//线程执行函数
void __fastcall TComThread::Execute()
{
if(hComm==INVALID_HANDLE_VALUE)  //串口句柄有效
{
Application->MessageBox("串口句柄无效,串口监控线程无法工作.","错误",MB_ICONSTOP);
return;
}
//清空串口缓冲区,退出所有相关操作
PurgeComm(hComm, PURGE_RXCLEAR|PURGE_TXCLEAR|
PURGE_RXABORT|PURGE_TXABORT);

COMSTAT ComStat;        //串口状态
DWORD dwEvent,dwError,dwResult;
//进入无限循环,直到线程被关闭
while(!Terminated)
{
//调用WaitCommEvent().这一调用将立即返回,因为我用异步方式
//(FILE_FLAG_OVERLAPPED)打开串口,并且指定重叠操作结构,
//如果有一个字符到达串口,重叠结构中的事件将被置为有信号态
bool bResult=WaitCommEvent(hComm,&dwEvent,&ov_Read);
if (!bResult)
{
//如果WaitCommEvent()返回FALSE,调用GetLastError()判断原因
                        dwError=GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:      //重叠操作正在后台进行
{
//如果串口这时无字符,这是正常返回值,继续
break;
}
case 87:
{
//在WIN NT下这是一个可能结果,但我没有找到
//它出现的原因,我什么也不做,继续
break;
}
default:
{
//所有其它错误代码均显示串口出错,显示出错信息
ProcessErrorMessage("等待串口事件");
return;
}
}
}
else
{
//如果WaitCommEvent()返回true,检查输入缓冲区是否确实
//有字节可读,若没有,则继续下一循环
//ClearCommError()将更新串口状态结构并清除所有串口硬件错误
ClearCommError(hComm,&dwError,&ComStat);
if (ComStat.cbInQue==0)   //输入缓冲队列长为0,无字符
continue;
}

//等待串口事件产生
dwResult=WaitForSingleObject(ov_Read.hEvent,1000);
                if(dwResult==WAIT_OBJECT_0) //事件产生
                {
//获取串口事件掩码
GetCommMask(hComm,&dwEvent);
if (dwEvent & EV_RXCHAR) //有一个字符
    ReceiveAChar(); //接收一个字符

                }
}                                           
}

谢谢您的参考源码。我的这段代码只是针对目前的标准USB接口时出现了问题,一直接收不到数据,串口线程进入了死等(一直认为数据在回收状态)

#10


都是同样的,USB上面的金手指不也是四个管脚吗,5V、GND、IN和OUT

#11


还得从程序上找问题

#12


你使用串口调试助手能收能发吗?

#13


引用 11 楼 sunxingzhesun 的回复:
还得从程序上找问题

谢谢您的思想指导,我正在寻找程序上的问题

#14


没有什么思想上的哈,你在程序中几个关键节点添加断点试试,看看一些关键变量的值,就能知道能不能收到,希望你尽快解决问题

#15


能确定不是驱动或者是其他别的原因造成的么? 还是要通过串口监听看数据到底是否有效发送。有没有其他的类似设备试试?如果是设备本身硬件原因造成的话,会走弯路。

#16


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