我想在一个按钮响应函数中,发送一个数据包,然后等待一段时间后,再对接收的数据进行判断。我想用MSCOMM控件来实现,请问可不可以?我在发送数据后,用Sleep函数让线程等待一段时间,可是仍然不会产生CommEvent,要等到执行完这个按钮中所有的语句才会响应。请高手指点,谢谢!

解决方案 »

  1.   

    Windows中的程序是消息驱动的
    while(!GetMessage(...))
    {
      switch(msg.message)
      {
      case ...:
        Function();
      ...
      }
    }
    因此实际上没有中断来产生,一个按钮消息产生后只有消息Function()处理完成后才会获取到下一个消息,因此这种情况是正常的,不是代码问题
      

  2.   

    怎么用查询方式啊,能不能给出详细的代码,本人是个超级菜鸟。是不是不能用这个控件了,要用API函数实现或者用一个串口类啊。不过我还想用这个控件,不知道能不能行?
      

  3.   

    没用过MSCOMM,不过看了你的问题,说说我的想法.
    既然想等commevent发生再继续执行,不如加个mutex,互斥变量。
      

  4.   

    MZP互斥变量怎么加?怎么用?能不能给出代码?
      

  5.   

    CSDN的高人都进来看看啊,我这个问题都发了2天了还没解决啊。
      

  6.   

    请问
    CreateMutex
    WaitForSingleObject
    在哪里创建,用的时候怎么用,能不能给出详细的代码。本人实在太菜了
    我的程序中的一部分如下:void CMovequipDlg::OnButton10() 
    {
    // TODO: Add your control notification handler code here
    CMainFrame * pMainFrame = (CMainFrame*)AfxGetMainWnd();
    CAutoMedView * pAutoMedView = (CAutoMedView*)pMainFrame->GetActiveView();
    OnButton1();//对机器发送一条指令,然后它作出相应的动作后返回一条指令。
             Sleep(1000);
    pAutoMedView->OnComm();
             pAutoMedView->m_strReceiveData;//等待接收缓冲区里的数据,然后判断做下一步。这里主要是要接收到数据,然后才能最下一步。
    OnButton2();
    Sleep(2000);
    }
      

  7.   

    http://cs.nju.edu.cn/yangxc/dcc2003.files/jszc-sub/comif-30.htm
      

  8.   

    http://www.vczx.com/article/show.php?id=790
    换个控件试试
      

  9.   

    示例:
    初始化:
    bool CYourClass::OpenPort()
    {
    if(m_Comm.GetPortOpen())
    m_Comm.SetPortOpen(FALSE);
    m_Comm.SetCommPort(m_iPort); //选择com1
    if( !m_Comm.GetPortOpen())
    m_Comm.SetPortOpen(TRUE); //打开串口
    else
    AfxMessageBox("cannot open serial port"); m_Comm.SetSettings(_T("1200,E,8,1")); //波特率1200,无校验,8个数据位,1个停止位
    m_Comm.SetSThreshold(0); 
    m_Comm.SetRThreshold(1); //参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
    m_Comm.SetInputMode(1);
    m_Comm.SetInputLen(0); //设置当前接收区数据长度为0
    return true;
    }
    发送:
    CByteArray bArryFrame;
    bArryFrame.Add(0x68);
    bArryFrame.Add(0x23);
    m_Comm.SetOutput(COleVariant(bArryFrame));接收:
    CByteArray  m_RecFrameArray_All;(类中定义即可)
    void CYourClass::OnCommMscommCtrl() 
    {
    // TODO: Add your control notification handler code here
    Sleep(300); VARIANT variant_inp;
    COleSafeArray safearray_inp;
    CString csDispString;
    LONG len;
    BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.
    short ENO;
    CString strtemp;
    ENO=1;BYTE bt;CString csByte,csResult;
    if(1)//bReceive)
    {
    ENO=m_Comm.GetCommEvent();

    if(ENO==2)     //事件值为2表示接收缓冲区内有字符
    {
    variant_inp = m_Comm.GetInput(); //读缓冲区
    safearray_inp = variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
    len=safearray_inp.GetOneDimSize(); //得到有效数据长度
    for(LONG iter=0;iter<len;iter++)
    {
    safearray_inp.GetElement(&iter,rxdata+iter); //转换为BYTE型数组 bt=*(char*)(rxdata+iter);m_RecFrameArray_All.Add(bt);
    strtemp.Format("%02X ",m_RecFrameArray_All.ElementAt(iter));
    csResult+=strtemp;
    }
    }
      

  10.   

    如果是VC程序,建议不要用MSCOMM控件,自己用API实现,也没几句代码兼容性还好,不过我在网吧,没法给例子。
      

  11.   

    我的代码是这样写的:
    void CAutoMedView::OnInitialUpdate()
    {
    m_Comm.SetCommPort(1);
    m_Comm.SetInBufferSize(1024);
    m_Comm.SetOutBufferSize(512);
    if(!m_Comm.GetPortOpen())
    m_Comm.SetPortOpen(TRUE);
    m_Comm.SetInputMode(1);
    m_Comm.SetRThreshold(1);
    m_Comm.SetSettings("9600,n,8,1");
    m_Comm.SetInputLen(0);
    m_Comm.GetInput();
    m_Comm.SetEOFEnable(true);}
    ////////////////////
    void CAutoMedView::OnOnCommMscomm() 
    {
    // TODO: Add your control notification handler code here
    Sleep(3000);
    VARIANT m_Input1; 
    COleSafeArray m_Input2; 
    long length,i;
    BYTE data[1024]; 
    CString str; 
    if(m_Comm.GetCommEvent()==2) 
    {
    m_Input1=m_Comm.GetInput();
    m_Input2=m_Input1;
    length=m_Input2.GetOneDimSize(); 
    for(i=0;i<length;i++)
    m_Input2.GetElement(&i,data+i);
    for(i=0;i<length;i++) 

    BYTE a=*(char*)(data+i); 
    str.Format("%02X ",a); 
    m_strReceiveData+=str;    
    }
    }
    UpdateData(false);
    }
    ////////////////////////////
    void CMovequipDlg::OnButton3() 
    {
    // TODO: Add your control notification handler code here
    CMainFrame * pMainFrame = (CMainFrame*)AfxGetMainWnd();
    CAutoMedView * pAutoMedView = (CAutoMedView*)pMainFrame->GetActiveView();
    byte.RemoveAll();
    UpdateData(TRUE);
    switch(m_nHprobe)
    {
    case 0:
    packet = "a5c5a040000000f5";
    break;
    case 1:
    packet = "a5c5a140000000f5";
    break;
    case 2:
    packet = "a5c5a240000000f5";
    break;
    case 3:
    packet = "a5c5a340000000f5";
    break;
    case 4:
    packet = "a5c5a440000000f5";
    break;
    default:
    AfxMessageBox("请输入0--4之间的数");
    return;
    }
    pAutoMedView->String2Hex(packet,byte);
    pAutoMedView->m_Comm.SetOutput(COleVariant(byte));

    }
    //////////////////////////////////////////////////
    void CMovequipDlg::OnButton4() 
    {
    // TODO: Add your control notification handler code here
    CMainFrame * pMainFrame = (CMainFrame*)AfxGetMainWnd();
    CAutoMedView * pAutoMedView = (CAutoMedView*)pMainFrame->GetActiveView();
    byte.RemoveAll();
             UpdateData(TRUE);
    CString str;
    switch(m_nHsamplingpin)
    {
    case 0:
    packet = "a5c7a140000000f5";
    break;
    case 1:
    packet = "a5c7a240000000f5";
    break;
    default:
    AfxMessageBox("请输入0--1之间的数");
    return;
    }
    pAutoMedView->String2Hex(packet,byte);
    pAutoMedView->m_Comm.SetOutput(COleVariant(byte));

    }
    void CMovequipDlg::OnButton10() 
    {
    // TODO: Add your control notification handler code here
    CMainFrame * pMainFrame = (CMainFrame*)AfxGetMainWnd();
    CAutoMedView * pAutoMedView = (CAutoMedView*)pMainFrame->GetActiveView();
    OnButton3();
             Sleep(2000);
    pAutoMedView->OnComm();
    //在这里对收到的数据进行判断,然后再进行其它数据的发送。可是进入 OnOnCommMscomm()函数它并不执行if(m_Comm.GetCommEvent()==2)这个判断里的内容,不管Sleep多久。        
    OnButton4();
    UpdateData(false);
    }
      

  12.   

    void CMovequipDlg::OnButton10() 
    {
    OnButton3();
             Sleep(2000);
    }
    你在事件处理函数中调用事件处理函数.OnButtton3是不会执行的.你可以跟踪一下
      

  13.   

    wy311216
    我的OnButton3()里实际也是发送数据的,我跟踪了,实际实际是执行的,及时把他换成,OnButton3()里的语句也没有意义,我现在主要想解决的是,在一个按钮里,同时发送然后等下微机处理完数据后,在接收数据,对其判断,然后再发数据。
      

  14.   

    BOOL CComTestDlg::ComInitialize(int i)
    {
    if(m_com.GetPortOpen())
    {
    //若有开启的COM口则关闭
    m_com.SetPortOpen(FALSE);
    }
    m_com.SetCommPort(i); 
    if (!m_com.GetPortOpen())
    {
    //打开串口
    m_com.SetPortOpen(TRUE);
    }
    //波特率9600,无校验,8个数据位,1个停止位
    m_com.SetSettings("19200,n,8,1"); 
    // 以二进制方式检取数据,参数取0数据以文字形式取回
    m_com.SetInputMode(1);  
    //参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
    m_com.SetRThreshold(1);
    //先预读缓冲区以清除残留数据
    m_com.GetInput();
    return TRUE;
    }void CComTestDlg::OnButtonopencom() 
    {
    UpdateData(TRUE);
    if(!(m_comValue == "1" || m_comValue == "2") )

    {
    MessageBox("请选择需要打开的COM口");
    return;
    }
    ComInitialize(atoi(m_comValue));
    m_openBtn.EnableWindow(FALSE);
    m_sendBtn.EnableWindow(TRUE);
    m_importBtn.EnableWindow(TRUE);
    }void CComTestDlg::OnClose() 
    {
    if(m_com.GetPortOpen())
    {
    //若有开启的COM口则关闭
    m_com.SetPortOpen(FALSE);
    }
    DestroyWindow();

    }void CComTestDlg::OnOnCommMscomm() 
    {
    CListCtrl *preturnListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST2);
    CListCtrl *pdataListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST1);
    //定义VARIANT型变量 
        VARIANT m_input1;
        //定义COleSafeArray型变量
        COleSafeArray m_input2; 
    int length; 
    LONG i;
    //定义字节数组   
        BYTE data[128],datahead; 
    CString str,str1; 
    //接收缓冲区内字符 
    if(m_com.GetCommEvent()== 2) 
    {  
    m_com.SetInputLen(1);
    //从缓冲区读数据
    m_input1=m_com.GetInput(); 
    //将VARIANT型变量转换为ColeSafeArray型变量 
    m_input2=m_input1; 
    //将数据转换为BYTE型数组 
    for(i=0;i< 1;i++) 
    m_input2.GetElement(&i,data+i);
    datahead=data[0];
    //传送出的数据得到正确响应,终止定时器,删除第一个数据
    if(datahead==0xA5)
    {
    KillTimer(1);
    pdataListCtrl->DeleteItem(0);
    Send();
    }
    //重发第一个数据
    else if(datahead==0xA6)//发送出去的数据错误,重新发送.
    {
    Send();
    }
    else if(datahead==0x5A)//发送过来的命令
    {
    m_com.SetInputLen(1);
    m_input1=m_com.GetInput();
    m_input2=m_input1;
    for(i=0;i< 1;i++) 
    m_input2.GetElement(&i,data+i);
    length=data[0];
    m_com.SetInputLen(length);
    //从缓冲区读数据
    //Sleep(50);
    m_input1=m_com.GetInput(); 
    //将VARIANT型变量转换为ColeSafeArray型变量 
    m_input2=m_input1; 
    //将数据转换为BYTE型数组 
    for(i=0;i< length;i++) 
    m_input2.GetElement(&i,data+i); 
    //m_data1=data[1];//sno
    //m_data2=data[2]+1;//bno
    BYTE CHKRESULT = 0;
    for(i=0;i<length;i++)//校验数据的正确与否。CHK+SNO+BNO+BARCODE[1]+BARCODE[N]
    {
    CHKRESULT+=data[i];
    }
    if(CHKRESULT==0)
    {
    //preturnListCtrl添加数据
    CString strBoxNo,strReaderNo,strData;
    strBoxNo.Format("%d",data[1]);
    strReaderNo.Format("%d",data[2]+1);
    strData.Format("0x%02X",data[3]);
    int i = preturnListCtrl->GetItemCount();
    pdataListCtrl->InsertItem(LVIF_TEXT|LVIF_STATE,i,strBoxNo,0,LVIS_SELECTED,0,0);
    pdataListCtrl->SetItemText(i,1,strReaderNo);
    pdataListCtrl->SetItemText(i,2,strData);
    }
    }
    else if(datahead==0xA7)
    {
     
    }
    }
    }//将CString转为CByteArray
    void CComTestDlg::String2Hex(CString str, CByteArray &senddata)
    {
    int hexdata,lowhexdata;
    int hexdatalen=0;
    int len=str.GetLength();
    senddata.SetSize(len/2);
    for(int i=0;i<len;)
    {
    char lstr,hstr=str[i];
    if(hstr==' ')
    {
    i++;
    continue;
    }
    i++;
    if(i>=len)
    break;
    lstr=str[i];
    hexdata=ConvertHexChar(hstr);
    lowhexdata=ConvertHexChar(lstr);
    if((hexdata==16)||(lowhexdata==16))
    break;
    else 
    hexdata=hexdata*16+lowhexdata;
    i++;
    senddata[hexdatalen]=(char)hexdata;
    hexdatalen++;
    }
    }//这是一个将字符转换为相应的十六进制值的函数
    //功能:若是在0-F之间的字符,则转换为相应的十六进制字符,否则返回-1
    char CComTestDlg::ConvertHexChar(char ch) 
    {
    if((ch>='0')&&(ch<='9'))
    return ch-0x30;
    else if((ch>='A')&&(ch<='F'))
    return ch-'A'+10;
    else if((ch>='a')&&(ch<='f'))
    return ch-'a'+10;
    else return (-1);
    }void CComTestDlg::SendData(CString str,int sno,int bno)//向串接器发送命令
    {
    CByteArray hexdata;
    CString str1 = "";
    CString str2 = "";
    CString str3 = "";
    int CMD[5];
    int result = 0;
    int check = 0;
    int header = 0x5A;
    int len = str.GetLength();
    BYTE data[128];

    for (int i=0; i<len; i++) 
    {
    data[i] = str.GetAt(i);
    result = result +  data[i];
    str1.Format("%02X", data[i]); //$
    str2 += str1;
    }

    str3 = str2;
    //计算校验码
    check = 256-(sno + bno + result - 1)%256;
    CMD[0] = 0x5A;
        CMD[1] = len + 3;
        CMD[2] = check;
        CMD[3] = sno;
        CMD[4] = bno - 1; str1 = "";
    str2 = "";
    for(i=0;i<5;i++) 

    str1.Format("%02X",CMD[i]); //$
    str2 += str1; 
    }
    //向串口发送数据
    str = str2 + str3;
        String2Hex(str,hexdata);
    m_com.SetOutput(COleVariant(hexdata)); //发送数据
    }//发送数据到串口
    void CComTestDlg::OnSend() 
    {
    Send();
    }//发送数据到串口
    void CComTestDlg::Send()
    {
    //从datalist中得到要发送的数据发送出去
    CString strBoxNo;
    CString strReaderNo;
    CString strData;
    int BoxNo;
    int ReaderNo;
    CListCtrl *pdataListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST1);

    if (pdataListCtrl->GetItemCount() <= 0)
    {
    //MessageBox("没有数据");
    return;
    }

    strBoxNo = pdataListCtrl->GetItemText(0,0);
    strReaderNo = pdataListCtrl->GetItemText(0,1);
    strData = pdataListCtrl->GetItemText(0,2);
    BoxNo = atoi(strBoxNo.GetBuffer(0));
    ReaderNo = atoi(strReaderNo.GetBuffer(0));
    SendData(strData, BoxNo, ReaderNo);
    //启动定时器
    SetTimer(1,20000,NULL);
    }void CComTestDlg::OnTimer(UINT nIDEvent) 
    {
    switch(nIDEvent)
    {
    case 1:
    Send();
    break;
    case 2:
    ;
    }
    //CDialog::OnTimer(nIDEvent);
    }void CComTestDlg::OnClear() 
    {
    //CListCtrl *preturnListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST2);
    //preturnListCtrl->DeleteAllItems();
    MessageBox("hello");
    }
    void CComTestDlg::OnImport() 
    {
    CListCtrl *pdataListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST1);
    pdataListCtrl->DeleteAllItems();

    CString szLine = "";
    CString strBoxNo = "";
    CString strReaderNo = "";
    CString strData = "";
    CFileFind find;
    if(!find.FindFile(".//data.txt"))
    {
    MessageBox("没有可导入的数据文件");
    return;
    }
    CStdioFile file;
    file.Open("data.txt",CFile::modeRead);

    while(file.ReadString(szLine))
    {
    if(szLine != "")
    {
    CString str = "";
    szLine.TrimLeft();
            szLine.TrimRight();
    for(int i=0; i<szLine.GetLength(); i++)
    {
    str = szLine.Mid(i,1);
    if(str == " ")
    {
    strBoxNo = szLine.Left(i);
    szLine = szLine.Mid(i);
    szLine.TrimLeft();
    szLine.TrimRight();
    break;
    }
    }

    if(szLine != "")
    {
    CString str1 = "";
    for(int k=0; k<szLine.GetLength(); k++)
    {
    str1 = szLine.Mid(k,1);
    if(str1 == " ")
    {
    strReaderNo = szLine.Left(k);
    szLine = szLine.Mid(k);
    szLine.TrimLeft();
    szLine.TrimRight();
    break;
    }
    }
    if(szLine != "")
    {
    strData = szLine;
    }
    }
    if(strBoxNo=="" || strReaderNo=="" || strData == "")
    {
    continue;
    }
    int j = pdataListCtrl->GetItemCount(); pdataListCtrl->InsertItem(LVIF_TEXT|LVIF_STATE,j,strBoxNo,0,LVIS_SELECTED,0,0);
    pdataListCtrl->SetItemText(j,1,strReaderNo);
    pdataListCtrl->SetItemText(j,2,strData);
    strBoxNo = "";
    strReaderNo = "";
    strData = "";
    }
    }
    }
      

  15.   

    pAutoMedView->OnComm();
    虽然你触发了串口事件,但是和接收到外部数据触发的串口事件是两个不同的线程.所以你在OnButton10里面接收数据是不可能收到的.你得在OnComm事件处理里面接收
      

  16.   

    pAutoMedView->OnComm();
    这个我也知道,不过是想检验一下在按钮执行的过程中是否能响应OnComm事件处理,我也说过了它根本不会去执行if(m_Comm.GetCommEvent()==2) 里面的东东。
      

  17.   

    程序并没有错, ComEvReceive也可能发生了(如果通信连接正确的话.),怀疑测试过程中发送的数据太少,当你点击void CAutoMedView::OnOnCommMscomm() 所对应的工具或菜单时发送已经完成,此时收到的是ComEvEOF事件.建议1:把m_Comm.SetPortOpen(TRUE);放到OnOnCommMscomm()函数中;建议2:对m_Comm.GetCommEvent()==2返回的事件进行逐一判断,这应该是好习惯.