最近要写一个关于GSM模块的发送短信的程序,在网上找了半天的代码和资料都不太懂。有些需要什么dll文件的呀,有些需要专门数据结构的呀。 其中众所周知MSComm控件是操作串口的很好工具。 经过不少挫折,最终还是自己写了个非常简单的程序,代码很简单,非常容易理解,只有300行左右哦。下面我就仔细讲解一下。
详细的工程可以在这里下载http://download.youkuaiyun.com/detail/jin123wang/3659302
第一:程序的界面
第二:各个按钮对应的函数
首先需要打开串口并初始化,对应的按钮时“打开串口”
/***************************************************/ /**********打开串口****************************/ void CGSMDlg::OnOpenCom() { UpdateData(TRUE);//刷新变量值 if(m_scomm.GetPortOpen()) m_scomm.SetPortOpen(FALSE);//关闭串口 m_scomm.SetCommPort(m_com);//选择端口 m_scomm.SetInputMode(1);//设置方式为二进制 m_scomm.SetInBufferSize(1024); m_scomm.SetOutBufferSize(1024); m_botelv+=",n,8,1"; m_scomm.SetSettings(m_botelv); m_scomm.SetPortOpen(TRUE);//打开串口 // m_scomm.SetRThreshold(1); m_scomm.SetSThreshold(1); m_scomm.SetInputLen(0); m_scomm.GetInput(); cmd="AT"; m_scomm.SetOutput(COleVariant(cmd+"\r")); Sleep(1000); write_port(); if(receivestr.Find("OK")>=0) MessageBox("OK"); else MessageBox("模块没有相应"); //设置短消息的格式是TEXT cmd="AT+CMGF=1"; m_scomm.SetOutput(COleVariant(cmd+"\r")); Sleep(1000); write_port();//读串口 } 其中有个函数是write_port(),就是从串口的接受缓冲区读取数据,为什么不用对应的事件响应函数呢?因为那样不能及时得到GSM返回的信息。其中sleep(1000)这个函数不能少,因为读取之前,GSM发送数据到串口需要一段时间。这个函数源代码是: /**********读串口函数**************/ LONG len=0,k=0; BYTE rxdate[1024]; CString strtemp; BYTE bt; void CGSMDlg::write_port() { VARIANT variant_inp; COleSafeArray safe_np; receivestr=""; strtemp=""; for(int i=0;i<1024;i++) rxdate[i]=0; variant_inp=m_scomm.GetInput();//读取缓冲区 safe_np=variant_inp;//类型转换 len=safe_np.GetOneDimSize();//得到数据有效长度 for(k=0;k<len;k++) safe_np.GetElement(&k,rxdate+k);//转换啊成BYTE型数组 for(k=0;k<len;k++) { bt=*(char *)(rxdate+k); strtemp.Format("%c",bt); receivestr+=strtemp; } //把结果写入到相应的显示区域中 m_from_com.SetSel(-1,-1); m_from_com.ReplaceSel(receivestr); m_from_com.SetSel(-1,-1); m_from_com.ReplaceSel("\n"); } /*****************************************/
其次的功能有发送短信,对应的按钮时“发送”
/**************发送短信内容**************/ void CGSMDlg::Onsend() { UpdateData(TRUE);//更新变量 if(m_centerphone.GetLength()!=11||m_phone.GetLength()!=11) { MessageBox("号码应该是11位数"); return ; } CString temp; temp="+86"; cmd="AT+CSCA="; m_centerphone=temp+m_centerphone; m_phone=temp+m_phone; //修正电话号码 m_scomm.SetOutput(COleVariant(cmd+m_centerphone+"\r")); Sleep(1000); write_port(); //设置短信中心电话号码 m_sendM.GetWindowText(temp); cmd="AT+CMGS="; m_scomm.SetOutput(COleVariant(cmd+m_phone+"\r")); Sleep(1000); write_port(); if(receivestr.Find("<",0)>=0||receivestr.Find(">",0)>=0) MessageBox("发送成功"); else MessageBox("发送失败"); m_scomm.SetOutput(COleVariant(temp+"\x1A"));//发送短消息内容 Sleep(1000); write_port(); }
其次需要读短信,“读取”是指根据具体的索引位置进行读取指定的短信,“全部读取”是读取全部的消息
“读取”按钮的函数是
/*******************读取短消息************************/ void CGSMDlg::OnRead() { UpdateData(TRUE); if(m_position==""||m_position=="0") { MessageBox("您要读取的短信位置为空或0,请重新输入"); return; } else { recv=""; cmd="AT+CMGR="; m_scomm.SetOutput(COleVariant(cmd+m_position+"\r"));//发送命令 write_port(); m_recvM.SetSel(-1,-1); m_recvM.ReplaceSel(receivestr); m_recvM.SetSel(-1,-1); m_recvM.ReplaceSel("\n"); } } /*****************************************************/
“全部读取”按钮的函数是
/**************读取全部短信********************/ void CGSMDlg::OnReadAll() { cmd="AT+CMGL=ALL"; m_scomm.SetOutput(COleVariant(cmd+"\r")); Sleep(1000); write_port(); m_recvM.SetSel(-1,-1); m_recvM.ReplaceSel(receivestr); m_recvM.SetSel(-1,-1); m_recvM.ReplaceSel("\n"); } /*******************************/
“删除”消息的按钮函数是
/***********删除选定的消息*****************/ void CGSMDlg::OnDeleteMessage() { UpdateData(TRUE); cmd="AT+CMGD="; m_scomm.SetOutput(COleVariant(cmd+m_pos+"\r")); Sleep(1000); write_port(); } /*****************************************/
最后“清空”按钮应该是很简单的,将对应的字符串设置为空就好了。整个程序应该还是比较简洁的,但缺点是通过TEXT格式发送发送的,而不是PDU,所以不能发送中文,但是大概的框架就是这样,不清楚的可以根据这个程序改进一下的。