天堂草原最受欢迎的角色,天堂动漫,天堂在线,色天堂下载,天堂中文在线资源,亚洲男人天堂

技術(shù)熱線: 4007-888-234

專注差異化嵌入式產(chǎn)品解決方案 給智能產(chǎn)品定制注入靈魂給予生命

提供開發(fā)工具、應(yīng)用測試 完善的開發(fā)代碼案例庫分享

從全面的產(chǎn)品導(dǎo)入到強大技術(shù)支援服務(wù) 全程貼心伴隨服務(wù),創(chuàng)造無限潛能!

技術(shù)支持

單片機通過短信貓收發(fā)短信的方法

更新時間: 2019-03-26

單片機通過短信貓收發(fā)短信的方法

       短信在現(xiàn)今的生活中起著非常重要的作用,我們每天都會使用它來進行信息的接收與發(fā)送,為我們的溝通提供新的手段。從本質(zhì)上說,其實是一種數(shù)據(jù)傳輸?shù)臋C制,通過GSM(全球移動通信系統(tǒng))作為其傳輸?shù)牡缆罚瑥亩鴮崿F(xiàn)了數(shù)據(jù)的遠距離傳輸。如果我們把它運用于單片機上,就可以實現(xiàn)單片機上的數(shù)據(jù)遠距離傳輸,這在實際的應(yīng)用中是十分有用的。如數(shù)據(jù)的遠程采集與傳輸、環(huán)境的監(jiān)測與報警等。
       然而要實現(xiàn)單片機發(fā)送短信,就要依賴于專用的硬件――短信貓(GSM Modem),,它用來負責(zé)與GSM網(wǎng)絡(luò)進行通信,而單片機則負責(zé)短信的編解碼。下面介紹短信的編碼,其實這些編碼我們每天都在使用,只是它藏匿于手機或終端設(shè)備中,不被我們熟知。

短信編碼

以一個發(fā)送實例來進行講解:
       筆者位于哈爾濱市,其短信中心號碼為13800451500,短信接收方號碼采用我本人的號碼15846003114,短信內(nèi)容(最多為140個字節(jié),如果是中文則最多為70個字)為“大家好?。?!”。
先列出最終的編碼,然后再來慢慢分析:
0891683108401505F011000B815148063011F40008A70C59275BB6597DFF01FF01FF01
將以上編碼通過串口寫入短信貓,再輔以相應(yīng)的AT指令與附加信息就可以成功發(fā)送短信。
1.08:短信中心地址長度(可以固定不變)
2.91:短信中心號碼類型(可以固定不變)
3.68:中國地區(qū)代碼(在中國范圍內(nèi)固定不變)
4.3108401505F0:短信服務(wù)中心號碼 13800451500
 (根據(jù)地域的不同進行變動,實際情況下,可以固定不變,不論在中國任何地域都通過哈爾濱短信中心,但使用當(dāng)?shù)氐姆?wù)中心收發(fā)會更快。)
       可以看到,短信服務(wù)中心號碼采用了一種比較特殊的表示方法。其實也很簡單就是在短信服務(wù)中心號碼后加一個F,號碼長度就變成了12位,然后對它每兩位中的字符進行對調(diào)。在后面的接收方號碼也是采用此種方法進行表示的,對這一點的理解的至關(guān)重要的,它將直接關(guān)系到短信發(fā)送的正確與否。
5.1100:發(fā)送短信的編碼方式(可以固定不變)
6.0B:目的地址長度(可以固定不變)
7.81:目的地址類型(可以固定不變)
8. 5148063011F4:目的地址,即接收方號碼 15846003114
如前面所說,接收方號碼亦采用此種方法。
9.0008:發(fā)送中文字符方式
10.A7:(可以固定不變)
11.0C:短信內(nèi)容長度

