用MFC做个串口通信的软件,出现很奇怪的错误,成员变量在一个函数改变后,跳出该函数后成员变量的值却没变
我在软件InitDlg中设置时钟3,等时钟3到后进行设备初始化ConectDevice();在设备初始化函数中,发送串口命令,在串口响应函数中把串口接收的数据放到成员变量...
我在软件InitDlg中设置时钟3,
等时钟3到后进行 设备初始化ConectDevice();
在设备初始化函数中,发送串口命令,
在串口响应函数中 把串口接收的数据放到成员变量m_strCARXData,用MessageBox显示出来m_strCARXData为接收的数据不为空
设备初始化函数中,发送串口命令后等待300ms,读取变量m_strCARXData,用MessageBox显示m_strCARXData的值却为空,???再次调用MessageBox显示m_strCARXData的值却为正常的数据???
为什么第一次调用MessageBox m_strCARXData的值却为空?第二次调用MessageBoxm_strCARXData的值却为正常的数据?
代码:
串口响应
void CEEICalculateDlg::OnMscommCa()
{
//。。。省略
if(m_ComCA.GetCommEvent()==2) //值为 2 表示接收缓冲区内有字符
{
。。。省略
//从串口读取数据到变量 m_strCARXData中
if (m_strCARXData.Find(_T("OK"))!=-1)//接受到的数据格式为(X为数据):OK00,XXX.XX
{
m_strRealBr=m_strCARXData;
m_strRealBr=m_strRealBr.Right(6);//取 从右边取5位亮度数据
m_dCARXData = atof(m_strRealBr);
//MessageBox(m_strCARXData);//在这里m_strCARXData可以接受到数据
}
else
{
//MessageBox("没有接受到CA数据OK");
m_strRealBr=m_strCARXData;//当接受到错误数据时显示出来
}
}
}
设置SetTimer(3,1000,Null)
OnTimer( UINT nIDEVENT)
{
if(nIDEVENT==3)
{
Kill(3);
ConectDevice();//初始化设备
}
}
ConectDevice();//初始化设备
{
if (OpenComCA())
{
if (SendData(1,_T("COM,1"));==1)//发送串口命令 打开Remote on
{
Sleep(300);//等待200ms
//+++串口数据,
UpdateData(FALSE);
if (m_strCARXData.Find(_T("OK"))!=-1)//需要CA210测试
{
m_strCAStat=_T("已连接");
ReCode=1;
}
MessageBox(m_strCARXData); 第一次调用MessageBox 为空?
MessageBox(m_strCARXData); 第二次调用MessageBox正常数据?
}
}
SetDlgItemText(IDC_STATIC_CA_STATE,m_strCAStat);
} 展开
等时钟3到后进行 设备初始化ConectDevice();
在设备初始化函数中,发送串口命令,
在串口响应函数中 把串口接收的数据放到成员变量m_strCARXData,用MessageBox显示出来m_strCARXData为接收的数据不为空
设备初始化函数中,发送串口命令后等待300ms,读取变量m_strCARXData,用MessageBox显示m_strCARXData的值却为空,???再次调用MessageBox显示m_strCARXData的值却为正常的数据???
为什么第一次调用MessageBox m_strCARXData的值却为空?第二次调用MessageBoxm_strCARXData的值却为正常的数据?
代码:
串口响应
void CEEICalculateDlg::OnMscommCa()
{
//。。。省略
if(m_ComCA.GetCommEvent()==2) //值为 2 表示接收缓冲区内有字符
{
。。。省略
//从串口读取数据到变量 m_strCARXData中
if (m_strCARXData.Find(_T("OK"))!=-1)//接受到的数据格式为(X为数据):OK00,XXX.XX
{
m_strRealBr=m_strCARXData;
m_strRealBr=m_strRealBr.Right(6);//取 从右边取5位亮度数据
m_dCARXData = atof(m_strRealBr);
//MessageBox(m_strCARXData);//在这里m_strCARXData可以接受到数据
}
else
{
//MessageBox("没有接受到CA数据OK");
m_strRealBr=m_strCARXData;//当接受到错误数据时显示出来
}
}
}
设置SetTimer(3,1000,Null)
OnTimer( UINT nIDEVENT)
{
if(nIDEVENT==3)
{
Kill(3);
ConectDevice();//初始化设备
}
}
ConectDevice();//初始化设备
{
if (OpenComCA())
{
if (SendData(1,_T("COM,1"));==1)//发送串口命令 打开Remote on
{
Sleep(300);//等待200ms
//+++串口数据,
UpdateData(FALSE);
if (m_strCARXData.Find(_T("OK"))!=-1)//需要CA210测试
{
m_strCAStat=_T("已连接");
ReCode=1;
}
MessageBox(m_strCARXData); 第一次调用MessageBox 为空?
MessageBox(m_strCARXData); 第二次调用MessageBox正常数据?
}
}
SetDlgItemText(IDC_STATIC_CA_STATE,m_strCAStat);
} 展开
4个回答
展开全部
这个函数
OnMscommCa() 是串口有数据的时候的消息响应,那么就是主线程必须处在消息循环不停滞的情况下才能响应这个函数,你Sleep(300);//等待200ms 这不是让主线程消息循环暂停了吗?
那Sleep过了,主线程才读取消息队列的消息进行处理,所以你立即MessageBox(m_strCARXData); 是在数据未被读取时进行的,而等你弹出消息框,主线程消息循环是继续的,这时OnMscommCa() 读取数据完毕,所以你第二次弹出的时候就成了。
OnMscommCa() 是串口有数据的时候的消息响应,那么就是主线程必须处在消息循环不停滞的情况下才能响应这个函数,你Sleep(300);//等待200ms 这不是让主线程消息循环暂停了吗?
那Sleep过了,主线程才读取消息队列的消息进行处理,所以你立即MessageBox(m_strCARXData); 是在数据未被读取时进行的,而等你弹出消息框,主线程消息循环是继续的,这时OnMscommCa() 读取数据完毕,所以你第二次弹出的时候就成了。
追问
网上搜了下还不是太明白,是不是这样理解MessageBox(m_strCARXData)时,MessageBox内部应该有一个循环,在不停地处理主窗口队列里面的消息(可以处理OnMscommCa())消息。
所以当第一次MessageBox(m_strCARXData)时系统会处理OnMscommCa()读取到数据到m_strCARXData,第二次MessageBox时m_strCARXData就有了数据。
追答
主线程消息循环就一个而已,我说的是Sleep使得主线程消息循环停滞,不能处理串口数据,而Sleep结束,消息循环继续,不管你是弹出MessageBox还是处理串口数据,都是消息循环负责发送消息的,由于处理数据的过程和消息框是顺序进行的,弹出消息框后,一旦有空闲时间,那么串口数据消息就会被处理,如果你在弹出消息框后,OnMscommCa里面有死循环,那么你的消息框就看起来假死了。
而你现在的情况,第一个消息框一旦弹出,只有关闭了才弹出第二个消息框,所以,第一个消息框弹出后程序有空闲时间就把数据处理了。
如果要实现那个等待,你可以再使用定时器,或者用线程中进行串口操作,这样在子线程中Sleep不会影响主线程,有数据要主线程显示的时候,就发消息给主线程对应的窗口即可。
展开全部
其实就是接收延时的问题,看你的代码,定时发送一次数据,然后停300ms等接受,然后想弹出对话框显示其接受内容。但实际上,你的串口发送命令是单开线程运行的,很可能你即使等300毫秒,你的senddata都没有执行完或者还没有执行,所以OnMscommCa也没有给m_strCARXData赋值,因而你第一次messagebox没有内容,但是等你点击关闭了对话框,再弹出第二个的时候,至少也有1秒钟的时间,这个时间对于我们虽短,但对于计算机,线程调度已经n多次,也足够让你的串口发送完,并且也接收完数据,所以就能显示数据了。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
等待时间不够吧,在打开Remote on之后,做一个while循环,循环中sleep,直到m_str的Length不为0,这样逻辑就比较合理了,为了防止死机,也可以加一个计数器,当等待时间超过10次(3秒)这样子不行就退出循环,返回失败。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
2012-12-26
展开全部
UpdateData
追问
已经调用UpdateData(FALSE); 还是不行
追答
调试 很费时间
祝你顺利
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询