int CCHARGESYSTEMView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
AfxMessageBox("OnCreate首部");
///////////////////////////////////////////////////////////////////////////////////////   
    if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
////////////////////////////////////////////////////////////////////////////////初始化串口^_^
    
CString m;
CCHARGESYSTEMApp* app=(CCHARGESYSTEMApp*)AfxGetApp();
    m.Format("%d,n,8,1",app->iRate);
m_MSComm.Create(NULL,0,CRect(0,0,0,0),this,IDC_MSCOMM1);//创建控件
//如果串口是打开的,则行关闭串口
if(m_MSComm.GetPortOpen()){m_MSComm.SetPortOpen(FALSE);}
m_hComDev=m_MSComm.GetCommID();
m_MSComm.SetCommPort(app->iPort);//根据全局变量赋值
m_MSComm.SetInBufferSize(1024);//输入缓冲区的大小
m_MSComm.SetOutBufferSize(1024);//输出缓冲区的大小
m_MSComm.SetInBufferCount(0);//清空输入缓冲区
m_MSComm.SetOutBufferCount(0);//清空输出缓冲区
m_MSComm.SetInputLen(0);//设置当前接收区数据长度位0,表示全部读取
m_MSComm.SetInputMode(1);//以二进制方式读写数据
    m_MSComm.SetRThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件,这里有待商讨
    m_MSComm.SetSThreshold(1);//发送缓冲区有1个及1个以上字符时触发OnComm();
m_MSComm.SetSettings(m);//使用全局变量的字符串赋值
m_MSComm.SetHandshaking(2);
if(!m_MSComm.GetPortOpen())m_MSComm.SetPortOpen(TRUE);//串口如果未打开,则打开
else
{
AfxMessageBox("Open Serial Port Failure!");//打开失败时,报告!!!!
    return -1;
}
    m_MSComm.GetInput();//先预读缓冲区以清除残留数据
///////////////////////////////////////////////////////////////////////////////////////////
// 下面是初始化的命令
//////////////////////////////////////////////////////////////////////////////////////////
     CString a;
 a="AT\r\n";
 SendString(a);  ::Sleep(1000);
 a="ATE0\r\n";
 SendString(a);
 ::Sleep(200);
 a="AT+CMGF=0";
 //SendString(a);
 //::Sleep(300);
//////////////////////////////////////////////////////////////////////////////////////////
     return 0;
}
void CCHARGESYSTEMView::OnComm()

VARIANT vResponse;
char *str;
char *str1;
int k, nEvent,i;
    CString m_ReceiveData;
nEvent=m_MSComm.GetCommEvent();
switch(nEvent)
{
case 1:
AfxMessageBox("1触发");
break;
case 2:
m_MSComm.SetInputLen(0);
        AfxMessageBox("2触发");
        k=m_MSComm.GetInBufferCount();
if(k>0)
{
vResponse=m_MSComm.GetInput();
str=(char*)(unsigned char*)vResponse.parray->pvData;
}
i=0;
str1=str;
while(i<k)
{
i++;
str1++;
}
*str1='\r';
//m_MSComm.SetInputLen(0);
m_ReceiveData+=(const char*)str;

//m_ReceiveData=(const char*)str;
AfxMessageBox(m_ReceiveData);
m_ReceiveData=" ";
m_MSComm.SetInBufferCount(0);
//清除字符串中不必要的字符
break;
case 3:
AfxMessageBox("3触发");
break;
case 4:
AfxMessageBox("4触发");
break;
case 5:
AfxMessageBox("5触发");
break;
case 6:
AfxMessageBox("6触发");
break;
default:
AfxMessageBox("其它触发");
//break;
}

}

