2010-08-27 02:53:00 crazyleen 阅读数 3281
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3997 人正在学习 去看看 朱有鹏

最近做一个基于GSM的智能家居远程控制系统,花了好多天来完成了pcb板的制作到硬件调试完毕,感觉和那些乱七八糟的元件打交道也别有一番乐趣,硬件昨晚了就开始我的软件编写。由于经验不足,很少做单片机的系统,最初编写GSM模块,再编写其他模块,每个模块多调试完毕后,才开始主控函数的编写,编写的过程中,还不断修改原来模块的代码,不久后又觉得这样的设计不合理,继续改吧,改到何年何月?这个系统刚开始没设计好模块之间的接口,搞得乱七八糟的。后来居然还在一个模块中嵌入另一个模块的细节,还好写了一些后意识到了这个问题的严重性,这样下去的话,不用多久,我所有的代码都乱七八糟了。决心模块与模块之间必须独立出来,一个模块不要混合另一个模块的内容,模块只留下公共接口给外部调用处理,特殊需要时才放到main.c中写,比如我这个系统几个模块都有中断,而中断处理函数中又必须调用其他模块的东西,那我就干脆把模块的中断放到main.c中,而在模块文件中只留下一个函数的副本,当然是注释掉的了。这样我以后查看模块的时候,知道这个函数放到哪里去做什么了。模块之间有条理地界限分明,是很利于日后维护与二次开发的。代码修改的过程中,由于最初的设计不合理,难免会有很大的改动,所以在你完成了一个比较重要的一个部分后,或者说你觉得它是一个进步的时候,立即备份一个,并给予一个编号,比如我就喜欢用beta***的编号表示,呵呵。否则当你做错了一大步后就没得后悔了哦。。。这些天进度还是客观的,很快就可以完成这个设计了。到时候发到博客与大家分享一下吧。决心这个设计完成后就把单片机撇在一边,开始ARM的学习。

总的来说,经验或者教训,就这么几个:

1.三思而后行,先思考各个模块的接口等具体细节,再完成具体模块的各个部分的实现。函数接口很重要,在你开始写模块的代码前,你就需要写好各个函数的声明与功能。然后具体实现它。

2.模块化,模块之间不要发生不明不白的关系,最好不要发生。实在需要就在主函数的那个文件里写吧。刚开始要一个模块一个地独立编写调试,然后再整合真个系统。

3.不是硬件底层的东西,先在界面比较好的环境中实现后,在移植到工程中。这样能加速调试过程。

4..边编写边维护,完成一个重要功能后,立即做好备份,这个是你的里程碑。也有可能是还魂丹。

以上皆是这次设计的一些心得,有对的也有错的,不停改进,不断提高,实现自我价值,加油

2012-06-20 15:50:40 abclixu123 阅读数 1745
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3997 人正在学习 去看看 朱有鹏

最近参加一次校内电子比赛,有个题目就是让做用单片机与GSM的结合实现远程控制,这里的控制是控制两盏220V的灯泡,要求实现单片机的短信的收发。比赛已经完了,这次比赛有学习到不少新东西,写写总结体会(软件方面,因为负责软件部分)。

GSM模块选择的是西门子TC35I,网上它的资料比较多。以前有同学买过这个模块,但是直接用GSM模块的话对比赛成绩有影响,所以我们只是买了TC35I和SIM卡插槽,自己来重新画板子,把ARM与TC25I画在一块板子上。网上关于GSM控制的资料很多,但很多都是用51控制的,所以我们起初的工作就是学习TC35I和将51与GSM的程序移植到ARM上。幸好单从控制GSM上来说,并不是太难,它是基于串口通信的,而且全是基于AT指令的控制,说起来,就只是熟悉下指令,而且这次比赛用到的指令也比较少,主要是关于短消息方面的指令。我们用到的指令如下:

AT&F:设置目前参数为厂商默认值,成功则返回OK。

AT+CREG?:网络注册。成功则返回+CREG:0,1或 +CREG:0,5。错误则返回ERROR。

AT+CMGF=1:设置短信格式为TEXT格式。

AT+CSCA=’+86XXXXXXXXXXX’:发送本地中心号码

AT+CMGS=’XXXXXXXXXXX’:发送目标手机号码

AT+CMGR=n:读取某条短信,n表示第几条短信

AT+CMGD=n:删除某条短信,n表示第几条短信


