最近要写一个关于GSM模块的发送短信的程序,在网上找了半天的代码和资料都不太懂。有些需要什么dll文件的呀,有些需要专门数据结构的呀。 其中众所周知MSComm控件是操作串口的很好工具。 经过不少挫折,最终还是自己写了个非常简单的程序,代码很简单,非常容易理解,只有300行左右哦。下面我就仔细讲解一下。
详细的工程可以在这里下载http://download.csdn.net/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,所以不能发送中文,但是大概的框架就是这样,不清楚的可以根据这个程序改进一下的。