单片机控制GSM模块实现短信收发的软件设计
- 格式:pdf
- 大小:136.69 KB
- 文档页数:4
基于GSM智能家居控制系统的设计物理与电子信息工程系电子信息工程专业张彪指导老师张华林摘要论文中介绍了一种智能家居控制的新方法,详细的论述了系统的组成及实现原理。
以STC12C5A60S2单片机作为主控制芯片,使用GSM模块TC35i发送短信息和接收短信息,实现了手机终端和智能家居控制系统远距离全双工通信。
使用红外热式传感、MQ2煤气传感器、MQ5烟雾传感器采集家中的安全信息并将险情发送至用户的手机上。
系统可以用手机短信定时控制家电,也可以利用VB上位机通过CC1100无线传输模块定时控制家电。
关键词:智能家居;单片机;远程控制;GSM1 引言随着通信技术、嵌入式技术、网络技术的迅猛发展,生活节奏不断加快使人们对智能化的家庭居住环境提出了更高的要求。
目前市场上各种智能化家居控制系统的产品层出不穷,其中大部分产品是以电话线作为载体的,对电话线的依赖较高。
但目前现状是电话家庭用户的数量正逐步减少,且电话线路容易遭到破坏,同时受到地区限制,故这种智能化家居产品中有存在一定的局限性和安全隐患。
但随着GSM 移动网络通信的普及和移动通信应用领域不断扩大以及手机用户的日益增多,为利用GSM 网络研制智能化家居系统提供了一种新的途径。
2 系统的设计要求2.1 系统的设计要求系统设计要求主要有:(1)能够用PC机和远程终端定时和立即控制多路家电的电源开关;(2)具备监控家庭中的安全信息并能把险情随时通知用户。
2.2 设计的基本思路设计一个实用智能化家居控制系统,按照系统设计的基本要求,可分为5个主要模块,分别是:远程控制模块、液晶显示模块、无线射频CC1100模块、实时时钟模块、六路继电器控制模块。
其中远程控制模块是使用短信息或者电话远程控制家用电器(包括定时和立即控制)。
CC1100模块是实现上下位机数据中转,因此PC机可以实现短距无线传输控制家电。
实时时钟模块为定时控制家电提供时间参考,系统实现的大部分功能需要软件控制。
20084产品设计与实现基于GSM模块TC35I的远程报警和控制装置的研制彭宇平林喜荣李建荣1121、清华大学深圳研究生院工程学部,深圳,5180552、阳江纳安科技有限公司,广东,529500【摘 要】【关键词】结合保险柜远程报警和开启的应用背景,研制了利用单片机AT89S52控制GSM模块TC35I以短消息(SMS)的方式进行报警和控制的装置。
振动信号触发单片机外部中断,在中断处理程序中控制TC35I向外发送预先存储在SIM卡中的报警短消息;用户发来的控制短信触发单片机的串行中断,单片机读取收到的短信并进行解析处理。
装置结构简单、传输可靠,稍做改进即可应用于多种需远程交互的场合。
TC35IAT89S52短消息远程报警远程控制一、引言二、系统方案设计随着短消息服务(SMS)和通用分组无线服务(GPRS)等数据业务的发展,GSM无线网络应用于机电产品和工业控制领域的趋势不断扩大,各种以GSM网为传输平台的数据采集及远程监控系统方案和产品也不断出现。
例如,在现代家庭的环境安全监测和家用电器的控制上,利用GSM网络既可实现对盗情、燃气泄漏及火警等的监测,并以短消息方式向主人发出警报;又可发送短消息对家用电器例如空调、电视、音响、微波炉等进行遥控。
GSM网络信号覆盖面积广、网络接入灵活、无需布线,打破了距离的限制,从而可以实现全国乃至全球漫游监控。
短消息(SMS)利用信令信道传输,直接把要发的信息加上目的地址发送到短消息服务中心,由服务中心再发给终端。
短消息容量有限(每条短信内容最多140个字节),适于传输小流量的数据;由于建立时间较长,传送过程要受短消息服务中心服务器繁忙程度的影响,因而适于非连续性和实时性要求不太高的传输场合。
短消息传输具有实现简单,通信成本低的优点。
本研究在保险柜远程报警和远程开启的应用背景下,结合其传输数据少和非连续性工作的应用特征,研制了利用51系列单片机控制GSM模块TC35I以短消息(SMS)的方式进行远程报警和开启的装置。
概述GPS/GPRS/GSM是基于SIMCOM公司SIM548C设计的一款结合GSM/GPRS&GPS功能为一体的通信模块。
可通过GPS功能定位,通过GSM短信、GSM打电话、GPRS的TCP/IP协议将GPS 数据或者其他数据信息发送到远端。
兼容Arduino接口规格。
注意:下面程序适用于GPS/GPRS/GSM第二版本。
性能描述GSM/GPRS指标∙四频GSM 850/900/1800/1900MHz∙GPRS multi-slot Class 10标准∙GPRS mobile station Class B标准∙满足 GSM 2/2+标准-Class 4(2W @ GSM850/900MHz)-Class 1(1W @ GSM1800/1900MHz)∙AT命令控制 (GSM 07.07 ,07.05和SIMCom增强型AT命令集)∙支持STK∙支持低功耗模式∙支持电压范围:3.4…4.5 V∙正常工作温度:–30°C至+80°C∙受限运作温度:–40°C至–30°C和+80°C至+85°C∙存储温度:–45°C至+90°CGPS指标∙接收20个通道,L1 1575.42 MHz,C/A 代码 1,023 MHz 芯片率∙准确定位2.5米CEP-无SA/Velocity 0.1 m/s-无SA/Time 1 μs GPS同步时间∙DGPS/SBAS位置:2.0 CEP∙Date WGS-84∙捕获时间率 (95% TTFF首个当地位置)-热启时间:< 1 秒,平均,室外-温启时间:35 秒,平均,室外-冷启时间:35 秒,平均,室外∙支持AGPS∙工作电压:3.3 V DC ±5%∙低功耗:3.3 V时,160mW∙协议-NMEA-0183(默认)-SiRF binary-RTCM SC-104∙晶体振荡器(TCXO),频率稳定的温度±0.5ppm∙Memory: 4 Mb flash and 1Mb SRAM模块特性∙通过串口执行AT命令∙GSM串口波特率:300,1200,2400,4800,9600,19200,38400,57600,115200bps(默认115200bps)可通过AT命令更改波特率GSM自动波特率:4800,9600,19200,38400,57600,115200bps∙通过串口输出GPS定位信息∙GPS串口波特率:1200,2400,4800,9600,19200,38400,57600,115200bps (默认4800bps)∙支持6针翻盖式SIM卡座∙支持耳机、麦克接口∙支持4*4矩阵键盘接口∙模块工作电压:5V∙模块尺寸:长度82mm,宽度70mm∙模块重量:引脚定义图片按键切换功能说明控制端口PD345可更改,换成别的IOGPS功能GPS部分与PC机通讯GPS数据通过串口输出到PC机∙硬件连接主控板选用Arduino 328作为例子说明。
SIM900A模块单片机SIM900A模块是一种常用的GSM/GPRS通信模块,可以用于单片机与移动通信网络的连接,实现远程监控、远程控制、短信通知等功能。
本文将介绍SIM900A模块的基本原理、使用方法以及常见问题解决方案。
一、SIM900A模块的基本原理。
SIM900A模块是基于GSM/GPRS技术的通信模块,可以实现单片机与移动通信网络的连接。
它具有GSM和GPRS双模式,支持全球四频段,可以在全球范围内使用。
SIM900A模块可以通过串口与单片机进行通信,实现短信发送、接收、电话呼叫、网络连接等功能。
SIM900A模块内部集成了GSM/GPRS通信模块、SIM卡接口、天线接口、电源管理电路等部分。
它可以通过AT指令进行控制,与单片机通信时,只需要发送相应的AT指令即可完成各种功能的操作。
SIM900A模块还具有丰富的接口,可以与各种外部设备连接,如传感器、继电器等,实现更多的应用场景。
二、SIM900A模块的使用方法。
1. 硬件连接。
使用SIM900A模块时,首先需要将SIM卡插入SIM卡接口,并连接天线。
接着将SIM900A模块的串口引脚与单片机的串口引脚相连,同时连接电源和地线。
在连接时需要注意电源的稳定性,以免影响SIM900A模块的正常工作。
2. 软件编程。
在单片机的程序中,需要通过串口向SIM900A模块发送AT指令,以实现各种功能的操作。
例如,发送短信可以使用AT+CMGS指令,接收短信可以使用AT+CMGR指令,呼叫电话可以使用ATD指令,挂断电话可以使用ATH指令,建立GPRS连接可以使用AT+CGATT指令等。
通过编写相应的程序,可以实现单片机与SIM900A模块的通信,从而实现各种功能的操作。
3. 功能测试。
在完成硬件连接和软件编程后,需要进行功能测试,以验证SIM900A模块的正常工作。
可以通过发送短信、接收短信、呼叫电话、建立GPRS连接等操作,检查SIM900A模块的各项功能是否正常。
第16卷第2期广州航海高等专科学校学报V o.l 16 N o .22008年6月J OURNAL OF GUANGZ HOU MARI TI M E COLLEGEJ un .2008文章编号:1009-8526(2008)02-0043-04单片机实验系统中GS M 、GP RS 实验模块的设计与应用柳 青1,戴立坤2(1.广州航海高等专科学校计算机与信息工程系,广东广州510725;2.江苏海事职业技术学院信息工程系,江苏南京211170)摘 要:以单片机实验系统中GSM 、GPRS 模块的应用为例,介绍单片机应用于移动通信教学实验的一个解决方案.关键词:无线通信;单片机实验系统;GS M;GPRS中图分类号:TN915 文献标识码:A收稿日期:2007-09-24作者简介:柳 青(1949)),男,教授,主要从事计算机网络技术、计算机应用、数据与信息管理的教学与研究.目前的数字蜂窝通信系统GS M 包括2个并行的系统:GS M 900和DCS1800,2个系统功能相同,主要是频率不同.GS M 系统主要由移动台(M S)、基站子系统(BS)和基站控制器(BSC)等部份组成[1].其中1)移动台:便携台(手机)或车载台,由用户识别模块(SI M 卡)和硬件设备(GS M 模块)组合而成;2)基站子系统(BS):由传输无线信号的各种硬件设备和软件组成,如发射机、接收机、天线等.一个城市内通常设有许许多多的基站;3)基站控制器(BSC ):基站收发台和移动交换中心之间的连接点,并为基站收发台和操作维修中心之间交换信息提供接口.一个基站控制器通常控制几个基站收发台,主要功能是进行无线信道管理、实施呼叫、通信链路的建立和拆除,并为本控制区内移动台的过区切换进行控制等.本文介绍利用单片机实验系统进行移动通信实验,该产品已在/汽车防盗实时监控报警系统0的产品开发中得到应用.本实验局限于移动台的物理设备,包括无线通信模块和SI M 卡两部份.其中,无线通信模块可以进行的通信实验包括GSM 和GPRS 两部份.1 GS M 与GP R SGPRS (Genera l Packet Rad i o Ser v ice ,通用无线分组业务)是一种基于GSM 系统的无线分组交换技术,提供端到端的、广域的无线I P 连接.GS M 采用拨号的电路交换数据传送方式,GPRS 采用分组交换技术,具有/实时在线0、/按量计费0、/快捷登录0、/高速传输0、/自如切换0的优点.从应用的角度看,GS M 与GPRS 主要有以下区别:¹访问速度:GS M 为9.6kbps ,GPRS 大于56kb -ps ;º建立通信的连接时间:GS M 需要10~30s ,GPRS 只需要极短的时间;»计费:GS M 按连接时间计费,GPRS 按数据流量计费.可见,GPRS 对网络资源的利用率远远高于GS M.GPRS 的优点:¹高速数据传输,GPRS 的数据传送速度是GS M 的10倍,且可以稳定地传送大容量的音频与视频信号.GS M 移动通信网的传输速度一般为每秒9.6K 字节,GPRS 的传输速度可以达到115Kbps ,是常用56Kmode m 理想速率的2倍.ºGPRS 建立连接后永远保持连接,无需为每次数据访问再建立呼叫连接,使用户随时与网络保持联系.通俗地说,GPRS 可以做到/通话、上网两不误0.»GPRS 按数据流量计费,GS M 按接通时间计费.GPRS 支持用户在进行数据传输的同时进行语音通话.2 G S M 、GPRS 实验电路[2-3]GS M 、GPRS 模块的接线图如图1所示,实验电路由GS M 、GPRS 模块U2和右边的SI M 卡两部份电路组合而成.设计要点如下:44 广州航海高等专科学校学报第16卷图1 GS M 、G PR S 实验电路图1)GS M 、GPRS 模块U2的选型要点:主要考虑的模块的典型性、可靠性、兼容性、节电性和降低成本等因素.为此,选用国产的H ua W e iGTM 900模块.除此之外,还可以采用SI M E M S 公司的TC35、M C35等模块,以提高实验板的适应性和实用性.2)GS M 、GPRS 模块的外围电路设计要点:¹模块的电源应具有不小于1.5A 的供电能力.虽然模块正常工作电流为50mA 左右(3.9V),但模块建立连接时需要不小于1.5A 的瞬间电流.为此,电源供给电路必须有大容量的滤波电解电容.根据经验,该电容不能小于2000L F .º多数应用场合中,模块的串口只有RXD 、TXD 引脚有用,其它引脚一般不用.不用的串口引脚可以悬空处理,但RTS 、DTR 引脚不能悬空,必需用电阻R7、R8接地,如图2所示.»模块的启动信号I G T.GS M 、GPRS 模块的充电过程要求I GT 引脚提供一个正脉冲的启动信号,该信号由单片机的I/O 线提供.为便于实验,设计了图2所示的启动电路,实现/向模块通电即可启动0.实践证明这是行之有效的.图2 SI M 卡的结构及引脚定义图3)SI M 接口电路,S I M 卡是GSM 、GPRS 通信系统中的/用户识别模块0,用于识别用户、存储各种数据以及计费.实质上,SI M 卡是一个微型的单片机控制的I C 卡,由CPU 、随机存储器RAM 、程序存储器ROM 、数据存储器EEPROM 和串行通信口等组成,工作电压为2.8V.图2是SI M 卡的结构和引脚定义图.其中,引脚1和4为单片机的电源供给,引脚2为复位信号,引脚3为时钟脉冲,引脚5为编程电压,引脚6为输入/输出线,引脚7和8通常不用(可用于SI M 卡是否接入的识别信号).SI M 卡上的各个触点与GSM 、GPRS 模块本身的SI M 接口线连接(见图1).图中,C13、C14、C15、C16为滤波电容.4)辅助电路,图1中LED2是GS M 模块是否已经建立连接的指示灯,由模块引脚SYNC 提供的脉冲信号通过Q 1(NP N )点亮,R9可以调节LED2的亮度.LED2的电源电压VDD 为2.8V.必需说明,如果不安装该部分电路,不会影响GS M 、GPRS 模块U2的正常工作.3 G S M 语音通话实验的电路图GS M 语音通话实验的电路图如图3所示,任务是把GSM 模块天线上接收到的语音信号转变为可第2期柳青等:单片机实验系统中GS M、G PR S实验模块的设计与应用45以用耳机接听的音频信号.图中,J5选用一个标准的电话手柄插座,以便把普通电话机手柄直接插入J5中进行语音通话.电话机手柄M I C中的偏置电压由+5V电源通过电阻R22、R25、R23、R24提供, L2、L3是语音接听电路中的滤波电感.4与微机超级终端连接的电平转换电路图4所示电平转换电路图是GS M、GPRS模块实验必不可少的.其中,U3(MAX202)为电平换器蕊片,任务是把实验板上GS M模块的TTL电平转变为微机串口所需的RS232电平.U3的第10、9脚分别与GS M模块的RXD、TXD连接(TTL电平),U2的第14、8脚为RS232电平,分别与微机串口COM1中的TXD、RXD连接;J3为微机串口COM2,用于/网络串口实验0.46广州航海高等专科学校学报第16卷5实验电路的应用以上实验电路可进行GS M模块实验与GPRS 模块实验.5.1GS M实验要点GS M模块实验主要包括两部份:语音通信实验和收发短信SM S实验.1)GS M模块的上电过程:为便于观察,使用带电流表的12V稳压电源.GS M模块刚刚上电时,由于模块要/拔号上GS M网络0,拔号上网过程的瞬间电流很大(约1.5A),维持时间很短(约200m s),称为/瞬间脉冲电流0.上网建立连接后,GS M模块的维持工作电流约50mA左右.GS M模块的上电过程可以从电流表的电流变化中得到证实.2)检查GS M模块正常工作的基本参数:检查GS M模块的供电电压是否+3.9V,检查S I M卡第二脚的工作电压是否+2.8V.3)检查GS M模块是否与微机超级终端建立了连接.主要检查GS M模块与微机超级终端的电平转换电路(图4)是否正常工作.方法:在微机键盘上键入AT并按回车键,如果在显示器上可以看到AT和OK,表示GS M模块与微机超级终端的连接正常,这是进行实验的重要保证.所有GS M模块都通过模块上的串口引脚RXD、TXD进行工作,且所有GS M模块都用AT命令进行控制,不同品牌和型号的GS M模块,其GS M 通信的AT命令基本相同,不同部分只是涉及有关GPRS通信的AT命令.4)语音通信实验方法:从微机键盘键入语音通信的AT命令/ATDxxxxxxxxxxx;0,按回车键.其中, /xxxxxxxxxxx0为对方的十一位手机号,/;0为手机号的结束符.5)短信通信的实验方法:从微机键盘键入发送短信的AT命令/AT+C MGS=-xxxxxxxxxxx.0,按回车键.其中,/xxxxxxxxxxx0为对方的十一位手机号.接收短信的方法:从微机键盘键入接收短信的AT命令/AT+C MGR=10,按回车键.其中,/10为短信索引号.5.2GPRS通信实验的有关AT命令(适用于H ua W ei GT M900模块)a t+cgdcont=1,/ip0,/c m net0<CR>a%t etcp i p<CR>a%t i o m ode=0<CR>a%t ioopen=/udp0,/xxx.xx.xx.xx0,9999<CR >(xxx.xx.xx.xx为I P地址)a%t i p send=/<aaaa>0<CR>a%t i p close=1<CR>说明:GPRS通信实验需要建立TCP/I P连接.参考文献:[1]魏红.移动通信技术[M].北京:人民邮电出版社,2005:30-150.[2]文志成.GP RS网络技术[M].北京:电子工业出版社,2005:1-30.[3]钟章队.GPRS通用分组无线业务[M].北京:人民邮电出版社,2001:1-20.DESI GN AND APPLICATI ON OF EXPER IM ENTAL MODULE OF GS M AND GPR S IN ONE-CH IP COM PUTER TEST S YSTE MLIU Q i n g1,DA I L-i kun2(1.D epart m ent o f Co m puter Sc ience and Infor m a ti o n Techno l o gy,GuangzhouM ariti m e Co llege,Guangzhou Guangdong510725,Ch i n a;2.D epart m en t o f Infor m ati o n and Eng i n eering,JiangsuM ariti m e Instit u te,Nan ji n g Jiangsu211170,Ch i n a)Abst ract:Taking the app li c ation o f experi m entalm odu le of GS M and GPRS i n One-ch i p Co m puter test syste m for exa m ple,a so lution of apply i n g One-chip Co m puter to i n struction experi m ent ofm ob ile co mmunicati o n is intr oduced hereby.K ey w ords:w ireless co mmunication;One-chip Co m puter test syste m;GSM;GPRS。
GSM短信发送PDU编码解码C++控制台实现(一)2009-04-20 14:12// SendMsg.h#include <windows.h>#include <winnls.h>#include <string>#include <stdio.h>#include <iostream>#include <memory.h>using namespace std;// 用户信息编码方式#define GSM_7BIT 0#define GSM_8BIT 4#define GSM_UCS2 8//应答状态#define GSM_WAIT 0 // 等待,不确定#define GSM_OK 1 // OK#define GSM_ERR -1 // ERROR// // 编码用到的常量定义// #define CONST91 "91"#define CONSTF "F"#define CONSTLEN 1024// #define CONST1100 "1100"// #define CONST000800 "000800"#define CONST0 0// 短消息参数结构,编码/解码共用// 其中,字符串以0结尾typedef struct {char SCA[16]; // 短消息服务中心号码(SMSC地址)char TPA[16]; // 目标号码或回复号码(TP-DA或TP-RA)char TP_PID; // 用户信息协议标识(TP-PID)char TP_DCS; // 用户信息编码方式(TP-DCS)char TP_SCTS[16]; // 服务时间戳字符串(TP_SCTS), 接收时用到 char TP_UD[161]; // 原始用户信息(编码前或解码后的TP-UD) char index; // 短消息序号,在读取时用到} SM_PARAM;typedef struct {int len;char data[16384];}SM_BUFF;class SendMsg{public:int gsmInvertNumbers(const char* pSrc,char* pDst,int nSrcLength);int gsmSerializeNumbers(const char* pSrc, char* pDst, int nSrcLength);int gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength); int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength);int gsmBytes2String(const unsigned char* pSrc, char* pDst, int nSrcLength);int gsmString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength);int gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength); int gsmDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength);int gsmEncode8bit(const char* pSrc, unsigned char* pDst,int nSrcLength) ; int gsmDecode8bit(const unsigned char* pSrc, char* pDst, int nSrcLength) ;int gsmEncodePdu(const SM_PARAM* pSrc, char* pDst);int gsmDecodePdu(const char* pSrc, SM_PARAM* pDst);BOOL gsmSendMessage(const SM_PARAM* pSrc);void gsmReadMessageList();BOOL gsmDeleteMessage(const int index);int gsmGetResponse(SM_BUFF* pBuff);int gsmParseMessageList(SM_PARAM* pMsg, SM_BUFF* pBuff);BOOL OpenComm(const char* pPort, int nBaudRate, int nParity, int nByteSize, int nStopBits );BOOL CloseComm();void WriteComm(void* pData, int nLength);int ReadComm(void* pData, int nLength);BOOL gsmInit();//// 初始化GSM状态public:SendMsg(){}~SendMsg(){}};GSM短信发送PDU编码解码C++控制台实现(二)2009-04-20 14:12//SendMsg.cpp#include "StdAfx.h"#include "SendMsg.h"HANDLE hComm;//串口设备句柄// 正常顺序的字符串转换为两两颠倒的字符串,若长度为奇数,补'F'凑成偶数// 如:"8613722216254" --> "683127226152F4"// pSrc: 源字符串指针// pDst: 目标字符串指针// nSrcLength: 源字符串长度// 返回: 目标字符串长度int SendMsg::gsmInvertNumbers(const char* pSrc,char* pDst,int nSrcLength){int nDstLength; // 目标字符串长度char ch; // 用于保存一个字符// 复制串长度nDstLength = nSrcLength;// 两两颠倒for(int i=0; i<nSrcLength;i+=2){ch = *pSrc++; // 保存先出现的字符*pDst++ = *pSrc++; // 复制后出现的字符*pDst++ = ch; // 复制先出现的字符}// 源串长度是奇数吗?if(nSrcLength & 1){*(pDst-2) = 'F'; // 补'F'nDstLength++; // 目标串长度加1}// 输出字符串加个结束符*pDst = '\0';// 返回目标字符串长度return nDstLength;}// 两两颠倒的字符串转换为正常顺序的字符串// 如:"683127226152F4" --> "8613722216254"// pSrc: 源字符串指针// pDst: 目标字符串指针// nSrcLength: 源字符串长度// 返回: 目标字符串长度int SendMsg::gsmSerializeNumbers(const char* pSrc, char* pDst, int nSrcLength){int nDstLength; // 目标字符串长度char ch; // 用于保存一个字符// 复制串长度nDstLength = nSrcLength;// 两两颠倒for(int i=0; i<nSrcLength;i+=2){ch = *pSrc++; // 保存先出现的字符*pDst++ = *pSrc++; // 复制后出现的字符*pDst++ = ch; // 复制先出现的字符}// 最后的字符是'F'吗?if(*(pDst-1) == 'F'){pDst--;nDstLength--; // 目标字符串长度减1}// 输出字符串加个结束符*pDst = '\0';// 返回目标字符串长度return nDstLength;}// 7-bit编码// pSrc: 源字符串指针// pDst: 目标编码串指针// nSrcLength: 源字符串长度// 返回: 目标编码串长度int SendMsg::gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength){int nSrc; // 源字符串的计数值int nDst; // 目标编码串的计数值int nChar; // 当前正在处理的组内字符字节的序号,范围是0-7 unsigned char nLeft; // 上一字节残余的数据// 计数值初始化nSrc = 0;nDst = 0;// 将源串每8个字节分为一组,压缩成7个字节// 循环该处理过程,直至源串被处理完// 如果分组不到8字节,也能正确处理while(nSrc<nSrcLength){// 取源字符串的计数值的最低3位nChar = nSrc & 7;// 处理源串的每个字节if(nChar == 0){// 组内第一个字节,只是保存起来,待处理下一个字节时使用nLeft = *pSrc;}else{// 组内其它字节,将其右边部分与残余数据相加,得到一个目标编码字节*pDst = (*pSrc << (8-nChar)) | nLeft;// 将该字节剩下的左边部分,作为残余数据保存起来nLeft = *pSrc >> nChar;// 修改目标串的指针和计数值 pDst++;nDst++;}// 修改源串的指针和计数值pSrc++; nSrc++;}// 返回目标串长度return nDst;}// 7-bit解码// pSrc: 源编码串指针// pDst: 目标字符串指针// nSrcLength: 源编码串长度// 返回: 目标字符串长度int SendMsg::gsmDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength){int nSrc; // 源字符串的计数值int nDst; // 目标解码串的计数值int nByte; // 当前正在处理的组内字节的序号,范围是0-6unsigned char nLeft; // 上一字节残余的数据// 计数值初始化nSrc = 0;nDst = 0;// 组内字节序号和残余数据初始化nByte = 0;nLeft = 0;// 将源数据每7个字节分为一组,解压缩成8个字节// 循环该处理过程,直至源数据被处理完// 如果分组不到7字节,也能正确处理while(nSrc<nSrcLength){// 将源字节右边部分与残余数据相加,去掉最高位,得到一个目标解码字节*pDst = ((*pSrc << nByte) | nLeft) & 0x7f;// 将该字节剩下的左边部分,作为残余数据保存起来nLeft = *pSrc >> (7-nByte);// 修改目标串的指针和计数值pDst++;nDst++;// 修改字节计数值nByte++;// 到了一组的最后一个字节if(nByte == 7){// 额外得到一个目标解码字节*pDst = nLeft;// 修改目标串的指针和计数值pDst++;nDst++;// 组内字节序号和残余数据初始化nByte = 0;nLeft = 0;}// 修改源串的指针和计数值pSrc++;nSrc++;}*pDst = 0;// 返回目标串长度return nDst;}// 8bit编码// 输入: pSrc - 源字符串指针// nSrcLength - 源字符串长度// 输出: pDst - 目标编码串指针// 返回: 目标编码串长度int SendMsg::gsmEncode8bit(const char* pSrc,unsigned char* pDst,int nSrcLength){// 简单复制memcpy(pDst, pSrc, nSrcLength);return nSrcLength;}// 8bit解码// 输入: pSrc - 源编码串指针// nSrcLength - 源编码串长度// 输出: pDst - 目标字符串指针// 返回: 目标字符串长度int SendMsg::gsmDecode8bit(const unsigned char* pSrc, char* pDst, int nSrcLength){// 简单复制memcpy(pDst, pSrc, nSrcLength);// 输出字符串加个结束符*pDst = '\0 ';return nSrcLength;}// UCS2编码// 输入: pSrc - 源字符串指针// nSrcLength - 源字符串长度// 输出: pDst - 目标编码串指针// 返回: 目标编码串长度int SendMsg::gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength){int nDstLength; // UNICODE宽字符数目WCHAR wchar[128]; // UNICODE串缓冲区// 字符串-->UNICODE串nDstLength = MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLength, wchar, 128);// 高低字节对调,输出for(int i=0; i<nDstLength; i++){*pDst++ = wchar[i] >> 8; // 先输出高位字节*pDst++ = wchar[i] & 0xff; // 后输出低位字节}// 返回目标编码串长度return nDstLength * 2;}// UCS2解码// 输入: pSrc - 源编码串指针// nSrcLength - 源编码串长度// 输出: pDst - 目标字符串指针// 返回: 目标字符串长度//int SendMsg::gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength){int nDstLength; // UNICODE宽字符数目WCHAR wchar[128]; // UNICODE串缓冲区// 高低字节对调,拼成UNICODEfor(int i=0; i<nSrcLength/2; i++){wchar[i] = *pSrc++ << 8; // 先高位字节wchar[i] |= *pSrc++; // 后低位字节}// UNICODE串-->字符串nDstLength = WideCharToMultiByte(CP_ACP, 0, wchar, nSrcLength/2, pDst, 160, NULL, NULL);// 输出字符串加个结束符pDst[nDstLength] = '\0';// 返回目标字符串长度return nDstLength;}// 可打印字符串转换为字节数据// 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}// pSrc: 源字符串指针// pDst: 目标数据指针// nSrcLength: 源字符串长度// 返回: 目标数据长度int SendMsg::gsmString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength){for(int i=0; i<nSrcLength; i+=2){// 输出高4位if(*pSrc>='0' && *pSrc<='9'){*pDst = (*pSrc - '0') << 4;}else{*pDst = (*pSrc - 'A' + 10) << 4;}pSrc++;// 输出低4位if(*pSrc>='0' && *pSrc<='9'){*pDst |= *pSrc - '0';}else{*pDst |= *pSrc - 'A' + 10;}pSrc++;pDst++;}// 返回目标数据长度return nSrcLength / 2;}// 字节数据转换为可打印字符串// 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"// pSrc: 源数据指针// pDst: 目标字符串指针// nSrcLength: 源数据长度// 返回: 目标字符串长度int SendMsg::gsmBytes2String(const unsigned char* pSrc, char* pDst, int nSrcLength){const char tab[]="0123456789ABCDEF"; // 0x0-0xf的字符查找表for(int i=0; i<nSrcLength; i++){// 输出低4位*pDst++ = tab[*pSrc >> 4];// 输出高4位*pDst++ = tab[*pSrc & 0x0f];pSrc++;}// 输出字符串加个结束符*pDst = '\0';// 返回目标字符串长度return nSrcLength * 2;}// PDU编码,用于编制、发送短消息// pSrc: 源PDU参数指针// pDst: 目标PDU串指针// 返回: 目标PDU串长度int SendMsg::gsmEncodePdu(const SM_PARAM* pSrc, char* pDst){int nLength; // 内部用的串长度int nDstLength; // 目标PDU串长度unsigned char buf[256]; // 内部用的缓冲区// SMSC地址信息段nLength = strlen(pSrc->SCA); // SMSC地址字符串的长度buf[0] = (char)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1; // SMSC地址信息长度buf[1] = 0x91; // 固定: 用国际格式号码nDstLength = gsmBytes2String(buf, pDst, 2); // 转换2个字节到目标PDU串nDstLength +=gsmInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength); // 转换SMSC到目标PDU串// TPDU段基本参数、目标地址等nLength = strlen(pSrc->TPA); // TP-DA地址字符串的长度buf[0] = 0x11; // 是发送短信(TP-MTI=01),TP-VP用相对格式(TP-VPF=10)buf[1] = 0; // TP-MR=0buf[2] = (char)nLength; // 目标地址数字个数(TP-DA地址字符串真实长度)buf[3] = 0x91; // 固定: 用国际格式号码nDstLength +=gsmBytes2String(buf, &pDst[nDstLength], 4); // 转换4个字节到目标PDU串nDstLength +=gsmInvertNumbers(pSrc->TPA, &pDst[nDstLength], nLength); // 转换TP-DA到目标PDU串// TPDU段协议标识、编码方式、用户信息等nLength = strlen(pSrc->TP_UD); // 用户信息字符串的长度buf[0] = pSrc->TP_PID; // 协议标识(TP-PID)buf[1] = pSrc->TP_DCS; // 用户信息编码方式(TP-DCS)buf[2] = 0; // 有效期(TP-VP)为5分钟if(pSrc->TP_DCS == GSM_7BIT){// 7-bit编码方式buf[3] = nLength; // 编码前长度nLength =gsmEncode7bit(pSrc->TP_UD, &buf[4], nLength+1) + 4; // 转换TP-DA到目标PDU串}else if(pSrc->TP_DCS == GSM_UCS2){// UCS2编码方式buf[3] =gsmEncodeUcs2(pSrc->TP_UD, &buf[4], nLength); // 转换TP-DA到目标PDU串nLength = buf[3] + 4; // nLength等于该段数据长度}else{// 8-bit编码方式buf[3] =gsmEncode8bit(pSrc->TP_UD, &buf[4], nLength); // 转换TP-DA到目标PDU串nLength = buf[3] + 4; // nLength等于该段数据长度}nDstLength +=gsmBytes2String(buf, &pDst[nDstLength],nLength); // 转换该段数据到目标PDU串// 返回目标字符串长度return nDstLength;}// PDU解码,用于接收、阅读短消息// pSrc: 源PDU串指针// pDst: 目标PDU参数指针// 返回: 用户信息串长度int SendMsg::gsmDecodePdu(const char* pSrc, SM_PARAM* pDst){int nDstLength; // 目标PDU串长度unsigned char tmp; // 内部用的临时字节变量unsigned char buf[256]; // 内部用的缓冲区//printf("Msg=%s\n",pSrc);// SMSC地址信息段gsmString2Bytes(pSrc, &tmp, 2); // 取长度tmp = (tmp - 1) * 2; // SMSC号码串长度pSrc += 4; // 指针后移gsmSerializeNumbers(pSrc, pDst->SCA, tmp); // 转换SMSC号码到目标PDU串pSrc += tmp; // 指针后移//printf("SMSC=%s\n",pDst->SCA);// TPDU段基本参数、回复地址等gsmString2Bytes(pSrc, &tmp, 2); // 取基本参数pSrc += 2; // 指针后移// if(tmp & 0x80)//{// 包含回复地址,取回复地址信息gsmString2Bytes(pSrc, &tmp, 2); // 取长度if(tmp & 1) tmp += 1; // 调整奇偶性pSrc += 4; // 指针后移gsmSerializeNumbers(pSrc, pDst->TPA, tmp); // 取TP-RA号码 pSrc += tmp; // 指针后移//printf("TP-RA=%s\n",pDst->TPA);//}// TPDU段协议标识、编码方式、用户信息等gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2); // 取协议标识(TP-PID)//printf("TP-PID=%c\n",pDst->TP_PID);pSrc += 2; // 指针后移gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2); // 取编码方式(TP-DCS)//printf("TP-DCS=%c\n",pDst->TP_DCS);pSrc += 2; // 指针后移gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14); // 服务时间戳字符串(TP_SCTS)//printf("TP-SCTS=%s\n",pDst->TP_SCTS);pSrc += 14; // 指针后移gsmString2Bytes(pSrc, &tmp, 2); // 用户信息长度(TP-UDL)pSrc += 2; // 指针后移if(pDst->TP_DCS == GSM_7BIT){// 7-bit解码nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (int)tmp * 7 / 4 + 2 : (int)tmp * 7 / 4); // 格式转换gsmDecode7bit(buf, pDst->TP_UD, nDstLength); // 转换到TP-DUnDstLength = tmp;}else if(pDst->TP_DCS == GSM_UCS2){// UCS2解码nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2); // 格式转换nDstLength = gsmDecodeUcs2(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU}else{// 8-bit解码nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2); // 格式转换nDstLength = gsmDecode8bit(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU}//printf("MessgeContent=%s\n",pDst->TP_UD);// 返回目标字符串长度return nDstLength;}// 发送短消息// pSrc: 源PDU参数指针BOOL SendMsg::gsmSendMessage(const SM_PARAM* pSrc){int nPduLength; // PDU串长度unsigned char nSmscLength; // SMSC串长度int nLength; // 串口收到的数据长度char cmd[16]; // 命令串char pdu[512]; // PDU串char ans[128]; // 应答串nPduLength = gsmEncodePdu(pSrc, pdu); // 根据PDU参数,编码PDU 串strcat(pdu, "\x01a"); // 以Ctrl-Z结束gsmString2Bytes(pdu, &nSmscLength, 2); // 取PDU串中的SMSC信息长度nSmscLength++; // 加上长度字节本身// 命令中的长度,不包括SMSC信息长度,以数据字节计sprintf(cmd, "AT+CMGS=%d\r", nPduLength / 2 - nSmscLength); // 生成命令WriteComm(cmd, strlen(cmd)); // 先输出命令串nLength = ReadComm(ans, 128); // 读应答数据// 根据能否找到"\r\n> "决定成功与否if(nLength == 4 && strncmp(ans, "\r\n> ", 4) == 0){WriteComm(pdu, strlen(pdu)); // 得到肯定回答,继续输出PDU串nLength =ReadComm(ans, 128); // 读应答数据// 根据能否找到"+CMS ERROR"决定成功与否if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0){return TRUE;}}return FALSE;}// 删除短消息// index: 短消息序号,从1开始BOOL SendMsg::gsmDeleteMessage(const int index){int nLength; // 串口收到的数据长度char cmd[16]; // 命令串char ans[128]; // 应答串sprintf(cmd, "AT+CMGD=%d\r", index); // 生成命令// 输出命令串WriteComm(cmd, strlen(cmd));// 读应答数据nLength = ReadComm(ans, 128);// 根据能否找到"+CMS ERROR"决定成功与否if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0){return TRUE;}return FALSE;}// 打开串口// pPort: 串口名称或设备路径,可用"COM1"// nBaudRate: 波特率// nParity: 奇偶校验// nByteSize: 数据字节宽度// nStopBits: 停止位BOOL SendMsg::OpenComm(const char* pPort, int nBaudRate, int nParity, int nByteSize, int nStopBits){DCB dcb; // 串口控制块COMMTIMEOUTS timeouts = { // 串口超时控制参数100, // 读字符间隔超时时间: 100 ms1, // 读操作时每字符的时间: 1 ms (n个字符总共为n ms)500, // 基本的(额外的)读超时时间: 500 ms1, // 写操作时每字符的时间: 1 ms (n个字符总共为n ms)100}; // 基本的(额外的)写超时时间: 100 mshComm = CreateFile(pPort, // 串口名称或设备路径GENERIC_READ | GENERIC_WRITE, // 读写方式0, // 共享方式:独占NULL, // 默认的安全描述符OPEN_EXISTING, // 创建方式0, // 不需设置文件属性NULL); // 不需参照模板文件if(hComm == INVALID_HANDLE_VALUE)return FALSE; // 打开串口失败GetCommState(hComm, &dcb); // 取DCBdcb.BaudRate = nBaudRate;dcb.ByteSize = nByteSize;dcb.Parity = nParity;dcb.StopBits = nStopBits;////////////////////PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);//SetCommMask(hComm,EV_ERR|EV_RXCHAR);/////////////////SetCommState(hComm, &dcb); // 设置DCBSetupComm(hComm, 4096, 1024); // 设置输入输出缓冲区大小SetCommTimeouts(hComm, &timeouts); // 设置超时//printf("OpenComm\n");return TRUE;}// 关闭串口BOOL SendMsg::CloseComm(){return CloseHandle(hComm);}// 写串口// pData: 待写的数据缓冲区指针// nLength: 待写的数据长度void SendMsg::WriteComm(void* pData, int nLength){DWORD dwNumWrite; // 串口发出的数据长度WriteFile(hComm, pData, (DWORD)nLength, &dwNumWrite, NULL); }// 读串口// pData: 待读的数据缓冲区指针// nLength: 待读的最大数据长度// 返回: 实际读入的数据长度int SendMsg::ReadComm(void* pData, int nLength){DWORD dwNumRead; // 串口收到的数据长度ReadFile(hComm, pData, (DWORD)nLength, &dwNumRead, NULL);return (int)dwNumRead;}// 读取短消息,仅发送命令,不读取应答// 用+CMGL代替+CMGR,可一次性读出全部短消息void SendMsg::gsmReadMessageList(){WriteComm("AT+CMGL\r",8);}// 初始化GSM状态BOOL SendMsg::gsmInit(){char ans[128]; // 应答串// 测试GSM-MODEM的存在性WriteComm("AT\r", 3);Sleep(100);ReadComm(ans, 128);if (strstr(ans, "OK") == NULL) //给两次机会{Sleep(100);WriteComm("AT\r", 3);ReadComm(ans, 128);if(strstr(ans, "OK") == NULL)return FALSE;}// ECHO OFFWriteComm("ATE0\r", 5);ReadComm(ans, 128);// PDU模式WriteComm("AT+CMGF=0\r", 10);ReadComm(ans, 128);//////////////////////////////////////WriteComm("AT+CSMS=1\r", 10);ReadComm(ans, 128);WriteComm("AT+CNMI=2,1\r", 12);ReadComm(ans, 128);///////////////////////////////////////// printf("InitCOMM\n");return TRUE;}// 读取GSM MODEM的应答,可能是一部分// 输出: pBuff - 接收应答缓冲区// 返回: GSM MODEM的应答状态, GSM_WAIT/GSM_OK/GSM_ERR// 备注: 可能需要多次调用才能完成读取一次应答,首次调用时应将pBuff初始化int SendMsg::gsmGetResponse(SM_BUFF* pBuff){int nLength; // 串口收到的数据长度int nState;// 从串口读数据,追加到缓冲区尾部nLength = ReadComm(&pBuff->data[pBuff->len], 128);pBuff->len += nLength;//确定GSM MODEM的应答状态nState = GSM_WAIT;if ((nLength > 0) && (pBuff->len >= 4)){//if (strncmp(&pBuff->data[pBuff->len - 4], "OK\r\n", 4) == 0) if(strstr(pBuff->data, "OK\r\n")!=NULL)nState = GSM_OK;else if (strstr(pBuff->data, "+CMS ERROR") != NULL)nState = GSM_ERR;}return nState;}// 从列表中解析出全部短消息// 输入: pBuff - 短消息列表缓冲区// 输出: pMsg - 短消息缓冲区// 返回: 短消息条数int SendMsg::gsmParseMessageList(SM_PARAM* pMsg, SM_BUFF* pBuff) {int nMsg; // 短消息计数值char* ptr; // 内部用的数据指针nMsg = 0;ptr = pBuff->data;// 循环读取每一条短消息, 以"+CMGL:"开头while((ptr = strstr(ptr, "+CMGL:")) != NULL){ptr += 6; // 跳过"+CMGL:", 定位到序号//sscanf(ptr, "%d", &pMsg->index); // 读取序号// TRACE(" index=%d\n",pMsg->index);//printf("index=%d\n",pMsg->index);ptr = strstr(ptr, "\r\n"); // 找下一行if (ptr != NULL){ptr += 2; // 跳过"\r\n", 定位到PDUgsmDecodePdu(ptr, pMsg); // PDU串解码pMsg++; // 准备读下一条短消息nMsg++; // 短消息计数加1}}return nMsg; }。
本科毕业设计(论文)题目:基于单片机的短信收发系统设计Graduation DesignThe Design Of Messaging System BasedOn MCUBy Wang HuiSupervised byLecture. SHI XinxinSchool of AutomationNanjing Institute of TechnologyJune, 2015摘要随着手机的广泛使用,GSM网络提供的短消息服务使得只需要增加少量投入便可以通过手机实现生活和生产中的远程控制和告警通知成为可能。
本设计是基于ARM Cortex-M3内核的32位单片机STM32的一种短信收发系统。
本系统主要实现中英文短信收发及TFT彩屏显示相关状态如短信未读、已读状态、短信发送状态和内容如要读取短信数、读取到的短信内容、时间、发件人手机号码等,并且可以实现通过TFT液晶屏触摸输入号码和功能按键如读取、返回、拨号、挂断、删除等。
此方案以ST公司32位单片机STM32F103ZET6为主控制器辅以GSM/GPRS模块SIM900A,64Mb串行Flash 存储器W25Q64,2K串行EEPROM AT24C02,TFT液晶屏ILI9320等硬件,通过C语言编写程序,用软硬件结合的方法实现其基本功能。
经过多次实践测试,本系统可以达到预期的稳定性、可靠性,可以应用在远程控制、智能家居、工业控制等领域。
关键词:SIM900A;STM32;短信;GSM;TFT液晶屏ABSTRACTWith the widespread use of mobile phones, short message services provided by the GSM network make it possible that only a slight increase in investment and production will be able to live in the remote control and alarm notification via cell phone.In this thesis , a messaging system base on the 32-bit MCU STM32 which is based on the core of Cortex-M3 by ARM is discussed.The system is mainly a Chinese and English text messaging and that TFT color screen displays the status of messages such as unread, read status, SMS status and content, such as the number of messages to be read, read the message content, time, sender's phone number, etc. and can be achieved by TFT LCD touch screen to input the number and function keys such as reading, return, dial, hang up, delete, and so on.This program selects ST company's 32-bit MCU STM32F103ZET6 as controller supplemented GSM / GPRS module SIM900A, 64Mb Serial Flash memory W25Q64,2K serial EEPROM AT24C02, TFT LCD ILI9320 hardware, through C language programming,and achieve its basic functions with the combination of software and hardware.After several practice tests, the system can achieve the desired stability, reliability, and can be used in remote control, smart home, industrial control and other fields.Key words:SIM900A; STM32; messaging; GSM; TFT screen目录第一章绪论 (1)1.1 引言 (1)1.2 选题背景与意义 (1)1.3 应用现状及发展趋势 (1)第二章 GSM系统及方案设计 (2)2.1 GSM系统 (3)2.1.1 GSM系统特点 (3)2.1.2 GSM系统的体系结构 (3)2.2 GSM系统方案设计 (4)2.3 本章小结 (5)第三章系统硬件设计 (5)3.1 单片机最小系统 (6)3.1.1主控制器 (6)3.1.2 主控制器外围简单电路 (6)3.1.3 JTAG接口 (8)3.1.4 电源电路 (9)3.2 SIM900A模块 (10)3.2.1 SIM900A模块的对外接口电路 (10)3.2.2 SIM900A模块初始化 (11)3.3 外围电路设计 (12)3.3.1 一键下载电路 (12)3.3.2 TFT液晶屏接口 (12)3.3.3外部存储器 (13)3.3.4 按键和指示灯电路 (15)3.3.5 蜂鸣器电路 (16)3.4 本章小结 (17)第四章系统软件设计 (17)4.1 总体框图 (17)4.2 系统初始化 (18)4.3 文件系统FATFS移植 (19)4.4 汉字字库 (19)4.4.1 更新字库 (19)4.4.2 查找汉字 (20)4.5 触摸屏模块 (23)4.6 RTC显示 (25)4.6.1 RTC简介 (25)4.6.2 设置时间 (25)4.6.3备份区域保护 (25)4.7 开关机 (26)4.7.1 待机模式简介 (26)4.7.2 开关机实现过程 (26)4.8 本章小结 (27)第五章系统调试 (28)5.1系统调试过程与方法 (28)5.1.1 串口通信 (28)5.1.2 系统UI (30)5.1.3 读取短信 (31)5.1.4 发送短信 (32)5.1.5 电话测试 (33)5.2系统调试结果与分析 (34)5.3本章小结 (41)第六章结论 (43)6.1 主要工作与结论 (43)6.2 存在的问题 (43)6.3 感想与收获 (43)致谢 (44)参考文献.................................................................................. 错误!未定义书签。
手机短信收发的AT指令控制在现代生活中,手机已经成为我们日常生活中不可或缺的一部分。
而谈到手机,就不可避免地要说到短信收发。
短信作为一种便捷的通讯方式,在我们的日常生活中占据了重要的地位。
大家知道吗?通过使用AT指令,我们还可以更好地控制我们的手机短信收发。
AT指令是一种用于控制终端的指令,最早出现在模拟时代,并在数字时代得到了进一步的发展和普及。
通过这些指令,我们可以在手机中执行各种操作,包括但不限于发送短信、读取短信、设置短信服务中心号码等等。
我们来了解一下如何使用AT指令来发送短信。
在大多数情况下,我们可以通过在手机上输入“AT+CMGS=短信长度+短信中心号码+短信内容”来发送短信。
其中,“AT”是AT指令的开头,“CMGS”则是用于发送短信的指令。
在指令后,我们需要输入短信的长度、短信中心号码和短信内容。
在输入完所有内容之后,我们还需要输入“Ctrl+Z”来结束输入。
当然,这只是最基本的短信发送方式。
实际上,我们还可以使用AT 指令来设置更多的短信相关的参数,包括服务中心号码、短信存储时间等等。
例如,我们可以使用“AT+CSCA=服务中心号码”来设置服务中心号码;使用“AT+CSCB=0”来设置短信存储时间为0,即不存储短信;使用“AT+CSC=0,1”来设置短信存储时间为1小时等等。
除了发送短信之外,我们还可以使用AT指令来读取短信。
例如,我们可以使用“AT+CMGR=短信序号”来读取指定序号的短信;使用“AT+CMGL=0”来读取所有未读短信;使用“AT+CMGL=1”来读取所有已读和未读短信等等。
通过使用AT指在现代社会中,短信收发已经成为人们日常生活中不可或缺的一部分。
随着科技的发展,利用单片机控制GSM模块实现短信收发已经变得越来越普遍。
本文将介绍单片机控制GSM模块实现短信收发的技术及应用。
单片机是一种集成度较高的芯片,可以通过编程来实现各种不同的控制功能。
GSM模块是一种专门用于短信收发的模块,它可以通过SIM卡来实现短信的收发功能。
■ 武汉理工大学 王骐 何嘉斌摘 要关键词借助系统模型,阐明GSM模块收发短信的基本概念以及串口控制SMS的基本原理。
详细介绍单片机控制GSM模块工作的软件实现过程,对怎样用单片机控制GSM模块收发短信进行探讨,也对程序设计的主体思想作了较为细致的分析。
单片机 短信收发 软件设计GSM(Global System for Mobile communication)系统是目前基于时分多址技术的移动通信体制中,比较成熟完善,且应用最广泛的一种系统。
目前已建成的覆盖全国的GSM数字蜂窝移动通信网,是我国公众移动通信网的主要方式。
基于GSM的短信息服务,是一种在移动网络上传送简短信息的无线应用,是一种信息在移动网络上储存和转寄的过程。
由于公众GSM网络在全球范围内实现了联网和漫游,建立上述系统不需再组建专用通信网络,所以具有实时传输数据功能的短信应用将得到迅速普及。
笔者开发设计的基于GSM网络的温度数据采集与无线传输系统正是借助该网络平台,利用短信息业务实现数据的自动双向传递。
系统模型图如图1所示。
本系统由数据采集部分、数据接收和发送部分、终端处理部分三个模块组成。
数据采集模块将采集到的温度数据存入存储器中。
数据收发模块采用双单片机共用E2RPOM的方式,单片机2控制数据从存储器转存入E2PROM中;单片机1负责将数据从E2PROM中读出,并经GSM模块2借助GSM网络将数据发送出去。
单片机1不仅控制数据的发送,也控制数据的接收。
在这里,E2PROM是温度数据临时存储和上传的中转站。
终端处理模块负责将接收到的数据交给计算机处理,并将处理后的结果存放到数据库中,以供查询。
当终端处理模块需要向GSM模块2发送控制命令时,GSM模块2接收过程正好与上述过程相反,从而实现数据的自动双向传递。
系统中,三个模块相互独立,彼此又相互依赖,共同完成数据的传输。
数据收发模块在系统中起着承上启下的作用,是系统的核心模块。
该模块以双单片机为核心,以RS232通信接口,在物理层上实现与GSM模块的连接。
由于篇幅的限制,本文主要介绍单片机控制这一模块工作的软件实现过程,旨在对怎样用单片机控制GSM模块收发短信息进行探讨。
1GSM模块MZ28MZ28是中兴通讯推出的GSM无线双频调制解调器,主要为语音传输、短信发送和数据业务提供无线接口。
MZ28集成了完整的射频电路和GSM的基带处理器,特别适合于迅速开发基于GSM无线网络的无线应用产品。
带有人机接口(MMI)界面的应用产品内部与MZ28的通信可通过标准的串行接口(RS232)进行。
MZ28使用简单的20-PIN ZIP插座与用户自己的应用系统相连,此ZIP连接方式提供开发所需的数据通信、音频和电源等接口信号。
MZ28可以作为无线引擎,嵌入到用户自己的产品当中,用户可以用单片机或其它CPU的UART口,使用相应的AT命令,对模块进行控制,达到使其产品可以轻松进入GSM网络的目的。
2串口控制SMS的工作原理单片机与GSM模块一般采用串行异步通信接口,通信速度可设定,通常为19200bps。
采用这种RS232电缆终端处理模块图1 系统模型图单片机控制GSM模块实现短信收发的软件设计※方式进行连接时,数据传输的可靠性较好。
RS232接口方式连接,通过串行接口集成电路和电平转换电路与GSM模块连接,电路比较简单,所涉及的芯片包括单片机89C52和电平转换芯片MAX232,是非常常见的接口电路。
需要说明的是,该接口通过I2C总线扩展了一个E2PROM存储器芯片AT24C64,它的主要作用是存储采集到的数据。
该芯片能够反复擦/写,能够持久保存数据,而且断电信息也不会丢失,这些特性正是存储数据所必须的。
GSM的短信息业务SMS利用信令信道传输,这是GSM通信网所特有的。
它不用拨号建立连接,把要发的信息加上目的地址发送到短信息服务中心,经短信服务中心完成存储后再发送给最终的信宿。
所以当目的GSM终端没开机时信息不会丢失。
每个短信的信息量限制为160字节。
现在市场上大多数手机均支持GSM07.05规定的AT指令集。
该指令集是ETSI(欧洲通信技术委员会)发布的,其中包含了对SMS的控制。
利用GSM手机的串行接口,单片机向手机收发一系列的AT命令,就能达到控制GSM模块收发SMS的目的。
必须注意的是,用单片机实现时,编程必须注意它发送指令与接收到的响应都是字符的ASCII码。
用单片机控制GSM模块收发短信息所涉及到的AT指令如表1所列。
3软件实现3.1上位机模块和下位机模块半双工通信协议的实现3.1.1应答和重发上位机模块和下位机模块的通信双方遵照半双工通信方式进行,即数据传送是双向的。
但是,任何时刻只能由其中的一方发送数据,另一方接收数据,因为E2PROM的读出和写入不能同时进行。
为了避免一方在发送信息帧时(这里的信息帧指的是下位机模块发送的数据帧和上位机模块发送的命令帧,下同),另一方也会发送数据,必须把信道变成半双工方式。
尽管这样效率可能不如全双工方式,但通过此举牺牲效率可以换取模块工作性能的稳定。
双方采取的顺序是:发→收到应答后→再发。
按照整个系统的设计思路,上位机模块(即图1中的GSM模块1,下同)发送的帧包括命令帧、确认帧和非确认帧;下位机模块(即图1中的GSM模块2,下同)发送的帧包括数据帧、确认帧和非确认帧。
其中确认帧和非确认帧是发送数据后等待对方发送的应答帧,以此作为继续发送下一帧和重新发送上一帧的依据。
命令帧和数据帧是信息帧。
当一方先发送完信息帧,如果收方接收到对方的信息帧,而又没有信息帧需要发送,那么情况就比较简单,收方将根据信息帧的正确与否决定发送确认帧还是非确认帧,以使对方决定是继续发送还是重新发送;如果此刻收方也有信息帧需要发送,那么收方将不立即发送应答帧,而是立即发送本方的信息帧给对方,并等待对方对此帧的应答帧,在收到对方的应答帧后,收方将依据应答帧的内容(即确认帧或者是非确认帧,下同)决定是继续发送下一信息帧,还是重新发送原来的信息帧。
如果由于链路本身不可靠等因素造成应答帧的丢失,收方将在一定时间内因为没有收到应答帧而延时重发原来的信息帧。
在收到对方的应答帧后,收方将继续发送下一信息帧,并等待对方的应答帧,如此反复,直到收方全部发送完信息帧。
在本方收到对方最后一个应答帧后,表明本方全部的信息帧发送完毕。
然后收方将发送对方仍然等待的应答帧,通知对方收到的信息帧正确与否。
3.1.2延时重发在双方通信过程中,有两个时间t1和t2,分别表示重新发送信息帧的最大延时。
t1表示一方发送完信息帧到收到对方应答帧的时间,如果等待应答帧的时间超过了t1,则发方会重新发送原来的信息帧;当收方接收到对方发送的信息帧,如果收方此时有需要发送的信息帧,则收方此刻不发送应答帧,而是发送信息帧给对方。
也就是说,利用对方等待收方应答帧的时间t1内,收方插入发送本方的信息帧,同样本方的发送也存在一个延时重发的问题。
在规定的时间内,如果没有收到对方应答帧,收方也同样需要重发原来的信息帧,这个规定的时间就是t2。
显然由于收方是利用间隙时间发送本方信息帧,所以t2<t1。
图2以下位机模块先发数据帧为例,阐述双方通信的具体实现过程。
需要说明的是,由于版面的限制,图2所示的通信过程没有涉及到发送非确认帧的情况,如果收方发送非确认帧,发方的发送过程跟发送数据帧是一样的,只不过这种情况下需要重发同一帧号的数据帧。
如果上位机模块先发命令帧,双方通信的实现过程跟图2类似,所表1 AT指令 A T指令功能描述AT+OFF 关机并重新启动AT+CSDH=0 在TEXT模式下在返回值中不显示详细的头信息ATE0 关闭回显AT+CMGF=1 选择短信格式为TEXT模式AT+CMGS 发送短信息AT+CMGR 读取短信息AT+CMGD=0 删除全部短信息不同的是数据帧此时变成命令帧,命令帧变成数据帧。
在延时的时间上,无论是下位机先发送数据帧还是上位机先发送命令帧,t2的大小都应该是一样的,都是利用时间间隙t1发送收方信息帧,延时的时间是相同的。
然而,对于t1而言,情况就有所不同。
因为下位机模块先发送数据帧时,利用t1的间隙时间上位机模块发送的命令帧可能较少,因此当下位机模块先发送数据帧时所定义的t1应该小于当上位机模块先发送命令帧时,所定义的t1。
这是因为当上位机模块先发送命令帧时,利用t1的间隙时间下位机模块发送的数据帧可能比较多。
3.2帧格式GSM模块通过异步通信接口实现对SMS的控制共有三种接入协议:Block Mode;基于AT指令的TextMode;基于AT指令PDU Mode。
本系统发送和接收的数据都是基于数字的温度数据和命令字,为了保证系统的适用性,SMS的收发采用TEXT模式。
TEXT模式是基于字符的,更具体地说是基于ASCII码的一种结构模式。
在该模式下,模块发送和接收的信息帧格式如下。
信息帧包括数据帧和命令帧。
帧头表示数据帧的标记,是由固定的字符“WQ”构成。
帧序号表示数据帧的序号,由两个字节组成。
帧序号表示下位机模块发送的递增数据帧序号和上位机模块发送的命令帧序号。
为了简化帧结构,命令帧的序号统一为00H。
数据字段的长度为154字节,最多发送77个字符(采用TEXT模式,不能发送汉字)。
检验子为数据字段所有字节累加和的补码(原码取反加1),由一个字节组成。
在整个帧结构中,帧头字段是由两个固定的字符组成,这两个字符都可以通过模块直接发送。
在帧序号、数据、校验子三个字段中,都存在这样一个问题:这三个字段都可能要发送某些模块不能直接发送的字符,比如00H等。
为此采取了一种编码方案,将高低4位分别加上40H,拆成两个字节进行发送,比如要发送00H,那么模块会发送40H、40H。
当然,很多字符都是可以直接发送的,为了程序算法的简便,将所有要发送的字符统一进行这种“一拆二”的编码方案。
因此,这三个字段实际的字节数经过编码后都会扩大2倍。
TEXT模式下,一次能发送的字符数是160个字节,它是由帧头(2字节)+帧序号(2字节)+数据(154字节)+校验子(2字节)构成的。
除了信息帧外,双向传送的还有应答帧,它包括确认帧和非确认帧。
确认帧是收方反馈给发方的应答帧,表示收方已经正确接收到了发方发送的信息帧。
确认帧格式仅包括两个字段,且两个字段的内容都是固定的,即帧头“WQ”和数据字段“ACK”,确认帧格式如下。
非确认帧是收方反馈给发方的应答帧,表示收方收到的是无效的信息帧,其格式与应答帧格式类似,帧格式如下。
3.3E2PROM空间的分配采用8KB的E2PROM,按照每77个字节为一个块进行划分,共106块,如图3所示。
第00、01块留作系统使用,第02块~第105块是数据块,用作存放数据。