先把代码贴上。说明在后面!
void CFanDlg::OnButtonSendCommond() 
{

CString string="AA0104070000B6";
//senddata通过串口发送命令到下位机
CString temp;
//写串口命令的每一位
        temp=string.Mid(0,1);
m_com.buffer[0]=CString_Tran_Int(temp);
temp="";
temp=string.Mid(2,1);
m_com.buffer[1]=CString_Tran_Int(temp);
temp="";
temp=string.Mid(4,1);
m_com.buffer[2]=CString_Tran_Int(temp);
temp="";
temp=string.Mid(6,1);
m_com.buffer[3]=CString_Tran_Int(temp);
temp="";
temp=string.Mid(8,1);
m_com.buffer[4]=CString_Tran_Int(temp);
temp="";
temp=string.Mid(10,1);
m_com.buffer[5]=CString_Tran_Int(temp);
temp="";
temp=string.Mid(12,1);
m_com.buffer[6]=CString_Tran_Int(temp);

//将命令通过串口发送出去
m_com.ComWrite(m_com.buffer,7);
}LRESULT CFanDlg::OnReceive(WPARAM wParam, LPARAM lParam)
{
char sz[255];
CString outputstring="";
CString str;
CString s;
int len = m_com.ReadString(sz,255);
for(int i=0;i<len;i++)
{
s.Format("%02x",(BYTE)sz[i]);
str += s + " ";
}
outputstring=str;
str+="\r\n";
//将结果数据显示在文本框
m_edit.SetWindowText(str);
return 0;
}
DWORD CSerial::ThreadProc()//串口线程,异步方式
{
if(!::SetCommMask(m_hCom, m_dwMaskEvent))
{
::MessageBox(m_hNotifyWnd, " SetCommMask failed", "", 0);
return -1;
}
DWORD dwError, dwMask, dwTrans;
COMSTAT Stat;
while(!m_bExit)
{
dwMask = 0;
if(!::WaitCommEvent(m_hCom, &dwMask, &m_WaitOl))
{
if(::GetLastError() == ERROR_IO_PENDING)
{
::GetOverlappedResult(m_hCom, &m_WaitOl, &dwTrans, TRUE);
}
else
continue;
}
switch(dwMask)
{
case EV_RXCHAR:
{
::ClearCommError(m_hCom, &dwError, &Stat);
if(Stat.cbInQue >= m_dwNotifyNum)
{
if(::IsWindow(m_hNotifyWnd))
::PostMessage(m_hNotifyWnd, WM_COM_RECEIVE, 0, 0);
}
}
break;
case EV_TXEMPTY:
OnTXEmpty();
break;

default:
continue;
}
}
return 0;
}
程序目标:在窗口中向串口发命令,串口处理命令后,向窗口返回结果,结果数据显示在窗口上
实现方法:串口单独一个线程,循环监听串口事件,见ThreadProc函数,采用异步通信。窗口函数OnButtonSendCommond向串口发送命令,窗口函数OnReceive响应串口发回的消息(自定义消息WM_COM_RECEIVE)从串口读结果数据,显示在窗口上.
出现问题:向串口写一条命令,串口线程函数执行了两次case EV_RXCHAR:,窗口函数onreceive也执行了两次。本来第一次数据是正确的,可第二次又读为空又把正确数据覆盖掉了。还有设断点调试的时候一切正常,case EV_RXCHAR:和窗口函数onreceive都执行一次。实在没辙了,请高手帮我解脱了吧,睡不着觉呀。我也知道这是两个线程协调问题,可是就是不知道错在什么地方,请谅解一个新手的无知。

解决方案 »

  1.   

    楼主,应该是string.Mid(x,2)吧?
      

  2.   

    另外你的OnButtonSendCommond() 函数写的很麻烦的,直接一个循环就了然了,你还全部列出来
    我不知道你发送的数据是你的字符串格式呢,还是需要转换为十六进制,至于你的问题,线程函数应该是全局函数,这个你肯定是设置正确了的,其他好像我没发现什么问题,所以暂时不了然,MARK下。
      

  3.   

    ::PostMessage(m_hNotifyWnd, WM_COM_RECEIVE, 0, 0);改成::SendMessage(m_hNotifyWnd, WM_COM_RECEIVE, 0, 0);
      

  4.   

    default后面是continue;
    就是说一旦是进入default了,就一直执行case语句了,还是另外有解释呢?
      

  5.   

    这个我曾经想过,也改过,一样的效果,甚至连窗口函数再重入都看了,可是还是那样,sendmessage也是两遍,这我就很纳闷了,有人说SENDMESSAGE不是本窗口不进程序队列,这就改成POST了,还是那样的
      

  6.   

    这个不是我的程序,但是我感觉,这个continue应该是继续下一次while循环吧,就是继续监视下一次事件
      

  7.   


    可以在消息发送过去后,Sleep(100)
      

  8.   

    加了还是两次呀?加了sleep(1000)都还两次
      

  9.   

    你改下::GetOverlappedResult(m_hCom, &m_WaitOl, &dwTrans, TRUE);
    的参数试试。我上次也有这样问题。后来把TRUE改成FALSE就行了,也不知道为什么
      

  10.   

    楼主你先确定是不是真的只发了一次命令
    然后,GetOverlappedResult没有检查返回值啊
      

  11.   

    是发了一次命令,执行两次的第二次就到overlappedresult那个函数里面执行去了,请问这是为什么呀?不过参照12楼的大大的,果然有用,就只有一次,然后overlappedresult也执行,就是没有返回结果。希望指点一下