单片机怎么控制gsm_使用单片机控制gsm发送接受短信 - CSDN
  • 这是51单片机控制GSM模块收发短信的程序,希望可以帮到你
  • 详细介绍单片机控制GSM模块工作的软件实现过程,对怎样用单片机控制GSM模块收发短信进行探讨,也对程序设计的主体思想作了较为细致的分析。 关键词:单片机 短信收发 软件设计 GSM(Global System for Mobile ...

    摘要:借助系统模型,阐明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模块收发短信息进行探讨。

    1 GSM模块MZ28

    MZ28是中兴通讯推出的GSM无线双频调制解调器,主要为语音传输、短信发送和数据业务提供无线接口。MZ28集成了完整的射频电路和GSM的基带处理器,特别适合于迅速开发基于GSM无线网络的无线应用产品。带有人机接口(MMI)界面的应用产品内部与MZ28的通信可通过标准的串行接口(RS232)进行。MZ28使用简单的20-PIN ZIP插座与用户自己的应用系统相连,此ZIP连接方式提供开发所需的数据通信、音频和电源等接口信号。MZ28可以作为无线引擎,嵌入到用户自己的产品当中,用户可以用单片机或其它CPU的UART口,使用相应的AT命令,对模块进行控制,达到使其产品可以轻松进入GSM网络的目的。

    2 串口控制SMS的工作原理

    单片机与GSM模块一般采用串行异步通信接口,通信速度可设定,通常为19200bps。采用这种RSM232电缆方式进行连接时,数据传输的可靠性较好。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所列。

    表1 AT指令

    AT指令

    功 能 描 述

    AT+OFF 关机并重新启动
    AT+CSDH=0 在TEXT模式下在返回值中不显示详细的头信息
    ATE0 关闭回显
    AT+CMGF=1 选择短信格式为TEXT模式
    AT+CMGS 发送短信息
    AT+CMGR 读取短信息
    AT+CMGD=0 删除全部短信息

    3 软件实现

    3.1 上位机模块和下位机模块半双工通信协议的实现

    3.1.1 应答和重发

    上位机模块和下位模块的通信双方遵照半双工通信方式进行,即数据传送是双向的。但是,任何时刻只能由其中的一方发送数据,另一方接收数据,因为E2PROM的读出和写入不能同时进行。为了避免一方在发送信息帧时(这里的信息帧指的是下位机模块发送的数据帧和上位机模块发送的命令帧,下同),另一方也会发送数据,必须把信道变成半双工方式。尽管这样效率可能不如全双工方式,但通过此举牺牲效率可以换取模块工作性能的稳定。双方采取的顺序是:发→收到应答后→再发。

    按照整个系统的设计思路,上位机模块(即图1中的GSM模块1,下同)发送的帧包括命令帧、确认帧和非确认帧;下位机模块(即图1中的GSM模块2,下同)发送的帧包括数据帧、确认帧和非确认帧。其中确认帧和非确认帧是发送数据后等待对方发送的应答帧,以此作为继续发送下一帧和重新发送上一帧的依据。命令帧和数据帧是信息帧,当一方先发送完信息帧,如果收方接收到对方的信息帧,而又没有信息帧需要发送,那么情况就比较简单,收方将根据信息帧的正确与否决定发送确认帧还是非确认帧,以使对方决定是继续发送还是重新发送;如果此刻收方也有信息帧需要发送,那么收方将不立即发送应答帧,而是立即发送本方的信息帧给对方,并等待对方对此帧的应的应答帧,在收到对方的应答帧后,收方将依据应答帧的内容(即确认帧或者是非确认帧,下同)决定是继续发送下一信息帧,还是重新发送原来的信息帧。如果由于链路本身不可靠等因素造成应答帧的丢失,收方将在一定时间内因为没有收到应答帧而延时重发原来的信息帧。在收到对方的应答帧后,收方将继续发送下一信息帧,并等待对方的应答帧,如此反复,直到收方全部发送完信息帧。在本方收到对方最后一个应答帧后,表明本方全部的信息帧发送完毕。然后收方将发送对方仍然等待的应答帧,通知对方收到的信息帧正确与否。

    图2

    3.1.2 延时重发

    在双方通信过程中,有两个时间t1和t2,分别表示重新发送信息帧的最大延时。t1表示一方发送完信息帧到收到对方应答帧的时间,如果等待应答帧的时间超过了t1,则发方会重新发送原来的信息帧;当收方接收到对方发送的信息帧,如果收方此时有需要发送的信息帧,则收方此记得不发送应答帧,而是发送信息帧给对方。也就是说,利用对方等待收方应答帧的时间t1内,收方插入发送本文的信息帧,同样本方的发送也存在一个延时重发的问题。在规定的时间内,如果没有收到对方应答帧,收方也同样需要重发原来的信息帧,这个规定的时间就是t2。显然由于收方是利用间隙时间发送本方信息帧,所以t2<t1。

    图2以下位机模块先发数据帧为例,阐述双方通信的具体实现过程。

    需要说明的是,由于版面的限制,图2所示的通信过程没有涉及到发送非确认帧的情况,如果收方发送非常认帧,发方的发送过程跟发送数据帧是一样的,只不过这种情况下需要重发同一帧号的数据帧。如果上位机模块先发命令帧,双方通信的实现过程跟图2类似,所不同的是数据帧此时变成命令帧,命令帧变成数据帧。在延时的时间上,无论是下位机发送数据帧还是上位机发送命令帧,t2的大小都应该是一样的,都是利用时间间隔t2发送收方信息帧,延时的时间是相同的。然而,对于t1而方,情况就有所不同。因为下位机模块先发送数据帧时,利用t1的间隔时间上位机模块发送的命令帧可靠较少,因此当下位机模块先发送数据帧时所定义的t1应该小于当上位机模块先发送命令帧时,所定义的t1。这是因为当上位机模块先发送命令帧时,利用t1的间隔时间下位机模块发送的数据帧可能比较多。

    3.2 帧格式

    GSM模块通过异步通信接口实现对SMS的控制共有三种接入协议:Block Mode;基于AT指令的Text Mode;基于AT指令PDU Mode。本系统发送和接收的数据都是基于数字的温度数据和命令字,为了保证系统的适用性,SMS的收发采用TEXT模式。TEXT模式是基于字符的,更具体地说是基于ASCII码的一种结构模式。在该模式下,模块发送和接收的信息帧格式如下:

    帧头 帧序号 数据 校验子

    信息帧包括数据帧和命令帧。

    帧头表示数据帧的标记,是由固定的字符“WQ”构成。

    帧序号表示数据帧的序号,由两个字节组成。帧序号表示下位机模块发送的递增数据帧序号和上位机模块发送的命令帧序号。为了简化帧结构,命令帧的序号统一为00H。

    数据字段的长度为154字节,最多发送77个字符(采用TEXT模式,不能发送汉字)。

    检验子为数据字段所有字节累加和的初码(原码取反加1),由一个字节组成。

    除了信息帧外,双向传递的还有应答帧,它包括确认帧和非确认帧。确认帧是双方反馈给发方的应答帧,表示收方已经正确接收到了发方发送的信息帧。确认帧格式仅包括两个字段,且两个字段的内容都是固定的,即帧头“WQ”和数据字段“ACK”,确认帧格式如下。

    WQ ACK

    非确认帧是收方给发方的应答帧,表示收方收到的是无效的信息帧,其格式与应答帧格式类似,帧格式如下。

    WQ NACK

    3.3 E2PROM空间的分配

    采用8KB的E2PROM,按照每77个字节为一个块进行划分,共106块,如图3所示。

    第00、01块留作系统使用,第02块~第105块是数据块,用作存放数据。

    3.4 收发端与采集端的握手协议

    收发端与采集端共用一个存储器,即双CPU对同一个E2PROM进行操作。实现方案是分别使两个微处理器的一个I/O脚相连,两个CPU采用查询方式对此I/O端进行查询。如果某时候收发端查询到本地I/O端为高电平,则单片机1拥有此存储器的操作权,可以对E2PROM进行读写操作。如果采集端查询到本地I/O端为高电平,则单片机2拥有此存储器的操作权,可以对它进行写操作。一方操作完毕后将I2C总线置为高电平,表明本端已经释放I2C总线,E2PROM目前处于可用状态。

    3.5 程序的设计

    3.5.1 主函数的设计思路

    开机上电后,程序在主函数中运行,单片机和GSM模块分别进行初始化。单片机的初始化包括设置串口工作方式、波特率,并初始化变量参数和标志位。GSM模块初始化包括重新启动、关闭回显、设置在TEXT模式下的返回值中不显示详细的头信息、选择短信格式为TEXT模式、开发串口中断准备接收数据。

    3.5.2 GSM返回参数的处理—SHELL函数

    SHELL函数是进入时钟中断程序时被调用时,该函数是对GSM模块返回参数进行处理的函数。根据系统设计的要求,需要对GSM模块进行下列操作:呼叫对方模块号码、发送数据、阅读短信、删除短信。基于以上操作指令,如果操作成功GSM模块会分别返回不同的参数:>、+CMGS、+CMGR、OK。根据接收到的不同参数,下位机模块将转向不同的操作步骤,判断并改变标志位的值。比如,如果某时刻接收到>,这表明呼叫对方模块号码获得成功,接下来需要发送数据。这时SHELL函数将检查发送不同数据所代表的标志位f_sending、f_ack、f_nack,从而决定需要发送何种类型的数据。

    3.5.3 短信数据的处理—ExecData函数

    进入时钟中断调用SHELL函数时,如果接收到了返回的参数+CMTI,表明上位机模块向下位机模块发送了短信数据,可能是命令帧,也可能是确认帧或者非确认帧。在这种情况下,SHELL函数需要对短信内容进行分析,并根据短信的内容进行不同的处理,负责完成以上功能的就是ExecData函数,它是被SHELL函数调用的,用来分析并处理短信数据。

    结语

    通过以上的分析不难发现,整个程序错综复杂,函数之间相互牵扯。标志位在程序的实现过程中扮演着非常重要的角色,正是依靠这些标志位,程序才能很好地实现各个功能之间的切换,而标志位的值是通过OSM模块返回的参数修改的。因此程序的实现过程应该是阅读参数→修改标志位→发送指令。

    主函数、时钟中断和串口中断程序、SHELL函数、ExecData函数贯穿整个程序的主线和核心部分,对它们的分析可以理解程序的主体思想,这也正是笔者着重介绍的原因所在。然而这些函数和中断程序的实现,还需要依靠其它函数的配合,比如基于I2C总线的E2PROM操作函数、字符串操作函数以及串口发送函数等,由于篇幅所限,在此不再介绍。GSM网络本身是不完全可靠的,可能会发生帧发送错误、帧丢失的现象。但是由于重发、延时重发机制的存在,程序可以最大程度避免上述情况的发生。在实际应用过程中,模块运行正常,性能稳定,实时性好。

    展开全文
  • 51单片机控制GSM模块TC35i发短信,打电话的完整C程序!
  • 本程序实现了基于51单片机控制GSM模块通过短信控制继电器
  • STC89C52单片机控制GSM发送短信例程
  • 首先,GSM发短信,对英文和中文的处理是不一样的,请参考以下资料: 1 简述 使用GSM模块收发短信,主要有两个部分需要考虑,一个是AT指令,一个串口读写。Tc35i GSM模块在收发短信时,分为两种模式,一为text...
    首先,GSM发短信,对英文和中文的处理是不一样的,请参考以下资料:

    1 简述
    使用GSM模块收发短信,主要有两个部分需要考虑,一个是AT指令,一个串口读写。Tc35i GSM模块在收发短信时,分为两种模式,一为text模式,一为pdu模式,如果只需要发送英文内容,则text模式足矣,但若要发送中文短信,则必须使用pdu模式。串口的读写在不同的系统里是有区别的,在windows下使用系统提供的win32 API可以实现串口操作,在linux下串口作为文件读写,在单片机上串口的读写是把一个个字符送入特定缓冲区即可,但无论在何种系统中,操作串口之前都需要对串口进行初始化操作。
    2 AT指令
    在使用AT指令发送短信的时候,可以使用串口调试助手(windows和linux下的串口调试助手不同,而且版本也有许多,但使用方法大致相同,都需要先找到串口的端口号,windows下可以到设备管理器中查看(注意安装好usb转串口驱动),linux下可以到/dev下查看,设置波特率9600,校验位None,数据位8,停止位1;windows下可以使用stc-isp带有的串口助手,在linux下可以使用minicom,)来帮助熟悉指令,以及了解短信发送的流程。
    2.1 TEXT模式
    先对模块SMS进行一些初始设置,AT+CMGF=1设置为Text模式,AT+CSMP=17,167,0,0设置Text模式参数,AT+CSCS=GSM设置GSM字符集,接下来发送一条短信,例如要往15948020629这个号码发送一条短信,输入命令AT+CMGS=15948020629 并回车,返回
    >
    接着输入短信内容,输入完毕后以->结尾,这个字符是ASCII码中的26(0x1A),一个控制字符,在这里作为结束标志,测试时可以在正常短信内容输入完毕后:先点发送,再以十六进制方式输入1A,1A也就是16进制的026,再点发送,这时接收区就会显示这个符号,以后再需要这个符号时可以直接粘贴使用。如果返回OK就说明短信发送成功。需要注意的是,虽然有短信息服务中心号码设置的命令,不过一般不需要我们设置的,可以使用AT+CSCA?来查询服务中心号码。
    下面来往模块中发送一条短信,注意犹豫此时是Text模式,所以发送内容应为英文内容,包括数字,英文标点。发送短信前执行AT+CNMI=2,1
    此命令的作用是当有新的短信时给予提醒并显示存储位置,同时还会将信息存储到默认的内存位置。例如发送信息的手机为15948020629,信息到达后接收区显示
    +CMTI: "ME",22
    我们可以使用AT+CMGR=22来将其读出,接收区显示
    +CMGR: "REC UNREAD","15948020629",,"08/03/25,09:51:01+32"
    ADG123456

    OK
    其中ADG123456为短信内容,REC UNREAD 表示这条短信未读,以后再读取这条短信时将变为REC READ,接收时间时间,短信号码等信息皆显示在第一行里。
    2.2 PDU模式
    假如我要发送下面的短信:
    接收号码:+8613602433649
    短信内容:工作愉快!
    短信中心号码:+8613800200500
    一、短信中心号码处理:用字符串 addr 表示
    1、将短信息中心号码去掉+号,看看长度是否为偶数,如果不是,最后添加F
    即 addr = "+8613800100500"
    => addr = "8613800100500F"
    2、将奇数位和偶数位交换。
    => addr = "683108100005F0"
    3、将短信息中心号码前面加上字符91,91是国际化的意思
    => addr = "91683108100005F0"
    4、算出 addr 长度,结果除2,格式化成2位的16进制字符串,16 / 2 = 8 => "08"
    => addr = "0891683108100005F0"
    二、手机号码处理:用字符串 phone
    1、将手机号码去掉+号,看看长度是否为偶数,如果不是,最后添加F
    即 phone = "+8613602433649"
    => phone = "8613602433649F"
    2、将手机号码奇数位和偶数位交换。
    => phone = "683106423346F9"
    三、短信息部分处理:用字符串 msg 表示
    1、转字符串转换为Unicode代码,例如“工作愉快!”的unicode代码为 5DE54F5C61095FEBFF01,(5de54f5c61095febff01)
    (转换函数见最后附录)
    2、将 msg 长度除2,保留两位16进制数,即 5DE54F5C61095FEBFF01 = 20 / 2 => "0A",再加上 msg
    => msg = "0A5DE54F5C61095FEBFF01"
    四、组合
    1、手机号码前加上字符串 11000D91(1100:固定,0D:手机号码的长度,不算+号,十六进制表示,91:发送到手机为91,发送到小灵通为81),
    即 phone = "11000D91" + phone
    => 11000D91683106423346F9
    2、手机号码后加上 000800 和刚才的短信息内容,000800也写死就可以了
    即 phone = phone + "000800" + msg
    即 11000D91683106423346F9 + 000800 + 0A5DE54F5C61095FEBFF01
    => phone = 11000D91683106423346F90008000A5DE54F5C61095FEBFF01
    3、phone 长度除以2,格式化成2位的十进制数
    即 11000D91683106423346F90008000A5DE54F5C61095FEBFF01 => 50位 / 2 => 25
    五、所以要发送的内容为
    AT+CMGF=0 <回车>
    OK
    AT+CMGS=25<回车>
    > addr+phone <Ctrl+Z发送> (_)
    六、如果返回不是ERROR,恭喜你,发送成功了^_^
    其详细过程参看下图:
    [img]http://dl.iteye.com/upload/attachment/518816/89dd6fe0-07d4-37ea-b94c-651107ee4296.jpg[/img]
    2.3 常用AT指令
    命令 作用
    AT 测试连接是否正确
    ATE0/ATE1 关闭回显/打开回显
    AT+CGMI 得到厂商信息
    AT+CGMR 得到手机版本号
    AT+CGSN 得到手机序列号(IMEI)
    AT+CIMI 得到手机IMSI号码
    AT+CSCS 获取、设置手机当前字符集。可设置为 GSM 或 UCS2
    AT+CCLK 获取设置手机时钟
    AT+COPS 网络营运商
    AT+CSCA 短信中心号码
    AT+CPMS 选择短信储存地点。可选择 ME(SIM卡)和MT(机身)
    AT+CMGL 列出短信,列出指定状态的短信息的PDU代码
    AT+CMGR 读短信,列出指定序号的短信息PDU代码
    AT+CMGS 发送短信
    AT+CMGD 删除指定的短信
    AT+CMGF 短信格式。分为Text模式和PDU模式
    AT+CNMI 设置新短消息通知电脑端

    3 串口通信
    串口通信注意两点:一,在任何一个系统中,操作串口和操作其他设备的接口是一样的,都是系统提供的最基础的API,有打开,初始化,读写和关闭操作;二,如果不喜欢使用系统提供的API,网上有已经封装好了的串口通信类,使用这些串口通信类可以极大地减小出错的概率。
    3.1 windows
    3.1.1 win32 API

    见源码
    3.1.2 A communication class for serial port
    见源码
    windows下串口通信类的下载及使用方法请参见:
    http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c2483
    3.2 linux
    3.2.1 File Operation
    见源码
    3.2.2 a qt class for serial communication
    见源码
    linux下(其实是基于qt扩展的,既可以用于linux下也可以用于windows下)串口通信类的下载及使用方法请参见:
    http://code.google.com/p/qextserialport/
    [img]http://dl.iteye.com/upload/attachment/518818/5db8e927-b8ec-3f37-800b-a8d717781bb5.png[/img]
    3.3 单片机
    可以参看redmine系统中的单片机学习报告中关于串口通信的相信介绍。

    4 附录
    4.1 native2ascii工具
    在使用GSM模块发送和接收短信的时候,如果是中文,必须转化为unicode编码,这里介绍一个小工具
    在java的安装目录下,找到位于jdk目录下的bin目录下,有一个可执行文件: native2ascii.exe
    双击这个.exe文件,弹出一个命令行控制台,直接输入中文,然后回车,返回的字符则是相应中文的unicode编码,其实这个工具用的很广泛,在做一些java的企业级应用,如果需要进行国际化,往往都会使用这个工具对资源文件进行编码控制。
    其详细使用方法如下:
      1、只转换特定字符
      在控制台中可以输入汉字回车后,就可以看到转移后的字符了。
      Ctrl+C退出。
      2、转换properties文件
      native2ascii allMessages_zh_CN.input.properties allMessages_zh_CN.properties
      将文件allMessages_zh_CN.input.properties编码后输出为allMessages_zh_CN.properties。
      为了方便properties文件的管理,建议纯中文的配置文件用input命名。
      3、反向单一properties文件
      native2ascii -reverse allMessages_zh_CN.properties allMessages_zh_CN.txt
      注意-reverse参数
      4、批量反向所有的properties文件
      JDK自带的工具native2ascii可以将uncode编码的文件转换为本地编码的文件,但是不能批量转换文件。
    4.2 更多相关资料,请参看以下链接:
    GSM模块TC35i调试心得
    http://hi.baidu.com/robo2046/blog/item/7a407a589560e4d39c8204e1.html
    用MSP430串口中断服务程序将接受到的数据回发回去
    http://zhidao.baidu.com/question/202687795.html
    MSP430单片机的端口介绍
    http://blog.csdn.net/chen_cheng_fly/article/details/4552402
    MSP430单片机IO
    http://www.cnblogs.com/MrYang/archive/2010/04/14/1711993.html
    MSP430 多源中断 中断标志软件复位的问题
    http://bbs.21ic.com/icview-188418-1-1.html
    MSP430中断嵌套机制
    http://www.jdzj.com/pic/Class346/Class362/20091207165253.html
    MSP430源程序---P1.0口做外部中断
    http://hi.baidu.com/liclny/blog/item/ed92b62f5cb8fd3f1e3089c2.html
    引用 IAR+Proteus7.6仿真MSP430单片机PORT1外部中断功能
    http://datouguaa.blog.163.com/blog/static/166069841201052811221152/
    MSP430单片机学习(一)——Flash读写操作
    http://hi.baidu.com/frfly2008/blog/item/3a17df16aafd591fc83d6d08.html
    MSP430单片机入门例程-按键处理示例
    http://www.cpu-led.com/forum.php?mod=viewthread&tid=1918&archiver=1
    ***********下一篇文章会放出源码,以下是上位机上的截图***************
    [img]http://dl.iteye.com/upload/attachment/518820/4e639b22-feff-3054-9c4a-1b71248a8743.jpg[/img]
    展开全文
  • #include "serial.h" #include "bianliang.h" #include #include #include "1602.H" #define rev_FAUSE 0  #define rev_OK 1 #define SELInt_on() ES=1 #define SELInt_off() ES=0 ...uchar tem
    #include "serial.h"
    #include "bianliang.h"
    #include <REG51.h>
    #include <string.h>
    #include "1602.H"
    #define rev_FAUSE 0 
    #define rev_OK 1
    #define SELInt_on() ES=1      
    #define SELInt_off() ES=0      
    uchar temp[3];
    unsigned long ss;


    extern bit P0_0;
    extern bit P0_1;
    extern bit P0_2;
    extern bit P0_3;
    extern bit P0_4;
    extern bit P0_5;
    extern bit P0_6;
    extern bit P0_7;


    sbit P0_0=P0^0;
    sbit P0_1=P0^1;
    sbit P0_2=P0^2;
    sbit P0_3=P0^3;
    sbit P0_4=P0^4;
    sbit P0_5=P0^5;
    sbit P0_6=P0^6;
    sbit P0_7=P0^7;
    sbit P1_0=P1^0;
    sbit P1_1=P1^1;
    sbit P1_2=P1^2;
    sbit P1_3=P1^3;
    sbit P1_4=P1^4;
    sbit P1_5=P1^5;
    sbit P1_6=P1^6;
    sbit P1_7=P1^7;
    sbit P2_0=P2^0;
    sbit P2_1=P2^1;
    sbit P2_2=P2^2;
    sbit P2_3=P2^3;


    void delay1(int n)
    {
      uchar i;
      while(n--)
       for(i=0;i<100;i++);
    }
    void Excrescent(void)
    {
    if(Rev_Buf[0]==0x00)
    xx=1;
    else
    xx=0;
    }


    void gsm_Over(void)
    {
      Ser_TxDchar(0x0d);
      Ser_TxDchar(0x0a);
    }






    void Cls_Rebuf(void)
    {
    unsigned char i;
    for(i=0;i<Rev_BufSIZE+1;i++)
    {
        Rev_Buf[i]=0;
    }
    Rev_count=0;  
    }




    Test_Mc39i(void)
    {
    Cls_Rebuf();
      SELInt_off();
    Ser_TXDstring(TC_HEAD,2);//发送AT
    gsm_Over();//回车换行
    SELInt_on();
    while(Rev_count<9);
    Rev_count=0;
    Excrescent();
    for(i=5+xx;i<7+xx;i++)
    {
    temp[i-5-xx]=Rev_Buf[i];
    }
        if(!strcmp(temp,TC_OK))
    return rev_OK;
    else
    return rev_FAUSE;


    }




    MES_Mode(unsigned char mode)
    {
    Cls_Rebuf();
      SELInt_off();
      Ser_TXDstring(TC_HEAD,3);
      Ser_TXDstring(TC_CMGF,5);
      Ser_TxDchar(mode+0x30);
      gsm_Over();
      SELInt_on();
    while(Rev_count<15);
    Rev_count=0;
    Excrescent();
    for(i=12+xx;i<14+xx;i++)
    {
    temp[i-12-xx]=Rev_Buf[i];
    }
        if(!strcmp(temp,TC_OK))
        return rev_OK;
    else
    return rev_FAUSE;

    }




    Set_Speed(void)
    {


    Cls_Rebuf();
      SELInt_off();
    Ser_TXDstring(TC_HEAD,3);
    Ser_TXDstring(TC_IPR,8);
    gsm_Over();
    SELInt_on();
    while(Rev_count<18);
    Rev_count=0;
    Excrescent();
    for(i=14+xx;i<16+xx;i++)
    {
    temp[i-14-xx]=Rev_Buf[i];
    }
        if(!strcmp(temp,TC_OK))
    return rev_OK;
    else
    return rev_FAUSE;

    }


    Sent_Mes(unsigned char *p)
    {
    Cls_Rebuf();
      SELInt_off();
    Ser_TXDstring(TC_HEAD,3);
    Ser_TXDstring(TC_CMGS,5);
    Ser_TxDchar(0x22);
      Ser_TXDstring(TelNumber,11);
      Ser_TxDchar(0x22);
      gsm_Over();
      SELInt_on();
    ss=0xffff;
    while(Rev_Buf[Rev_count-1]!=0x3e)
        {
    ss--;   
    if(ss==0)
    {return;}
        }
    SELInt_off();
    Ser_TXDstring(p,5);
    Ser_TxDchar(0x1a);
    SELInt_on();
    }
    Store_Location(void)
    {


    Cls_Rebuf();
      SELInt_off();
    Ser_TXDstring(TC_HEAD,3);
    Ser_TXDstring(TC_CPMS,5);
    Ser_TxDchar(0x22);
    Ser_TXDstring(TC_SM,2);
    Ser_TxDchar(0x22);
    Ser_TxDchar(0x2C);
    Ser_TxDchar(0x22);
    Ser_TXDstring(TC_SM,2);
    Ser_TxDchar(0x22);
    Ser_TxDchar(0x2C);
    Ser_TxDchar(0x22);
    Ser_TXDstring(TC_SM,2);
    Ser_TxDchar(0x22);
    gsm_Over();
    SELInt_on();
    while(Rev_count<54);
    Rev_count=0;
    Excrescent();
    for(i=50+xx;i<52+xx;i++)
    {
    temp[i-50-xx]=Rev_Buf[i];
    }
        if(!strcmp(temp,TC_OK))
    return rev_OK;
    else
    return rev_FAUSE;


    }




    Auto_Prompt(void)
    {


    Cls_Rebuf();
      SELInt_off();
    Ser_TXDstring(TC_HEAD,3);
    Ser_TXDstring(TC_CNMI,8);
    gsm_Over();
      SELInt_on();
    while(Rev_count<17);
    Rev_count=0;
    Excrescent();
    for(i=14+xx;i<16+xx;i++)
    {
    temp[i-14-xx]=Rev_Buf[i];
    }
        if(!strcmp(temp,TC_OK))
    return rev_OK;
    else
    return rev_FAUSE;
    }




    void New_Mes(void)
    {
    Excrescent();
    for(i=3+xx;i<7+xx;i++)
    {
    temp1[i-3-xx]=Rev_Buf[i];
    }


        if(!strcmp(temp1,TC_CMTI))
    {
    if(Rev_Buf[10]==0x53&&Rev_Buf[11]==0x4D)
    {
    NewSMS_flag=1;
    MES_COUNT=Rev_Buf[13];
    Cls_Rebuf();
    }
    }


    }




    void Read_Mes(uchar num)
    {
    Cls_Rebuf();
      SELInt_off();
    Ser_TXDstring(TC_HEAD,3);
    Ser_TXDstring(TC_CMGR,5);
    Ser_TxDchar(num);
    gsm_Over();
    SELInt_on();
    ss=0xffff;
    while(Rev_Buf[Rev_count-1]!=0x4B)
        {
    ss--;  
    if(ss==0)
    {return;}
        }
    for(i=30;i<40;i++)
    {
    if(Rev_Buf[i]==0x2B&Rev_Buf[i+1]==0x38&Rev_Buf[i+2]==0x36)
    {
    t=i;

    }
    }
    for(i=t+3;i<t+14;i++)
    {
    TEL_Buf[i-t-3]=Rev_Buf[i];
    }
    TEL_Buf[11]=0x00;

    for(i=t-20;i<t-15;i++)
    {
    CMD_Buf[i-t+20]=Rev_Buf[i];
    CMD_Buf[5]=0x00;
    }


    }




    Del_Mes(num)
    {
    Cls_Rebuf();
    SELInt_off();
    Ser_TXDstring(TC_HEAD,3);
    Ser_TXDstring(TC_CMGD,5);
    Ser_TxDchar(num);
    gsm_Over();
    SELInt_on();
    while(Rev_count<14);

    Rev_count=0;
    for(i=12;i<14;i++)
    {
    temp[i-12]=Rev_Buf[i];
    }
        if(!strcmp(temp,TC_OK))
    return rev_OK;
    else
    return rev_FAUSE;
    Cls_Rebuf();
    }






    void CMD_SHIBIE(void)
    {
    if(!strcmp(TEL_Buf,TelNumber))
    {
    P1_2=0;
    TELNUM_OK=1;  

    }
    else  
    { P1_3=0;
    TELNUM_OK=0;
    Del_Mes(MES_COUNT);
    Cls_Rebuf();
    NewSMS_flag=0;
    }
    if(!strcmp(CMD_Buf,CMD_1))
    {
    CMD=1;


    }
    else if(!strcmp(CMD_Buf,CMD_2))
    {
    CMD=2;


    }
    else
    {
    CMD=0;
    }
    }






    void INIT_GSM(void)
    {
    if(Test_Mc39i())
    {
    if(MES_Mode(1))
    {
    if(Set_Speed())
    {
    if(Store_Location())
    {
    if(Auto_Prompt())
    P1_0=0;
    }


    }

    }
    }
    Cls_Rebuf();

    }


    我做过一点;
    (1)pc机和单片机发送的串口数据是不是不一样?
    答:一样,一般都为9600,n,8,1
    
    (2)把单片机和pc上位机相连,pc的超级终端接收的命令确实正确的?
    答:可以连,注意RXD和TXD应交叉对联。满足单片机发送PC接收,PC发送MCU接收的关系
    
    (2)是不是单片机和pc机波特率不一样?
    答,GSM模块一般都是自适应模特率的,只要断电一次,就可以自己适应当前波特率
    
    注意:你通讯补上可能是RXD和TXD交叉的问题(交换TXD和RXD尝试)
    ,也可能是需要硬件握手的问题(RTS  CTS

    展开全文
  • 9C51单片机控制GSM模块TC35的程序(C语言的) 部分程序: #include #include #define uchar unsigned char #define uint unsigned int #define RxIn 90 //定义接收的数组长度为90 uchar code AT[]="AT"; //握手信号...
  • 51单片机控制GSM模块TC35的方法介绍一种 采用GSM的短信功能,可以使某些控制达到“零距离"。由于短信息的费用低廉,可以取代传统的无线遥控。现在详细介绍一种采用单片机(MCS51系列)控制TC35(廉价的GSM模块)发送、接收...

    51单片机控制GSM模块TC35的方法

    介绍一种 采用GSM的短信功能,可以使某些控制达到“零距离"。由于短信息的费用低廉,可以取代传统的无线遥控。现在详细介绍一种采用单片机(MCS51系列)控制TC35(廉价的GSM模块)发送、接收GSM短信的方法。
    一、  TC35的控制简介
        TC35是Siemeils公司推出的新-代无线通信GSM模块。自带RS232通讯接口,可以方便地与PC机、单片机连机通讯。可以快速、安全、可靠地实现系统方案中的数据、语音传输、短消息服务(Short Message Service)和传真。TC35模块的工作电压为3.3—5.5V,可以工作在900MHz和1800MHz两个频段,所在频段功耗分别为2w(900M)和1w(1800M)。
        模块有AT命令集接口,支持文本和PDU模式的短消息、第三组的二类传真、以及2.4k,4.8k,9.6k的非透明模式。此外,该模块还具有电话簿功能、多方通话,漫游检测功能,常用工作模式有省电模式、IDLE、TALK等模式。通过独特的40引脚的ZIF连接器,实现电源连接、指令、数据、语音信号、及控制信号的双向传输。通过ZIF连接器及50Ω天线连接器,可分别连接SIM卡支架和天线。
        TC35模块主要由GSM基带处理器、GSM射频模块、供电模块(ASIC)、闪存、ZIF连接器、天线接口六部分组成。作为TC35的核心,基带处理器主要处理GSM终端内的语音、数据信号,并涵盖了蜂窝射频设备中的所有的模拟和数字功能。在不需要额外硬件电路的前提下,可支持FR、HR和EFR语音信道编码。其它功能介绍可参见有关资料!

    二、AT指令的介绍
    TC35模块的通讯全部采用AT+xxx完成。

    三、  TC35的连机方法
        任何一个TC35模块首次使用时,必须要测试其工作是否正常,由于其自带RS232接口,所以我们可以用PC机的串口调试软件进行调试。
    1、启动串口调试软件

      串口调试软件有许多,可以使用任意一款软件,也可以使用WINDOWS自带的“超级终端"。设置波特率19.2k,这是TC35的默认波特率,首次连机可以从2400~57.6k不断测试,直到TC35有应答。

    2、发送“AT"’
      AT 回车

    3、改变波特率“AT+IPS=XXXX"
      TC35的默认波特率是19.2k,实际使用时,可以改成9600或38.4K,方法如下:
      AT+IPR=9600 回车

    4、短信模式的设置
      (GSM模块的短信模式有2种。第1种是:TEXT模式;第2种是:PDU模式。PDU模式可以采用unicode编码发送英文、汉字。但合成PDU码比较复杂,而TEXT模式只能发送英文,但无须编码。实际使用可以采用TEXT模式。
    设置如下:
        AT+CMFG=1 回车

    5、短信模式简介
        SMS是由Etsi所制定的一个规范(GSM 03.40和GSM 03.38)。当使用7-bits编码的时候它可以发送最多160个字符;8-bit编码(最多140个字符)。通常无法直接通过手机显示;通常被用来作为数据消息,例如:smart messaging中的图片和铃声和OTA WAP设置。16-bit信息(最多70个字符)被用来显示Unicode(UCS2)文本信息,可以被大多数的手机所显示。一个以class 0开头的16-bit的文本信息将在某些手机上作为Flash SMS显示(闪烁的SMS和警告SMS)。
        有两种方式来发送和接收SMS信息:使用文本模式或者使用PDU(protocol description unit)模式。文本模式(可能某些手机不支持)实际上也是一种PDU编码的一种表现形式。在显示SMS信息,可能使用不同的字符集和不同的编码方式。

    6、短信读取方法
        AT+CMGR=X回车
    如果有短信息,TC35回应:
    AT+CMGR=1
    +CMGR:"REC UNREAD","13307496548",,"04/08/17,22:24:32+02
    testOK
    OK
    短信息分析:
    “test OK"就是短信息内容。
    短信息的存储容量与Ic卡有关,序号从1-N。
    REC UNREAD":代表短信息未读过。
    REC READ"    :已读过。
    13307496548"  :接收的手机号码。
    04/08/17,22:24:32+02":短信息发送的时间。
    无短信息,TC35回应:
    AT+CMGR=3
    +CMGR:0,,0

    7、短信的删除方法
        AT+CMGD=1回车

    8、短信的发送方法
        短信息的发送分成两步:
        1:发送接收的手机号码,等待应答:“>"
        AT+CMGS="13307496548"回车(目的地址)
        TC35回应:
        AT+CMGS="13307496548"  >
        2:  输入短信息的内容(只能是英文):Test 回车

    四、单片机控制TC35的方法
        上面介绍了用PC机控制TC35的方法,我们只需将PC机输出的控制命令转化成单片机输出的指令即可。
    1、硬件连接
      电路只需设计一个TTL转RS232电平电路,连接到MCU的UART口,另一端直接连接到TC35。
    2、指令输出的方法
        单片机串口设置成模式1(9600,N,8,1),依次将AT+xxx以ASCII码形式输出到UART口;接收TC35的数据采用中断方式。这里给出详细的程序清单(Keil C51),不介绍编程的方法。程序见下:

    //AT指令的定义
    char code AT_Tc35[]="AT+";    //连机
    char code Bps_Tc35[]="IPR=38400";  //波特率
    char code Text_Tc35[]="CMGF=1";    //文本模式
    char code Read_Tc35[]="CMGR=";  //读信息
    char code Erase_Tc35[]="CMGD=";  //删除信息
    char code Send_Tc35[]="CMGS=";  //发送信息
    char code Creg_Tc35[]="CREG?";    //注册

    //模式设置
    void UART_Init(void)
    {
    SCON=0x50;    //01010000b=>1模式scon,#11011000b;
    ES=l;
    }

    //发送-个ASCII
    void SendASC(unsigned char ASC)
    {
    bit es;
    es=ES;
    ES=0;//关闭中断
    TI=0;
    SBUF=ASC;
    while(!TI);
    TI=0;
    ES=es;
    )

    //发送命令到TC35
    void SendToTc35(unsigned char* p,unsigned char Long)
    {
    while(Long--)
    {
        SendASC(*p++);
      }
    }

    //  通讯中断接收程序
    void Rs485_Do(void) interrupt 4 using 1
      {
      if(RI==l)
      {
        RI=0;
        RsBuq[RsPoint++]=SBUF;
        if fRsPoint>=sizeof(RsBuf))
        {
        RsPoint=0;//FlagRs485=0;
        }  //数据处理
      }
    }

    // 发送AT连机命令
    char code AT_Code[]="OK";
    void Send_AT(void)
    {
    unsigned char *p;
    while(1)
    {
        ClrRsBuf(RsBuf,sizeof(RsBuf));
        SendToTc35(AT_Tc35,2);    //"AT"
        SendASC(OVER);
    //************等待应答“ok"
        ES=1;    //必须中断
        Delay(50);
        P=strstr(RsBuf,AT_Code);
        if(p!=NULL) break;
    }
    )

    //发送bps连机命令
    void Send_BPS(void)
    {
    SendToTc35(AT_Tc35,3);    //"AT+"
    SendToTc35(Bps_Tc35,sizeof(Bps_Tc35)-1);//"IPR=19200"
    SendASC(OVER);
    }

    //设置文本
    void SetText(void)
    {
    SendToTc35(AT_Tc35,3);    //"AT+"
    SendToTc35(Text_tc35,sizeof(Text_tc35)-1);//"IPR=19200"
    SendASC(OVER);
    Delay(100):

    //删除短信息
    unsigned char EraseMsg(unsigned char index)
    {
    unsigned char *p,i=20;
    SendToTc35(AT_Tc35,3);    //"AT+"
    SendToTc35(Erase_Tc35,sizeof(Erase_Tc35)-1);//"IPR=19200"
    SendASC(index);
    SendASC(OVER);
    ES=1;
    while(i--)
    {
        Delay(200);
        P=strstr(RsBuf,AT_Code);
        if(P!=NULL)    {return 1;}
    }
    return 0;
    }

    //读取短信息
    char code Ask_No[]="+CMGR:0,,0";
    char code ERROR{]="ERROR";
    char code Ask_Tc35[]="/";
    unsigned char ReadMsg(unsigned char index)
    {
    unsigned char *p,i;
    unsigned char Buf[40];
    SendToTc35(AT_Tc35,3);    //"AT+"
    SendToTc35(Read_Tc35,sizeof(Read_Tc35)-1);
    SendASC(index);
    SendASC(OVER);
    ES=1;    //必须中断
    Delay(600);
    /*-------
        ES=0:
        SendToTc35(RsBuf,99);
        ES=1;
    */|

    p=strstr(RsBuf,ERROR);
    if(P!=NULL)
    {
        Send_AT();return 0;
    p=strstr(RsBuf,Ask_No);//无信息
    if(p!=NULL)return 0;
    p=strstr(RsBuf,Ask_Tc35);//20个字节后是MSG
    if(p==NULL) return 0;
    p=p+21;
    for(i=0;i<sizeof(Buf);i++)
    {
      Buf=*p++;
    }

    if(EraseMsg(index)==0) return 0;
    p=strcpy(RsBuf,Buf);  //放回RsBuf
    return 1;
    )

    //发送短信息
    char code SK[]=">";
    void SendMsgStart(void)
    {
    unsigned char *p,i=10;
    SendToTc35(AT_Tc35,3);    //"AT+"
    SendToTc35(Send_Tc35,sizeof(Send_Tc35)-1);//"IPR=19200"
    SendASC(YinHao);
    SendToTc35(Mp1.Hand,sizeof(Mp1.Hand));    //"AT+"
    SendASC(YinHao);
    SendASC(OVER);
    ES=1;
    while(i--)
    {
      Delay(100);  //Get">"
      p=strstr(RsBuf,SK);//">"
      if(p!=NULL)
      {
        ClrRsBuf(RsBuf,sizeof(RsBuf));
        Delay(150);  //Get">"
        break;
    }
    }
    }

    展开全文
  • 单片机控制GSM手机的技术及应用随着科技的飞速发展和人民生活水平的不断提高,手机的普及率越来越高,更新也越来越快,价格也越来越便宜。 因为手机工作的无线网络覆盖范围广,在信息传递方面性能稳定、可靠,所以把...

    单片机控制GSM手机的技术及应用

    随着科技的飞速发展和人民生活水平的不断提高,手机的普及率越来越高,更新也越来越快,价格也越来越便宜。 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

      因为手机工作的无线网络覆盖范围广,在信息传递方面性能稳定、可靠,所以把手机作为信息传递的载体,与单片机结合起来构成应用系统有着强大的生命力和广阔的应用空间,特别是在远程数据传输、远程监控等领域更是受到电子设计应用工程师的关注。一些专业刊物也介绍了一些有关这方面的文章,然而由于手机的控制指令复杂,数据格式繁琐,工程技术人员在进行单片机与手机的硬软件接口设计时经常会遇到很多困难,有时还无资料可查。笔者在完成一个项目的开发过程中,针对几种手机进行了大量的测试和实验,在此基础上归纳出一些带规律性的结论,对此结论,工程设计人员可拿来即用,大大缩短研发周期,现在把它公布出来,愿与广大电子设计人员共享。

      1 硬件接口技术方面

      目前市场上流行的大部分手机几乎都具有数据引出口,并基本上都支持与GsM短信息相关的AT控制指令(GSM-SMS- AT指令),手机通过数据口以串行方式接收指令并向外输出数据。理论上讲,在数据口中找出RxDTxDGND引脚与单片机的串口对应连接即完成了硬件接口。

      然而,实际上由于不同品牌,不同型号手机的RxDTxDGND引脚并非一致,找查这三根线有时也非易事;况且手机数据口的电平既不是 RS232电平,也不是TTL电平,与由5V供电的单片机串口还不能直接连接。最简单可靠的方法是使用手机的数据线建立单片机与手机的硬件连接。手机数据线是专为连接PC9针串口而设计的,信号电平为标准的RS232电平,只要单片机的串口也转换为Rs 2 3 2电平,就可方便连接。9针串口引脚定义是固定的,即2脚为TxD(手机发送)3脚为RxD(手机接收)5脚为GND。这样,无论什么型号的手机与单片机的连接就成了固定连接,不需要知道手机数据口信号的具体定义,二者通过数据线的连接电路如图1所示。 

    <?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

      需要注意的是:不同手机数据线内部电平转换芯片的供电方式是不同的,有的是通过手机直接供电;有的是通过窃取PC机串口某些引脚(通常为4678引脚)的电流经内部整流滤波稳压后提供。判断的方法是将数据线一端插到手机数据口,测量另一端2脚与5脚之间的电压,如果有一7V左右的电压,则为前者,如果测不出电压,则为后者,对于后者则需要单片机为4678引脚任意一引脚提供+5V电压即可,如图1中虚线所示。

      2 软件接口技术及控制原理

      单片机与手机的软件接口其实就是单片机通过与GSM短信息有关的AT指令控制手机的控制技术,如读取手机的短消息内容,删除短消息内容,列出手机中还未读的短消息等。关于AT指令的功能描述见参考文献[1 2]的文章内容,此处不再赘述。然而,执行一条指令,也并非某些资料中介绍得那么简单。事实上,指令的执行过程需要单片机与手机交互应答完成,每一次发送或接收的字节数有严格的规定,二者必须依据这些规定实现数据交换,否则,通信就是失败的。笔者经过对几种手机反复测试,总结出来一些规律,如表1所列。

    点击看原图

      对几个问题说明如下。

      所有AT指令的指令符号、常数、PDu数据包等都是以ASCII编码形式传送的,比如“A”ASCII编码为41H“T”AscII编码为54H,数字“0,,的AsCⅡ编码为30H等。

      单片机控制手机工作,必须把手机的短信息工作模式设置为PDu格式,即通过指令AT+cMGF=O完成。

      单片机向手机发送每一条指令后,必须以回车符作为该条指令的结束,回车的ASCII编码为0DH。例如,单片机向手机发送“AT+CMGF= 0”这条指令,其ASCII编码序列为“41H54H2BH42H4DH47H46H3DH30H0DH”,最后一个字节0DH就是回车符,表示该条指令结束,如果没有这个回车符,手机将不识别这条指令。

      当手机接收到一条完整的AT指令后,手机并不立即执行这条指令,而是先把刚才接收到的AT指令的全部ASCII编码序列全部反发送出来(0DH),然后发送一个回车符和换行符的ASCII编码,即0DH0AH,最后执行该条指令。

      手机向单片机传送短信息内容时,其PDu数据包的内容是以十六进制表示的数据,但并不是直接向单片机传递十六进制数据,而仍然是把每一位十六进制数以AscII 编码来发送。这样,二个字节的十六进制数就变成4字节的ASCII码。但是,PDU数据包中的数据字节长度部分仍然是实际字节长度,而不是变成AscII 码的字节长度,这在编程时应特别注意,否则,接收的数据就不完整。单片机接收到PDU数据包数据后,必须将其恢复成十六进制数据,其算法如下:设a为接收的ASCII码,b为转换后的十六进制数。如果a<39H,则b=a-30H;如果a>39H,则b=a-30H-07H,最后把前后两个数合并为一个字节。

        ⑥手机向单片机应答PDU数据包的字节数不包括前9字节数据(短信服务中心地址),但向单片机传送PDU数据包时,包括这9个字节的数据。例如,如果手机应答的PDU数据长度为50,而实际向单片机传送的十六进制数据为59字节,ASCII码为2×59字节,所以,单片机必须按2×59字节接收PDU数据。

      3 应用实例

      笔者利用上述原理和接口技术开发了一个项目:高速公路显示导引系统。安装在高速公路上的LED显示屏实时显示前方路段车辆通行态势和天气气候情况,提醒并引导驾驶人员,正确驾驶。

      该系统的使用一定程度上消除了许多交通事故隐患,从而保障了道路的畅通和人民生命财产的安全。该系统由控制中心和若干个显示屏组成。控制中心实时将最新信息发送到各显示屏。构建控制中心与显示终端的通信链路,传统的方法要么铺设光缆用有线方式实现,要么构建专用无线网用无线方式实现。因为高速公路的特殊性,控制中心与显示终端之间的距离通常很远,两种方案都必须投入大量资金和巨大的施工工作量。如果采用GSM公众无线传输网络,控制中心以短信息的形式把显示信息发送到显示终端的技术方案,则具有投资小,施工方便,工作可靠,运行费用低等诸多优点。

      在控制中心,微机编辑好短信息后通过手机这个载体发送出去。在显示终端,单片机通过读取手机的短信息把它显示到LED显示屏上。项目的核心技术是单片机与手机的接口和PDU数据包中的汉字信息编码。因为短信息中的汉字仅仅是一个编码,单片机应用系统将编码变为汉字点阵数据,必须配置汉字字库。按GSM07.05协议规定,短信息中的汉字编码为Unicode编码,如果构建一个Unicode编码的汉字字库,确实是一件繁琐的工作,因此,在设计单片机应用系统时,采用如下两点技术措施。

      单片机系统配置的字库为GB-2312编码的汉字库,即区位码汉字库,该汉字库在网上可免费下载,固化到Flash存储芯片中即可。当然这样做的前提是PDU数据包中的汉字编码必须为汉字内码而非Unicode编码。

      控制中心编辑PDU数据包数据时,采用自定义数据方式,其中,代表汉字的数据,直接取用汉字的机内码即可,免去了把机内码再转换为Unicode编码之苦。实践证明,这是可行的。

      采用以上技术措施的优点,一是省去了两种编码的相互转换;二是保证了数据的保密性,非系统内用户无法接收,即使接收也无法显示。

      该项目研制成功投入使用后,因显示终端只接收不发送,几乎没有运行成本。发送端(控制中心)可采用月租方式,也能把运行费用降低到最低限度。因此该项目得到用户满意的评价。

     

    展开全文
  • 自己改的AT89S51单片机控制GSM模块(M22)发送短信程序,在Keil上编译没错,但还未试过烧入片内运行。。 大家看看,这个程序可行否? 还有什么错误的地方? 希望搞过GSM的朋友多提点意见,让程序完善起来! (偶弄...
  • 基于单片机GSM短信发送系统,上电之后发送短信到指定的手机 程序简单,方便
  • 本系统采用单片机以及GSM模块,通过AT指令与GSM模块通讯,识别短信内容,从而实现远程控制继电器,实现远程控制控制功能
  • 基于51单片机的短信收发设计,采用1602作为输出显示端口
  • 本代码实现了由STC89C52模块, GSM移动模块、烟雾传感器、温度...由各传感器采集数据传送至STC89C52单片机,通过单片机控制GSM模块实时将温测数据及火灾警情发送到指定的移动电话上,达到实时监测生活环境的目的。
  • 虽然单片机和TC35I模块都是TTL电平,但是TC35模块输入输出的TTL正电平逻辑不是+5V,而是+2.9V,但是单片机的输入输出的TTL正电平逻辑是+5V,所以如果直接将TC35I的RX,TX与单片机的TX,RX对应连接后,当然也要连接GND...
1 2 3 4 5 ... 20
收藏数 1,549
精华内容 619
关键字:

单片机怎么控制gsm