最近要寫一個關於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,所以不能發送中文,但是大概的框架就是這樣,不清楚的可以根據這個程序改進一下的。