12. 59275BB6597DFF01FF01FF01:發(fā)送中文字符的UNICODE碼
(根據(jù)發(fā)送信息內(nèi)容進行變動)
中文的發(fā)送采用UNICODE編碼。由于手機上對編程的解碼也是采用UNICODE的,因此只有只用UNICODE編碼才能使短信內(nèi)容成功顯示在手機上。其次,在向手機發(fā)送短信時,短信內(nèi)容需要使用內(nèi)存方式的顯示表示,如01FF為一個字符的UNICODE碼,在編碼中它為4個ASCII碼,而它表示是0x01ff,為兩個字節(jié),這一點至關(guān)重要,不采用這種表示方法或表示有錯,則會導(dǎo)致在接收方手機上無顯示或顯示不正常。
      此編碼段是單片機進行數(shù)據(jù)傳輸?shù)暮诵牟糠?,它是真正的?shù)據(jù)。在日常的中文短信編碼中均采用UNICODE,但其本身并不局限于UNICODE,如果接收終端是支持GB2312的,而不支持UNICODE,那么就可以在這里放相應(yīng)的GB碼。脫離開字符編碼,其實可以放入任何數(shù)據(jù),只是要在上一個編碼段中設(shè)置相應(yīng)的數(shù)據(jù)長度即可。
      在筆者的短信收發(fā)系統(tǒng)中,采用西門子的TC35i作為短信貓,由于使用了一種支持GB2312硬件字庫的液晶顯示器,因此在數(shù)據(jù)編碼中直接使用GB碼,成功實現(xiàn)短信發(fā)送與接收,并在顯示器上對解碼后的內(nèi)容進行顯示,達到了較好的效果。

14.:發(fā)送結(jié)束標(biāo)志(十六進制為0x1A),表示短信碼結(jié)束。
結(jié)束標(biāo)志在實際的操作中很容易遺忘,請讀者加以注意。

 UNICODE與GB2312碼

 與短信收發(fā)相關(guān)的AT指令

短信編碼還要輔以相應(yīng)的AT指令,才能實現(xiàn)短信的發(fā)送。AT指令如下:
AT:用以與Modem的握手,返回OK則說明握手成功。
AT+CMGR=X:用以讀取第X條短信。

AT+CMGD=X:用以刪除第X條短信。
AT+CMGS=X:設(shè)置發(fā)送短信的字節(jié)數(shù)為X。
實際的AT指令集功能非常豐富,在應(yīng)用中也是非常重要,尤其在手機開發(fā)中更如此。在這里只是實現(xiàn)簡單的短信收發(fā),只涉及到以上幾條AT指令。讀者如果想進行深入的了解,可以翻閱相應(yīng)的手冊。

短信的發(fā)送過程(以下過程中>代表發(fā)送,<代表接收)

通訊握手

>AT(回車 十六進制的0x0d 0x0a)
         <ok< />
           收到OK,說明握手成功。
       2.  設(shè)置短信字節(jié)數(shù)
          >AT+CMGS=26(回車)
           設(shè)置短信字節(jié)數(shù),由筆者的使用經(jīng)驗,后面的數(shù)值為短信內(nèi)容的字節(jié)數(shù)+14。
           如上面的編碼中內(nèi)容為12個字節(jié),則后面的數(shù)值為12+14=26
       3.  發(fā)送短信編碼
          <>
           收到>符號,說明貓正在等待接收短信編碼
>0891683108401505F011000B815148063011F40008A70C59275BB6597DFF01FF01FF01

          發(fā)送短信編碼,送送完畢后,如果短信貓已經(jīng)接收,則啟動短信發(fā)送。
       4.短信發(fā)送結(jié)果檢測
          <+CMGS:45
         <ok< />
          在短信發(fā)送成功后,會返回&ldquo;+CMGS&rdquo;,后面的45,是表示第45條短信。如果沒有返回此字符串則說明發(fā)送失敗。

          以上過程可以通過串口調(diào)試工具手工進行,而這里需要實現(xiàn)的是單片機的自動發(fā)送。握手、設(shè)置短信字節(jié)數(shù)、發(fā)送短信編碼、發(fā)送結(jié)果檢測等都需要單片機來實現(xiàn)。
   (5)單片機實現(xiàn)短信自動發(fā)送
            進行短信發(fā)送的前提是短信內(nèi)容的正確編碼。經(jīng)過以上對短信發(fā)送過程的分析,可以通過單片機對其進行實現(xiàn)。下面是實現(xiàn)程序例程:
/*-------------------------------------------------------------------------
 函數(shù)名:PDU_SMS()
 功能  :發(fā)送短信
 參數(shù)說明:SMS_Center為短信中心號碼 11位

           SMS_Telenum為短信接收方的號碼 11位

           SMS_Context為短信的內(nèi)容

--------------------------------------------------------------------------------*/

int PDU_SMS(char *SMS_Center, char *SMS_Telenum,

char *SMS_Context,char is_GB)