解决方案 »

  1.   

    case 2: 
      m_MSComm.SetInputLen(0); 一进去就清空了,还怎么读取case 2: 
    vResponse=m_MSComm.GetInput(); 
    int k = vResponse.parray->cbElements;
    str=(char*)(unsigned char*)vResponse.parray->pvData;
      

  2.   

    谢谢你的答复。可我对SetInputLen(0)的作用与你想法不同,书上说是全部读取的意思。现在的问题不是读取,读是可以读到,问题在于不停的读,因为执行完第一遍已经清空了缓冲区,但是下次再触发时,已经没有再发命令或传输数据了,但是2号事件还是触发了,所以程序就被非正常终结了。查了下资料,好像和硬件有关系,MSCOMM控件并不能完全驾驭硬件的操作,甚至不影响,所以书上建议说要合理的安排SetInputLen(?),RThreshold(?)和getInput();
    问题还没有解决,希望的大家的支持!!
    谢谢zgl7903的支持。
      

  3.   

    触发接收事件后,先设置m_MSComm.SetRThreshold(0);//关闭事件响应
    接收完毕后,m_MSComm.SetRThreshold(1);//打开事件响应
      

  4.   

    事件中就不要 用阻塞式的调试方式了 用 TRACE OutputDebugString 等方式比较好
    不停的读? 那就说明有数据不断的进来吧,把串口线拔了看看还会不停的读?
      

  5.   

    谢谢3,5 楼的回复,这几天就让这个东西愁着呢,本来是为了简单,但这个控件好像并不好用,对于硬件来说,这个控件的控制能力小不知道是不是总出问题的原因。
    L_hsh的说法很有思想,我试了一下,好像还是不行,而且好像输入缓冲区和输出缓冲区混在了一起
    下面的处理代码中我用AfxMessageBox()输出2号事件触发后输入缓冲区中捕获的内容时,首先是所有的gsminit()中的命令加上MODEM回复的OK混在了一起。然后后面2号事件又被多次触发,但用对话框捕获的是无法显示的内容,有15个左右,不知道原因在哪里?
    我的程序是基于SDI的,帮忙再分析下吧,我看了好久,好像RTHreshold和Setinputlen等几个属性的设置十分重要,但又把握不好。
    int CCHARGESYSTEMView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
    AfxMessageBox("OnCreate首部");
    ///////////////////////////////////////////////////////////////////////////////////////   
        if (CView::OnCreate(lpCreateStruct) == -1)
    return -1;
    // TODO: Add your specialized creation code here
    ////////////////////////////////////////////////////////////////////////////////初始化串口^_^
        
    CString m;
    CCHARGESYSTEMApp* app=(CCHARGESYSTEMApp*)AfxGetApp();
        m.Format("%d,n,8,1",app->iRate);//使用全局变量初始化settings
    m_MSComm.Create(NULL,0,CRect(0,0,0,0),this,IDC_MSCOMM1);//创建控件
    //如果串口是打开的,则行关闭串口
    if(m_MSComm.GetPortOpen()){m_MSComm.SetPortOpen(FALSE);}
    //m_hComDev=m_MSComm.GetCommID();
    m_MSComm.SetCommPort(app->iPort);//根据全局变量赋值
    m_MSComm.SetInBufferSize(1024);//输入缓冲区的大小
    m_MSComm.SetOutBufferSize(1024);//输出缓冲区的大小
    m_MSComm.SetInBufferCount(0);//清空输入缓冲区
    m_MSComm.SetOutBufferCount(0);//清空输出缓冲区

    m_MSComm.SetInputMode(1);//以二进制方式读写数据
        m_MSComm.SetRThreshold(2);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件,这里有待商讨
        m_MSComm.SetSThreshold(0);//发送缓冲区不触发OnComm();
    m_MSComm.SetSettings(m);//使用全局变量的字符串赋值
    m_MSComm.SetHandshaking(2);//不使用握手,将带来很多问题,这里使用RTS/CTS握手
    if(!m_MSComm.GetPortOpen())m_MSComm.SetPortOpen(TRUE);//串口如果未打开,则打开
    else
    {
    AfxMessageBox("Open Serial Port Failure!");//打开失败时,报告!!!!
        return -1;
    }
    m_MSComm.SetInputLen(0);//设置当前接收区数据长度位0,表示全部读取
        m_MSComm.GetInput();//先预读缓冲区以清除残留数据
    ///////////////////////////////////////////////////////////////////////////////////////////
    // 下面是初始化的命令
         GsmInit();
         return 0;
    }
    void CCHARGESYSTEMView::GsmInit()
    {
    CString a;
    ::Sleep(100);
    a="AT\r";//test
    SendString(a);
    ::Sleep(100);
    a="ATE1\r";//no echo
    SendString(a);
    ::Sleep(100);
        a="AT+CMGF=0\r";//pdu
    SendString(a);
    ::Sleep(100);
        a="AT+CNMI=1,1,0,0,1\r";//the indictor
    SendString(a);
    ::Sleep(100);
    init();
    }
    void CCHARGESYSTEMView::SendString(CString m_strSend)
    {
    char TxData[100];
    int Count=m_strSend.GetLength(); for(int i=0;i<Count;i++)
    TxData[i]=m_strSend.GetAt(i);//首先由CString转为char*
    CByteArray array;
    array.RemoveAll();
    array.SetSize(Count); for(i=0;i<Count;i++)
    array.SetAt(i,TxData[i]);//由 char* 转为Bytearray
    m_MSComm.SetOutput(COleVariant(array));//发送
    }
    void CCHARGESYSTEMView::init()
    {
    ::Sleep(100);
    char TxData[15]={'A','T','+','C','S','C','S','=','"','G','S','M','"','\r'};
    CByteArray arr;
        arr.RemoveAll();
        arr.SetSize(15);
        for(int i=0;i<15;i++)
        arr.SetAt(i,TxData[i]);
        m_MSComm.SetOutput(COleVariant(arr));
    }
    void CCHARGESYSTEMView::OnComm()
    {
    int nEvent=m_MSComm.GetCommEvent();
    switch(nEvent)
    {
    case 1:
    AfxMessageBox("1触发");
    break;
    case 2:
    {

    //这一步设定读取方式:一次全部读取
    int a=m_MSComm.GetInBufferCount();
    if(a>0)
    {
    m_MSComm.SetInputLen(a);
    AfxMessageBox("2触发");
    SM_PARAM *pdu=NULL;
                VARIANT variant_inp;
        BYTE rxdata[2048];
    char data[2048];

        LONG len,k;
            COleSafeArray safearray_inp;
        variant_inp=m_MSComm.GetInput();/////////////////使用它把输入缓冲区中的数取出来
    m_MSComm.SetRThreshold(0);//先关闭响应
    m_MSComm.SetInBufferCount(0);
        safearray_inp=variant_inp;
        len=safearray_inp.GetOneDimSize();//AfxMessageBox("下面转换为BYTE");
    CString recd;
    CString strtemp;
    for(k=0;k<len;k++)
    { safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
        //BYTE bt=*(char*)(rxdata+k); //字符型
                    strtemp.Format("%c",*(rxdata+k)); //将字符送入临时变量strtemp存放
                    recd+=strtemp;

                AfxMessageBox(recd);
                gsmBytes2String(rxdata,data,len);//第三个参数的确定,还是很有考虑的意义的



    if(strstr(data,"4F4B")!=NULL)
    {
    AfxMessageBox("ok");
    break;
    }
    if(strstr(data,"Error")!=NULL)
    {
    for(int j=0;j<3;j++)
    GsmInit();
    if(j==3)
    {
    AfxMessageBox("Error!");
    break;
    }
    }
    if(strstr(data,"+CNMI:")!=NULL)
    {
    int newone=data[6];//取编号
                    CString a;
    a.Format("AT+CMGR=%d",newone);
    SendString(a);
    }
        if(strstr(data,"+0891")!=NULL)
    {
        int length;
        length=gsmDecodePdu(data,pdu);
        //判断充值合法性
    pdu->TP_UD;
    //CString a="AT+CMGS=";
    //SengString(a);
    }
    if(strstr(data,">")!=NULL)
    {
    CString a;
    a="AT+CMGS";
    }
    }
      m_MSComm.SetInputLen(0);
                  m_MSComm.SetRThreshold(2);//恢复响应
         break;
    }
    case 3:
    AfxMessageBox("3触发");
    break;
    case 4:
    AfxMessageBox("4触发");
    break;
    case 5:
    AfxMessageBox("5触发");
    break;
    case 6:
    AfxMessageBox("6触发");
    break;
    default:
    AfxMessageBox("其它触发");
    //break;
    }

    }
    高手帮忙啊
      

  6.   

    m_MSComm.SetRThreshold(0);//先关闭响应放在进入case 2:后,接收前应判断一下接收缓冲区字节数目,由于计算机不同、通信波特率不同,引发接收事件后,接收缓冲区的字节数是不同的。只要你清楚通信协议,设置得当,通信控件很好用。