当前位置:首页 >> 信息与通信 >>

单片机通过短信猫发送短信的方法


单片机通过短信猫收发短信的方法
短信在现今的生活中起着非常重要的作用, 我们每天都会使用它来进行信息的接收与 发 送,为我们的沟通提供新的手段。从本质上说,其实是一种数据传输的机制,通过GSM(全 球移动通信系统)作为其传输的道路,从而实现了数据的远距离传输。如果我们把它运用于 单片机上,就可以实现单片机上的数据远距离传输,这在实际的应用中是十分有用的。如数 据的远程采

集与传输、环境的监测与报警等。 然而要实现单片机发送短信,就要依赖于专用的硬件――短信猫(GSM Modem),它 , 用来负责与 GSM 网络进行通信,而单片机则负责短信的编解码。下面介绍短信的编码, 其 实这些编码我们每天都在使用,只是它藏匿于手机或终端设备中,不被我们熟知。 (1) 短信编码 以一个发送实例来进行讲解: 笔者位于哈尔滨市,其短信中心号码为 13800451500,短信接收方号码采用 我本人的号码 15846003114,短信内容(最多为 140 个字节,如果是中文则最多 为 70 个字)为“大家好!!。 !” 先列出最终的编码,然后再来慢慢分析: 0891683108401505F011000B815148063011F40008A70C59275BB6597DFF01 FF01FF01 将以上编码通过串口写入短信猫,再辅以相应的 AT 指令与附加信息就可以 成功发送短信。 1.08:短信中心地址长度(可以固定不变) 2.91:短信中心号码类型(可以固定不变) 3.68:中国地区代码(在中国范围内固定不变) 4.3108401505F0:短信服务中心号码 13800451500 (根据地域的不同进行变动,实际情况下,可以固定不变,不论在中国任 何地域都通过哈尔滨短信中心,但使用当地的服务中心收发会更快。 ) 可以看到,短信服务中心号码采用了一种比较特殊的表示方法。其实也很 简单就是在短信服务中心号码后加一个 F,号码长度就变成了 12 位,然后 对它每两位中的字符进行对调。在后面的接收方号码也是采用此种方法进 行表示的,对这一点的理解的至关重要的,它将直接关系到短信发送的正

确与否。 5.1100:发送短信的编码方式(可以固定不变) 6.0B:目的地址长度(可以固定不变) 7.81:目的地址类型(可以固定不变) 8. 5148063011F4:目的地址,即接收方号码 15846003114 如前面所说,接收方号码亦采用此种方法。 9.0008:发送中文字符方式 10.A7: (可以固定不变) 11.0C:短信内容长度 12. 59275BB6597DFF01FF01FF01:发送中文字符的 UNICODE 码 (根据发送信息内容进行变动) 中文的发送采用 UNICODE 编码。 由于手机上对编程的解码也是采用 UNICODE 的,因此只有只用 UNICODE 编码才能使短信内容成功显示在 手机上。其次,在向手机发送短信时,短信内容需要使用内存方式的显示 表示,如“01FF”为一个字符的 UNICODE 码,在编码中它为 4 个 ASCII 码,而它表示是 0x01ff,为两个字节,这一点至关重要,不采用这种表示 方法或表示有错,则会导致在接收方手机上无显示或显示不正常。 此编码段是单片机进行数据传输的核心部分, 它是真正的数据。 在日 常的中文短信编码中均采用 UNICODE, 但其本身并不局限于 UNICODE, 如果接收终端是支持 GB2312 的,而不支持 UNICODE,那么就可以在这 里放相应的 GB 码。脱离开字符编码,其实可以放入任何数据,只是要在 上一个编码段中设置相应的数据长度即可。 在笔者的短信收发系统中, 采用西门子的 TC35i 作为短信猫, 由于使 用了一种支持 GB2312 硬件字库的液晶显示器, 因此在数据编码中直接使 用 GB 码,成功实现短信发送与接收,并在显示器上对解码后的内容进行 显示,达到了较好的效果。 14. 发送结束标志(十六进制为 0x1A) : ,表示短信码结束。 结束标志在实际的操作中很容易遗忘,请读者加以注意。