{

  int i,j;

  unsigned char len,time;

  char lens[3];

  time=0;

  for(i=0;i<300;i++) PDU_Code[i]=PDU_t[i];

  /*----------設(shè)置短信中心號碼--------------*/

  for (i = 0, j = 0; i < strlen(SMS_Center) / 2; i++)

  {

    PDU_Code[6+(j++)] = SMS_Center[2 *i + 1];

    PDU_Code[6+(j++)] = SMS_Center[2 *i];

  }

  PDU_Code[6+j++] = 'F';    //在最后補上的F

  PDU_Code[6+j] = SMS_Center[strlen(SMS_Center) - 1];

  /*---------------------------------------------*/

  /*----------設(shè)置接收號碼--------------*/

  for (i = 0, j = 0; i < strlen(SMS_Telenum) / 2; i++)

  {

    PDU_Code[26+(j++)] = SMS_Telenum[2 *i + 1];

    PDU_Code[26+(j++)] = SMS_Telenum[2 *i];

  }

  PDU_Code[26+j++] = 'F';

  PDU_Code[26+j] = SMS_Telenum[strlen(SMS_Telenum) - 1];

  /*---------------------------------------------*/

  /*----------設(shè)置短信內(nèi)容長度--------------*/

  if(is_GB==0)

  len = strlen(SMS_Context) *2;

  else

  len = strlen(SMS_Context);



  PDU_Code[44] = (len >> 4) > 9 ? (len >> 4) + 55: (len >> 4) + 48;

  PDU_Code[45] = (len &0x0f) > 9 ? (len &0x0f) + 55: (len &0x0f) + 48;

  /*---------------------------------------------*/



  /*----------編碼短信內(nèi)容--------------*/

  if(is_GB==0)//如果不是GB碼,短信內(nèi)容為ascii碼字符串

  {

  for (i = 0,j=0; i<strlen(SMS_Context);i++)

  {

     szzh16(SMS_Context[j++],lens);

     PDU_Code[46+i*4] = '0';

     PDU_Code[46+i*4+1] = '0';

     PDU_Code[46+i*4+2] = lens[0];

     PDU_Code[46+i*4+3] = lens[1];

  }

  PDU_Code[46+i*4] = 0x1a;

  PDU_Code[46+i*4+1] = 0xff;

  }

  else              

//短信內(nèi)容為GB碼,如果要使手機能夠顯示,改到UNICODE編碼

  {

  for (i = 0,j=0; i<strlen(SMS_Context);i++)

  {

     szzh16((int)SMS_Context[j++],lens);

     PDU_Code[46+i*2] = lens[0];

     PDU_Code[46+i*2+1] = lens[1];

  }

  PDU_Code[46+i*2] = 0x1a;

  PDU_Code[46+i*2+1] = 0xff;

  }

  /*---------------------------------------------*/

  if(PDU_HandShake())

  {

  do

  {

  //LCD_PutChn(5,96,"SS...");

  //if(is_GB)

  PDU_EnablePDU();

  if(is_GB==0)

  PDU_SetLength(Strlen(SMS_Context)*2);

  else

  PDU_SetLength(Strlen(SMS_Context));

  PDU_Send(PDU_Code);

  //LCD_PutEng(5,96,"SS");

  for(i=0;i<25;i++)

  delay(20000);  

  sbuf[counter]=0;

  //LCD_PutNum16(5,96,time);

  counter=0;

  time++;

  }

 //判斷是否發(fā)送成功,如果不成功繼續(xù)發(fā)送,最多4次,如仍不成功,返回0

  while(strpos(sbuf+strlen(sbuf)-20,'G')==-1&&time<4);



  if(strpos(sbuf+strlen(sbuf)-20,'G')==-1)

  return 0;

  else

  return 1;  //成功的話返回0

  }

  else

  {

  //LCD_PutEng(5,96,"LL");

  sbuf[counter]=0;

  //LCD_PutEng(0,0,sbuf);

  counter=0;

  return 0;

  }

}

       以上程序成功實現(xiàn)短信的發(fā)送,其中的一些函數(shù)限于篇幅可自行實現(xiàn)。
   (6)單片機對短信的讀取與解碼
            單片機可以通過AT指令對短信貓中的短信進行讀取,并對讀入的短信數(shù)據(jù)進行分析與解碼。
            讀出的短信格式與發(fā)送時的短信編碼大致是相同的。下面給出相應(yīng)的程序例程,讀者可以在自行實驗中對照驗證。

讀取某一條短信,并將其進行顯示

/*-------------------------------------------------------

函數(shù)名:LAD_SMS()(short for "Load And Display the Short MessageS")

功能:用戶函數(shù),讀取第n條短信,并在LCD的(x,y)位置顯示出來

作者:于振南

----------------------------------------------------------*/

unsigned char LAD_SMS(unsigned char n,unsigned char x,unsigned char y)

{

 unsigned char i,len,t;

 char temp[5];

 char temp1[3];

 //IN_Draw_BlankorBlackRect(0,20,30,72,0);

 szzh10(n,temp1);  

//將n轉(zhuǎn)為相應(yīng)的字符串,如n=21,則字符串為"21",用以與AT指令拼接。

 t=85;

 clear_sbuf();

 counter=0;

 send_s("AT+CMGR=");//AT+CMGR為讀取短信的AT指令

 send_s(temp1);//上面所得的字符串

 send(0x0d);

 send(0x0a);

 for(i=0;i<10;i++) delay(10000);  //等待讀取完畢

 sbuf[counter]=0;   //在收到的數(shù)據(jù)末尾附加'\0'

 temp[0]=sbuf[23];

<, SPAN style="mso-spacerun: yes"> temp[1]=sbuf[24];

 temp[2]=sbuf[25];

 temp[3]=0;

 if(sbuf[25]!=0x0d) t++;

 for(i=0;i<strlen(temp);i++) if(temp[i]==0x0d) temp[i]=0;

 len=atoi(temp);  //獲取收到的短信內(nèi)容長度

   //LCD_PutEng(23,76,"(SM:");

   //LCD_PutNum16(27,76,n);

   //LCD_PutEng(29,76,")");

 if(len==0)

 {

  //LCD_PutEng(5,96,"EMP");

  //LCD_PutChn(x,y,">短信空");

  delay(50000);

  return 0;

 }

 len-=20;

 if(len>90)

 {

  //LCD_PutEng(5,96,"MTL");

  //LCD_PutChn(x,y,">短信太長");

  delay(50000);

  return 0;

 }



 for(i=0;i<len;i++)

 {

  temp[0]=sbuf[t+2*i];

  temp[1]=sbuf[t+2*i+1];

  temp[2]=0;

  sbuf[i]=_hex_(temp);   

  //收到的短信內(nèi)容是內(nèi)存方式的顯示表示,轉(zhuǎn)為十六進制數(shù)

 }

 sbuf[i]=0;

 Analysis_Pro();//解碼后的內(nèi)容在sbuf中,此函數(shù)對其進行顯示輸出

 //LCD_PutEng(x,y,inf_bw.Date);

 //LCD_PutEng(x,y,sbuf+29);

 delay(50000);

 clear_sbuf();

 counter=0;

 return 1;

}


檢測新短信

/*-------------------------------------------------------

函數(shù)名:Check_New()

功能:用戶函數(shù),檢測有無新的短信,如果有返回1,否則返回0

作者:于振南

----------------------------------------------------------*/

unsigned char Check_New()

{int i;

 send_s("AT+CMGL=0"); //AT+CMGL=0為讀取新短信的AT指令

 send(0x0d);

 send(0x0a);  //發(fā)送回車

 delay(10000);   //等待接收完畢

 if(sbuf[12]=='O') return 0xff;

 if(sbuf[12]=='+')

 {

  for(i=18;i<23;i++)

  if(sbuf[i]==',') sbuf[i]=0;

  return atoi(sbuf+19);    //返回新短信的位置

 }

}


刪除某條短信

/*-------------------------------------------------------

函數(shù)名:Delete()

功能:用戶函數(shù),刪除第n條短信

作者:于振南

----------------------------------------------------------*/

unsigned char Delete(unsigned char n)

{

 char t[10];

 char t1[5];

 strcpy(t,"AT+CMGD=");  //AT+CMGD為刪除短信的AT指令

 szzh10(n,t1);

 strcpy(t+8,t1);

 while(Send_AT_CMD(t)!=1);

 //LCD_PutEng(5,96,"SM");

 //LCD_PutNum16(7,96,n);

 //LCD_PutEng(10,96,"De");

 delay(60000);

 return 1;

}



404
返回首頁 |  返回上一頁
联系我们: 屏南县| 双流县| 昭苏县| 渝北区| 科技| 宜川县| 郑州市| 个旧市| 北海市| 望都县| 松溪县| 乌拉特中旗| 利辛县| 陆川县| 罗田县| 宜丰县| 大关县| 右玉县| 扬州市| 鄄城县| 长汀县| 上高县| 济宁市| 南涧| 荥阳市| 平凉市| 察哈| 高陵县| 志丹县| 景谷| 道孚县| 天津市| 宜君县| 建阳市| 湟源县| 贺兰县| 定州市| 随州市| 旺苍县| 清丰县| 襄汾县|