因为只是简单的进行控制,只需传送ASCII码值。所以我们短信格式设置为了TEXT格式,减轻了编程的负担。

下图就是我们GSM控制方面的软件流程图:


ARM7串口通讯方面的,采用了FIFO接收,8字节触发,有字符超时中断。

下图是TC35I的电路图



另外,本来用ARM就是打算用ucosii完成软件设计的,但是临近比赛也还是没用弄出来,想了好久不知道错在哪里,最后果断放弃,跑裸机。看来,对Ucosii还要继续进行学习,熟练运用它进行编程。





       

2019-01-21 14:30:07 qq_36169781 阅读数 6747
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3997 人正在学习 去看看 朱有鹏

背景:SIM800C模块与服务器建立通讯实现了真正意义上的物联网应用,它突破了WiFi模块只能在固定无线网络范围内的距离局限,或是蓝牙模块的短距离传输瓶颈,我们只需要借助单片机连接GSM模块与电器开关,然后对单片机进行简单的控制逻辑编程。GSM模块只要在有移动网络信号覆盖的环境下就能与控制端进行基于TCP/IP协议的点对点数据传输,从而实现不限距离的远程控制。

本文介绍SIM800C模块通过GPRS与服务器进行串口通信。

设备清单:

  1. USB-TTL调试模块(驱动);
  2. SIM800C模块;
  3. 移动或联通SIM卡(可正常访问网络);
  4. 本地计算机;
  5. 拥有公网IP的远程计算机。

如果没有公网IP,可以在花生壳上付费做地址映射。

模块引脚说明

5V:供电引脚,只能输入DC5V,用于给板子供电。

V_TTL:接目标控制板单片机内核电压的5V/3.3V,TTL逻辑

GND:电源地线

TXD:模块串口发送引脚,TTL电平(不能直接接RS232电平)

RXD:模块串口接收引脚,TTL电平(不能直接接RS232电平)

DTR:数据终端准备

SPKP:内核音频输出引脚

SPKN:内核音频输出引脚

MICN:内核音频输入引脚

MICP:内核音频输入引脚

RI:内核振铃提示引脚

VRTC:RTC外置电池引脚

GND:电源地线

PWX:拉低该引脚可以实现模块的开启或者关闭

GND:电源地线

VBAT:锂电池输入引脚。

模块与电脑连接 ##

使用USB-TTL连接SIM800C然后插入电脑供电,接线如下

USBTTL SIM800C
5V-------VCC
GND------GND
TX-------RX
RX-------TX

USB-TTL 模块驱动,常用于调试TTL电平的串口信息。市面上常见的有 CP2102/PL2303/CH340等USB-TTL模块,推荐使用CP2102模块,是同类模块中性能最好最稳定的。

插入前确保电脑已经安装了USB-TTL调试驱动,在设备管理器中查看对应串口号(COM)

此时,SIM800C模块电源指示灯常亮,但并不会开始工作,前面的引脚介绍中有PWX引脚,我们需要给PWX引脚一个低电平触发来启动模块,从第一张图中可以看到,我用跳线帽将PWX和GND短接,这样每次通电只需拔下跳线帽再插上就可以启动模块。

模块与计算机通信测试

打开串口调试器,选择对应的串口号,波特率建议选择9600,数据位8,停止位1,然后点 “打开串口” 启动串口监听。向COM口发送AT命令。有些串口调试器有“发送新行”功能,一定要勾选上,这样会给每条命令的结尾加上一个换行符,模块才能识别该条命令,由于我用的串口助手没有这个功能,所以我在每条命令的结尾敲一个回车后发送。

模块的波特率可以自适应,即模块上电时候第一个发送的指令是什么波特率,系统会自动识别波特率按照这个波特率返回数据。

发送
AT
收到回复
AT
OK
SMS Ready

此时,模块与计算机的通信正常。

常用AT指令集介绍

AT+CPIN?

该指令用于查询 SIM 卡的状态,如果该指令返回:+CPIN:READY,则表明SIM卡状态正常。

AT+CSQ

该指令用于查询信号质量,返回 SIM800 模块的接收信号强度,最大有效值是31。

AT+COPS?

该指令用于查询当前运营商,该指令只有在连上网络后,才返回运营商,否则返回空,如返回:+COPS:0,0, “CHINA MOBILE”,表示当前选择的运营商是中国移动。

AT+CGMI

该指令用于查询模块制造商。

AT+CGMM

该指令用于查询模块型号。

AT+CGSN

该指令用于查询产品序列号(即IMEI号)。

AT+CNUM

该指令用于查询本机号码。不是所有的SIM卡都 支持这个指令。

ATE1

该指令用于设置回显模式(默认开启),即模块将收到的 AT 指令完整的返回给发送端,启用该功能,有利于调试模式。如果不需要开启回显模式,则发送 ATE0 指令即可关闭,这样收 到的指令将不再返回给发送端,这样方便程序控制。

ATD15002865210;

拨打电话,执行成功后返回ATD:15002865210 OK。

开启公网主机网络端口

我们远程登陆前面准备的公网IP主机,cmd命令netstat -a列出所有网络端口。

找出没有被占用的端口号,这里我选择10005,使用网络调试助手设置协议类型为TCP服务对端口10005进行监听,IP地址默认。

设置防火墙规则:
打开Windows防火墙->高级设置,增加入站规则->端口10005->适用于TCP协议,同时增加10005端口的出站规则。
或者直接关闭防火墙。

回到我们本地计算机的串口助手,接下来我们要使用串口助手给SIM800C发送指令来建立GPRS连接。
下面是我们会用到的GPRS功能指令集与相应功能:

AT+CGCLASS

用于设置移动台类别。SIM800模块仅支持类别"B"和"CC",发送:AT+CGCLASS=“B”,设置移动台类别为B。即,模块支持包交换和电路交换模式,但不能同时支持。

AT+CGDCONT

用于设置PDP上下文。发送:AT+CGDCONT=1,“IP”,“CMNET”,设置PDP上下文标标志为1,采用互联网协议(IP),接入点为"CMNET"。

AT+CGATT

用于设置附着和分离GPRS业务。发送:AT+CGATT=1,附着GPRS业务。

AT+CIPCSGP

用于设置CSD或GPRS链接模式。发送:AT+CIPCSGP=1,“CMNET”,设置为GPRS连接,接入点为"CMNET"。

AT+CLPORT

用于设置本地端口号。发送:AT+CLPORT=“TCP”,“8086”,即设置TCP连接本地端口号为8086。

AT+CIPSTART

用于建立TCP连接或注册UDP端口号。发送:AT+CIPSTART=“TCP”,“222.197.91.22”,“10005”,模块将建立一个TCP连接,连接目标地址为:222.197.91.22,连接端口号为10005,连接成功会返回:CONNECTOK。

AT+CIPSEND

用于发送数据。在连接成功后发送:AT+CIPSEND,模块返回:>,此时可以输入要发送的数据,最大可以一次发送1352字节,数据输入完后,同发短信一样,输入十六进制的:1A(0X1A),启动发送数据。在数据发送完成后,模块返回:SENDOK,表示发送成功。

AT+CIPSTATUS

用于查询当前连接状态。发送:AT+CIPSTATUS,模块即返回当前连接状态。

AT+CIPCLOSE

用于关闭TCP/UDP连接。发送:AT+CIPCLOSE=1,即可快速关闭当前TCP/UDP连接。

AT+CIFSR

查询模块IP

AT+CIPSHUT

用于关闭移动场景。发送:AT+CIPSHUT,则可以关闭移动场景,关闭场景后连接状态为:IPINITIAL,可以通过发送:AT+CIPSTATUS查询。另外,在连接建立后,如果收到:+PDP:DEACT,则必须发送:AT+CIPSHUT,关闭场景后,才能实现重连。

SIM800C 建立与服务器的连接

使用端口助手向SIM800C发送以下命令
查询网络注册情况

AT+CPIN?

查询信号质量

AT+CSQ

查询GSM网络注册状态

AT+CREG?

查询GPRS网络注册状态

AT+CGREG?

使模块附着GPRS网络

AT+CGATT=1

设置透传模式

AT+CIPMODE=1

设置APN=CMIOT

AT+CSTT=CMIOT

激活移动场景,建立无线连接

AT+CIICR

获取模块IP地址

AT+CIFSR

建立TCP连接,连接到IP:222.197.91.22,连接端口为:10005。

AT+CIPSTART=“TCP”,“222.197.91.22”,“10005”

此时SIM800C模块向串口返回CONNECT OK,现在可以进行数据交互,我们通过远程服务器向模块发送“Hello SIM800! This massage from server.” 我们的模块将会成功收到来自服务器的信息。

2016-09-09 17:02:20 cc214042 阅读数 4515
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3997 人正在学习 去看看 朱有鹏
本文以一个实例来解说AT指令发送PDU短信的全过程,假如我要发送下面的短信: 
接收号码:+8613602433649 
短信内容:工作愉快! 
杭州短信中心号码:
联通:+8613010360500
移动:+8613800571500
一、短信中心号码处理:用字符串 addr 表示 
1、将短信息中心号码去掉+号,看看长度是否为偶数,如果不是,最后添加F 
即 addr = "+8613800200500" 
=> addr = "8613800200500F" 
2、将奇数位和偶数位交换。 
=> addr = "683108020005F0" 
3、将短信息中心号码前面加上字符91,91是国际化的意思 
=> addr = "91683108020005F0" 
4、算出 addr 长度,结果除2,格式化成2位的16进制字符串,16 / 2 = 8 => "08" 
=> addr = "0891683108020005F0"
二、手机号码处理:用字符串 phone 
1、将手机号码去掉+号,看看长度是否为偶数,如果不是,最后添加F 
即 phone = "+8613602433649" 
=> phone = "8613602433649F" 
2、将手机号码奇数位和偶数位交换。 
=> phone = "683106423346F9"
三、短信息部分处理:用字符串 msg 表示 
1、转字符串转换为Unicode代码,例如“工作愉快!”的unicode代码为 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
五、所以要发送的内容为
 //PDU格式发送
AT+CMGF=0 <回车>//格式选择,PDU
OK 
AT+CMGS=25<回车> //信息长度
> addr+phone <Ctrl+Z发送>//发送完PDU编码之后,在不回车的情况下以Hex的格式发送0x1A
//文本格式发送
AT+CMGF=1 <回车>//格式选择,文本
OK 
AT+CMGS=+86139xxxxxxxx<回车> //输入手机号
>ABCD1234(短信信息,回车)
hex格式下发送0x1A 
注意点:格式选择和信息发出后的换行操作
六、PDU格式在线转换链接:
http://www.multisilicon.com/blog/a22201774~/pdu.htm    

2013-09-23 14:51:37 jzj1993 阅读数 14928
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3997 人正在学习 去看看 朱有鹏

GSM/GPRS芯片是手机中负责收发短信、拨打电话以及访问GPRS网络的核心器件。有方M660+为深圳有方公司生产的一款超小封装的GSM/GPRS工业无线模块,可以提供高品质的语音、短信、数据业务等功能,在各种工业和民用领域得到广泛的应用。

有方M660+ GPRS模块的硬件设计

硬件设计参考附件《M660+ 硬件设计指南》。

需要注意的几点:

  1. 模块工作电压为3.5V~4.3V(推荐值3.9V),不是5V。

  2. 模块平时工作电流较小,但是在模块注册网络或者其他一些特殊情况下,电流可能瞬间达到1.8A,如果电源供电能力不足,电压瞬间下降严重,将可能导致模块工作异常,没有信号,无法收发短信等情况。建议采用大电流的开关电源芯片供电,如LM2596 DC-DC转换模块;对于移动式设备,采用一块3.7V锂离子电池则刚好可以满足要求;另外应在GPRS模块供电端附近增加大电容滤波,滤波电容大小见硬件设计指南。

    • 瞬间电流Max 1.8A
    • 平均工作电流 <300mA
    • 待机电流1.5mA typ

  3. 该模块使用3.3V 电平串口,即高电平为3.3V,不是5V,对于5V电平的单片机或TTL串口,为保证工作可靠,不至于烧坏芯片,最好按照硬件设计指南中电路图搭建电平转换电路。

单片机系统的硬件设计

通常使用较多的单片机有51、AVR、MSP430、STM32等。需要根据系统功能,考虑选择合适的单片机。

51单片机使用5V电平,且多数型号RAM、ROM较小,运行速度较慢,适合做一些较简单的应用,优点是简便易学,且焊接容易(很容易买到使用DIP(直插式)封装的51单片机)。

430单片机使用3.3V电平,与GPRS模块能很好的兼容,且配置相比51更好,最大的特点是低功耗,且性价比较高,适合做不需要处理大量数据(如多媒体信息处理,复杂的人机交互)的多数应用。缺点是大部分430采用贴片封装,不易于焊接,且使用不当容易烧坏芯片。

STM32单片机基于ARM7内核,功能强大,功耗较低,性价比很高,但对于只接触过51一类单片机的人来说,不一定能很好的掌握,因为正是由于功能强大,导致其程序庞大,一些比较简单的应用不需要使用STM32。STM32适合开发一些需要处理一些图片、音频,以及用户可视化交互的系统。

总体来说,推荐优先选用MSP430;如果应用比较简单,可使用51;如果需要一些较为复杂的数据处理,尤其是多媒体信息,可考虑使用STM32、ARM9及以上处理器,或者结合FPFA、DSP来实现。

有方M660+ GPRS模块的软件设计

从硬件层面来说,有方GPRS模块仅仅涉及了串口通信,硬件层的编程比较容易。初次接触GPRS模块编程时,比较难的是面向AT指令集协议编程(尤其是字符串处理很麻烦),以及如何编写高效,而又可靠健壮的程序。

AT指令集是一种可用于GSM/GPRS模块的通信协议。何谓协议?举个简单的例子,我们说话过程中使用的语言,作为大家共同接受的标准,可以在我们之间传递信息,这就叫做协议。而串口则是一种接口,接口又是什么呢?接口就是收发信息的实现,我们的嘴巴和耳朵就相当于接口。

接口和协议又有什么关系呢?串口作为接口,只能一个字节一个字节的传输字符,类似的,我们的嘴巴和耳朵原本也只能收发不同的声音。接口是具体实现,而协议则规定了接口传输的信息代表什么含义。如果没有接口,协议肯定没法实现,人没有嘴巴和耳朵是没法用声音交流的。另一方面,如果没有协议,或者协议不兼容,接口的实现也并不能代表什么含义。没有语言的话,两个人只是乱叫完全没法交流;如果两个人使用不同的语言,而且听不懂彼此的语言(相当于协议不兼容),也是同样不能交流的。

在GPRS模块软件的开发中,接口的实现远比协议实现要简单。接口的实现在这里就不做介绍,这里主要探讨如何编写高效可靠的程序来实现GPRS模块的协议即AT指令集。

完整的AT指令集请参考附件《AT命令手册》,这里只介绍一些基本用法。

AT指令集的学习

要想编写程序实现AT指令集的功能,就应该先学习AT指令集。如何学习AT指令集呢?一些人会直接给单片机写程序去控制GPRS模块的方式学习。事实上,这样很难学好AT指令集,往往会出现各种错误。当你对AT指令集不了解的情况下,盲目的去写程序,而又并不能保证程序没有错误按设想运行(如果你能保证这一点,那么你就是编程经验非常丰富的高手了,反正我是做不到这一点),这样的情况下,实验失败时,你根本没法确定是程序的问题还是AT指令集的问题,甚至有可能是硬件问题等等。

于是,一般我们将GPRS模块连接到计算机上来学习AT指令集。对于大多数没有串口的计算机,你需要有个USB转TTL串口的转接线,即使有RS232串口,也需要通过一些转接芯片进行电平转换,转换成TTL串口。注意GPRS模块TTL串口的电平为3.3V,尽量使用电平转换电路以免电平不兼容烧坏GPRS模块。同时,你需要设计好GPRS模块的供电电路,给其提供一个稳定可靠的电压。然后插上一张可用的手机SIM卡,连接好电源和串口,GPRS模块上电后会和手机开机一样,需要数分钟的时间搜索信号,然后就可以正常工作。

电脑端我们使用串口超级终端软件来调试GPRS模块。

当我们从超级终端给GPRS模块发送“AT”,并按回车时,如果一切正常,屏幕上会显示返回的“OK”字符,这就是AT指令集最基本的操作:确认AT指令集工作正常。

通过AT指令集初始化GPRS模块一般包括以下步骤(前面加“--”符号的表示正常工作返回的字符串,不同模块不完全一样,仅供参考,//表示注释):

  1. AT // 确认AT指令集工作正常
  2. --OK
  3. ATE0 // 关闭回显(即禁止GPRS模块发送接收到每一个的字符,在电脑上调试时不需此语句)
  4. --OK
  5. AT+CPIN // SIM卡准备好?
  6. --READY
  7. AT+CMGF=1 // 设置短消息格式为Text模式,需在模块上电一段时间后才能正常返回OK,在此之前会返回ERROR
  8. --OK
  9. AT+CSMP=17,167,0,0 // 设置Text模式参数,用于短信发送
  10. --OK
  11. AT+CSCS="GSM" // 设置GSM字符集,用于短信发送
  12. --OK
  13. AT+CREG? // 网络注册完成?应该一直循环发送此句直到网络注册完成才能进行短信和电话操作,如果没有信号,也会返回错误信息
  14. --+CREG: 0, 1, "341B", "2DBF"

如果需要使用GPRS网络,也可以在此处初始化,或者在需要使用时才初始化。

写程序时发送这些字符串要注意,在每一句结尾处应有一个"\r"结束标志(回车符,ASCII码中的13,常缩写为)。对于大部分指令,GPRS模块接收到此结束符才会执行指令。另外有些引号不可省略,在写程序时应写为转义字符。

网络注册正常后,发送ATD10086,就会给10086打电话,返回OK说明正在尝试拨打,拨号成功或没有信号会返回相应字符串。拨号成功,如果连接了话筒和耳机,就能正常通话了。

发送短信有两种方式,一种是TEXT模式,另一种是PDU模式,需要先设置好。其中TEXT模式只支持英文(不排除可能有些模块或者某些特别的方法能使其支持中文),PDU模式支持中文,但编码方式较为复杂。

PDU可参考:http://yuanyu5237.iteye.com/blog/1126185

注:文中提到一个字符ASCII码中的26(0x1A),在超级终端中可通过Ctrl+Z输入

AT指令集协议的编程实现

要编写一个高效而又可靠的程序,我们既要向GPRS模块发送数据,又需要接收返回的数据并判断返回值是否正确。

发送数据可以调用串口发送函数直接发送,而接收数据时,需要接收一段完整的字符串。由于单片机可能正在处理其他任务,并不一定能马上响应接收的指令。编程时我们可以使用环形队列作为串口接收缓冲区,并在接收到"\r"结束符时置位一个接收标志,然后等待CPU处理。对于一些特殊情形,返回值并不是以"\r"结束,比如发送短信提示输入短信内容时是以">"结束,此时可以通过延时等待并不断查询的方式判断是否接收到正常的返回值。

还有一种通过超时判断是否接收完一条指令的方法,效果相对比较好。当接收到第一个字符时,启动定时器计时,如果一定时间内接收到下一个字符,清零定时器,再次重新计时……当接收到某个字符之后,计时到超过一定时间仍未收到下一个字符,表明接收完一条指令。因为返回的每条指令都是连续发送出来的,间隔时间固定,所以这种方式能准确判断指令是否接收完成,缺点是会占用更多硬件资源(需要多用一个定时器)。

为了充分实现代码复用,加快程序开发,可以考虑实现这样几个函数:

  1. // 字符串复制(可使用string.h中的标准函数)
  2. void StrCopy(char*, char*);
  3. // 判断一个字符串是否包含另一个字符串
  4. unsigned char StrContain(char*, char*);
  5. // 发送指令并等待返回指定字符串。注意如果超时仍未返回指定字符串,则应退出函数,以免死机
  6. unsigned char SendAndGet(char*, char*);
  7. // 发送指令并等待返回指定字符串,尝试n次
  8. unsigned char SendAndGetTimes(char*, char*, unsigned char);
  9. // 初始化AT指令集设备,返回初始化是否成功结果
  10. unsigned char AT_Init(void);
  11. // 发送短信,并返回发送是否成功标志
  12. unsigned char SendMsg(char*, char*);
  13. // 检测模块当前是否有信号
  14. unsigned char CheckSignal(void);

一些更复杂的问题

当先后间隔很短时间发送多条指令,或者是前一条指令需要GPRS模块使用较长时间去响应时,情况就变得比较复杂了。比如说,我们给出指令发送一条短信,一般可能在10秒左右时间发完,然后返回OK。而在返回OK之前,如果又需要发送另外一条指令,或者很不幸有人打电话来,处理起来就很麻烦了。再比如在间隔很短时间内接收到多条消息,前一条正在处理,后一条消息又被接收到,这个时候怎么保证不遗漏消息呢?我们可以考虑使用队列来解决这个问题。

类似这样的问题很多,尤其对于速度低存储空间小的单片机来说也不太好解决,而对于一些简单应用也不一定要考虑这么多情况,本文不做详细探讨。

附件

串口超级终端 http://download.csdn.net/detail/jzj1993/5744509
有方M660+硬件设计指南 http://download.csdn.net/detail/jzj1993/5507753
AT命令手册 http://download.csdn.net/detail/jzj1993/5507747

没有更多推荐了,返回首页