(2)

UNICODE 与 GB2312 码

(3)

与短信收发相关的 AT 指令 短信编码还要辅以相应的 AT 指令,才能实现短信的发送。AT 指令如下: AT:用以与 Modem 的握手,返回 OK 则说明握手成功。 AT+CMGR=X:用以读取第 X 条短信。 AT+CMGD=X:用以删除第 X 条短信。 AT+CMGS=X:设置发送短信的字节数为 X。 实际的 AT 指令集功能非常丰富,在应用中也是非常重要,尤其在手机开发中更 如此。在这里只是实现简单的短信收发,只涉及到以上几条 AT 指令。读者如果 想进行深入的了解,可以翻阅相应的手册。

(4) 短信的发送过程(以下过程中>代表发送,<代表接收) 1. 通讯握手 >AT(回车 十六进制的 0x0d 0x0a) <OK 收到 OK,说明握手成功。 2. 设置短信字节数 >AT+CMGS=26(回车) 设置短信字节数,由笔者的使用经验,后面的数值为短信内容的字节数+14。 如上面的编码中内容为 12 个字节,则后面的数值为 12+14=26 3. 发送短信编码 <> 收到>符号,说明猫正在等待接收短信编码 >0891683108401505F011000B815148063011F40008A70C59275BB6597DFF01FF 01FF01 发送短信编码,送送完毕后,如果短信猫已经接收,则启动短信发送。 4.短信发送结果检测 <+CMGS:45 <OK 在短信发送成功后,会返回“+CMGS” ,后面的 45,是表示第 45 条短信。如果

没有返回此字符串则说明发送失败。 以上过程可以通过串口调试工具手工进行, 而这里需要实现的是单片机的自动发 送。握手、设置短信字节数、发送短信编码、发送结果检测等都需要单片机来实现。 (5)单片机实现短信自动发送 进行短信发送的前提是短信内容的正确编码。经过以上对短信发送过程的分 析,可以通过单片机对其进行实现。下面是实现程序例程: /*

函数名:PDU_SMS() 功能 :发送短信 参数说明:SMS_Center 为短信中心号码 11 位
SMS_Telenum 为短信接收方的号码 11 位 SMS_Context 为短信的内容 */ 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=0i<300i++) PDU_Code[i]=PDU_t[i] /*设置短信中心号码*/ 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] /**/

/*设置接收号码*/ 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] /**/ /*设置短信内容长度*/ 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 /**/

/*编码短信内容*/ if(is_GB==0)//如果不是 GB 码,短信内容为 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 //短信内容为 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=0i<25i++)

delay(20000) sbuf[counter]=0 //LCD_PutNum16(5,96,time) counter=0 time++ } //判断是否发送成功,如果不成功继续发送,最多 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 } } 以上程序成功实现短信的发送,其中的一些函数限于篇幅可自行实现。 (6)单片机对短信的读取与解码 单片机可以通过 AT 指令对短信猫中的短信进行读取,并对读入的短信数据进 行分析与解码。 读出的短信格式与发送时的短信编码大致是相同的。下面给出相应的程序例 程,读者可以在自行实验中对照验证。

