微控制器的GPRS无线上网方案
其中GPRS模块与微控制器间是通过串行口进行通信的,通信速率最快可以达到115 200b/s。模块与控制器间的通信协议是AT命令集,其中大部分命令是符合协议“AT command set for GSM Mobile Equipment (ME) (GSM 07.07 version 6.4.0 Release 1997)”的,但也有一些是Wavecom自己定义的AT命令。除了串口发送(TX)、串口接收(RX)之外,微控制器与GPRS模块之间还有一些硬件握手信号,如DTR、CTS、DCD等。为了简化微控制器的控制,硬件设计时没有使用全部的硬件握手信号,而只使用数据载波检测(Data Carrier Detect, DCD)和终端准备(Data Terminal Ready, DTR)信号。DCD信号可以检测GPRS模块是处于数据传送状态还是处于AT命令传送状态。DTR信号用来通知GPRS模块传送工作已经结束。本文引用地址://m.amcfsurvey.com/article/157972.htm
硬件连接完成后,在进行GPRS上网操作之前,首先要对GPRS模块进行一定的设置。主要的设置工作有:① 设置通信波特率,可以使用AT+IPR=38400命令,把波特率设为38 400b/s或其它合适的波特率,默认的通信速度为9600b/s。② 设置接入网关,通过AT+ CGD CONT=1, “IP”, “CMNET”命令设置GPRS接入网关为移动梦网。③设置移动终端的类别,通过AT+CGCLASS=“B”设置移动终端的类别为B类,即同时监控多种业务;但只能运行一种业务,即在同一时间只能使用GPRS上网,或者使用GSM的语音通信。④ 测试GPRS服务是否开通,使用AT+CGACT=1,1命令激活GPRS功能。如果返回OK,则GPRS连接成功;如果返回ERROR,则意味着GPRS失败。这时应检查一下SIM卡的GPRS业务是否已经开通,GPRS模块天线是否安装正确等问题。(其它相关的AT命令请参阅文献3。)
中国移动在GPRS与Internet网中间建立了许多相当于ISP的网关支持节点(GGSN),以连接GPRS网与外部的Internet网。GPRS模块可以通过拨“*99***1#”登录到GGSN上动态分配到Internet网的IP地址。其间GPRS模块与网关的通信要符合点对点协议(Point to Point Protocol, PPP),其中身份验证时用户名、密码都为空。使用PPP协议登录上之后,就可以通过GGSN接上Internet了。
3 软件整体结构
3.1 软件层次结构
程序中的所有代码都是由C语言编写的,并采用分层的结构,从底到上分别为:串口驱动层、GPRS模块驱动层、PPP协议层、IP协议层、UDP协议层与应用层。上层函数的实现需要应用到底层函数,而底层函数的任务就是为上层函数提供服务,最终完成应用层任务――传送数据。各层的主要函数如图2所示。
图2 软件层次结构
3.2 驱动程序编写
首先是串行口驱动层。它实现打开串口(OpenComm)、关闭串口(CloseComm)、读串口数据(ReadComm)、写串口数据(WriteComm)等函数。例如WriteComm函数向串口发送一个字节的数据,而transmit函数向串口发送一个字符串的数据:
void WriteComm(char c){
ES = 0;
SBUF = c;
while(TI==0);
TI=0;
ES = 1;
}
void transmit (char *data) {
Delay (250);
while (*data) {
WriteComm (*data++);
}
}
然后,在这些串口函数的基础上编写GPRS模块的驱动函数。微控制器通过串行口控制GPRS模块,进行拨号、设置等操作。控制的方法是采用AT命令。在控制GPRS模块拨打移动梦网GGSN的登录号码“*99***1#”之后,GPRS模块就转入在线模式(On-Line)。此时微控制器向串行口发送的所有数据都透明地传送给了GGSN,同样GGSN的回答也传回单片机的串行口。当数据传送完成后,微控制器需要通知GPRS模块结束会话,并从在线模式转回普通的命令模式,这可以通过置高DTR线完成。同时,如果线路由于异常断开,CD线会回复到平常的低电平,所以处于在线模式下也要不断检测CD线是否处于高电平。根据这些操作,可以编写GPRS驱动函数:初始化GPRS模块函数(GPRSInit)、拨号函数(GPRSDial)、断开连接函数(GPRSHangup)、检测是否处于在线状态函数(GPRSOnline)。其中,GPRS的拨号和挂断代码如下:
BYTE GPRSDial (void) {
signed char delayCount = 80;
transmit (ATV0r); // 要求返回数字表示的回答
if (!Waitfor (0, 30)) { // 等待 OK 回答
return -1;
}
DTR_ON;
transmit (ATD*99***1#r); // 拨GGSN的号码
GPRSBuffFlush (); // 清空buffer
// 等待回答
while ((!GPRSBuffNotEmpty()) (--delayCount > 0)) {
Delay (250);
}
if (delayCount) {
return GPRSGetch (); // 返回回答的数字
}
return -1; // 没有返回,错误
}
void GPRSHangup (void) {
DTR_ON; // 置高DTR
Delay (40); // 保持一定时间
DTR_OFF; // 完成连接的断开
}
这些底层的驱动函数将会使上层协议的编写很方便,更重要的是,它为我们提供了一个驱动抽象层。当底层硬件做出改动的时候,只需要对底层的驱动函数进行改动,而上层函数的代码不变。
评论