1. 读取某一条短信,并将其进行显示 /*

函数名:LAD_SMS()(short for "Load And Display the Short MessageS") 功能:用户函数,读取第 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 转为相应的字符串,如 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=0i<10i++) delay(10000) //等待读取完毕 sbuf[counter]=0 temp[0]=sbuf[23] temp[1]=sbuf[24] temp[2]=sbuf[25] temp[3]=0 if(sbuf[25]!=0x0d) t++ for(i=0i<strlen(temp)i++) if(temp[i]==0x0d) temp[i]=0 //在收到的数据末尾附加'\0'

len=atoi(temp) //获取收到的短信内容长度 //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=0i<leni++) { temp[0]=sbuf[t+2*i] temp[1]=sbuf[t+2*i+1] temp[2]=0 sbuf[i]=_hex_(temp) //收到的短信内容是内存方式的显示表示,转为十六进制数 }

sbuf[i]=0

Analysis_Pro()//解码后的内容在 sbuf 中,此函数对其进行显示输出 //LCD_PutEng(x,y,inf_bw.Date) //LCD_PutEng(x,y,sbuf+29)

delay(50000) clear_sbuf() counter=0 return 1 } 2. 检测新短信 /*

函数名:Check_New() 功能:用户函数,检测有无新的短信,如果有返回 1,否则返回 0 作者:于振南
*/ unsigned char Check_New() {int i send_s("AT+CMGL=0") //AT+CMGL=0 为读取新短信的 AT 指令 send(0x0d) send(0x0a) //发送回车 delay(10000) //等待接收完毕

if(sbuf[12]=='O') return 0xff if(sbuf[12]=='+') { for(i=18i<23i++) if(sbuf[i]==',') sbuf[i]=0 return atoi(sbuf+19) } } //返回新短信的位置

3. 删除某条短信 /*

函数名:Delete() 功能:用户函数,删除第 n 条短信 作者:于振南
*/ unsigned char Delete(unsigned char n) { char t[10] char t1[5] strcpy(t,"AT+CMGD=") 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 } //AT+CMGD 为删除短信的 AT 指令


相关文章:
单片机控制sim900a收发短信
单片机控制sim900a收发短信_电子/电路_工程科技_专业资料。单片机接受指定短信内容...("AT+CMGF=1\r"); //设置 sim900 模块为英文方式发送短信 delay(500); ...
51单片机控制GSM模块发送短信
51单片机控制GSM模块发送短信_信息与通信_工程科技_专业资料。以下几个函数是51单片机最近调试GSM模块发短信,打电话,挂电话的程序,可行!!(晶振一定要使用正确,不...
基于单片机的短信收发系统设计_图文
第三种在电脑或单片机通过 GSM 模块向手机发送 短信, 对硬件需求较大, 比较适合小项目的开发, 但能实现自动收发短信[12,13,14]。 第二种方法短信收发通常又分...
基于单片机给手机接打电话发短信
基于单片机给手机接打电话发短信_电子/电路_工程科技_专业资料。单片机 12864LCD屏 信盈达 华北水利水电大学专业综合课程设计 学院:机械学院 专业:测控技术与仪器 学...
此程序是本人通过51单片机控制sim900发送英文短信
此程序是本人通过51单片机控制sim900发送英文短信_电子/电路_工程科技_专业资料。...///UART 方式 1:8 位 UART; REN=1:允许接收 PCON = 0x00; TF1 = 1;...
GSM的单片机短消息收发系统设计
本文利用单片机与西门子的 TC35i 组成一 个短信收发系统,对如何实现远程监控进行了论述。数据的传输方式最主要 是短消息方式,短消息的发送和接收是通过 AT 指令来...
51单片机短信控制GSM
51单片机短信控制GSM_信息与通信_工程科技_专业资料。...(0x1A); //发送短信 sendchar(0x0D); sendchar...//时器 1 为方式 2 初值自动装入 产生波特率 TH1...
C#短信猫操作源码开发经验_图文
4、短信猫工作稳定与否,收发短信成功率高不高,不仅取决于使用的是否 是正品模块,还取决于短信猫外围电路的设计是否精良,如采用单片机控制,有 看门狗电 路,外壳设计...
PDU模式的短信息编解码方法及单片机实现
PDU模式的短信息编解码方法单片机实现_信息与通信_工程科技_专业资料。PDU 模式...PDU 模式收发短信包括 3 种编码:7-bit、8-bit 和 UCS2 编码。7-bit 编码...
单片机短信收发资料
单片机短信收发资料_信息与通信_工程科技_专业资料。单片机短信收发资料手机SMS PDU 格式参考手册 开发者指南 SMS with the SMS PDU-mode 翻译整理: 犬犬(心帆) ...
更多相关标签: