AT指令控制GSM/GPRS模块上网连接服务器

现在已经是3G、4G的天下,但古老的GSM模式中有一个GPRS数据承载服务,是在2G网络下对上网需求的优化。

GSM和GPRS

GSM是全球移动通讯系统Global System of Mobile communication,分属于2G通信。

GPRS是Gerneral Packer Radio Service的英文缩写,中文译为通用无线分组业务,具体来讲,GPRS是一项高速数据处理的科技,即以分组的“形式”把数据传送到用户手上。

GPRS是在GSM系统上发展出来的一种新的承载业务,目的是为GSM用户提供分组形式的数据业务。GPRS采用与GSM同样的无线调制标准、频带、突发结构、跳频规则以及同样的TDMA帧结构。

GPRS允许用户在端到端分组模式下发送和接收数据,而不需要利用电路交换模式的网络资源,从而提供了一种高效、低成本的无线分组数据业务。

AT指令控制

部分GPRS模块内置了TCP/IP协议栈,可以很方便的通过厂家扩展的AT指令直接进行TCP或UDP通信。

这是在RTOS(RT-Thread Operating System)里面的一段控制Zigbee模块用GPRS通信方式和服务器通信的代码:

<!-- lang: cpp -->
void thread_gsm_entry(void *parameter)
{
uint16_t i = 0;

gsm_init_hw("uart3");

rt_kprintf("gsm init hardware success \n");

thread_gsm_at = rt_thread_create("gsm_at",
                                 thread_gsm_at_entry, RT_NULL,
                                 1024,
                                 10, 10);

if (thread_gsm_at != RT_NULL)
{ rt_thread_startup(thread_gsm_at); }

gsm_power_switch();
rt_thread_delay(RT_TICK_PER_SECOND * 7);

for (i = 0; i < 5; i++)
{
    rt_device_write(gsm_dev, 0, "AT\r\n", strlen("AT\r\n")); //测试连接是否正确
    rt_thread_delay(RT_TICK_PER_SECOND * 1);
}

for (i = 0; i < 1; i++)
{
    rt_device_write(gsm_dev, 0, "ATE1\r\n", strlen("ATE1\r\n")); //打开回显
    rt_thread_delay(RT_TICK_PER_SECOND * 1);
}

for (i = 0; i < 5; i++)
{
    rt_device_write(gsm_dev, 0, "AT+CSQ\r\n", strlen("AT+CSQ\r\n")); //检查信号
    rt_thread_delay(RT_TICK_PER_SECOND * 1);
}

for (i = 0; i < 5; i++)
{
    rt_device_write(gsm_dev, 0, "AT+CGREG?\r\n", strlen("AT+CGREG?\r\n"));//获取小区环境
    rt_thread_delay(RT_TICK_PER_SECOND * 1);
}

for (i = 0; i < 1; i++)
{
    rt_device_write(gsm_dev, 0, "AT+CGATT?\r\n", strlen("AT+CGATT?\r\n"));
    rt_thread_delay(RT_TICK_PER_SECOND * 3); //激活
}

for (i = 0; i < 1; i++)
{
    rt_device_write(gsm_dev, 0, "AT+CSTT\r\n", strlen("AT+CSTT\r\n"));
    rt_thread_delay(RT_TICK_PER_SECOND * 5);
}

for (i = 0; i < 1; i++)
{
    rt_device_write(gsm_dev, 0, "AT+CIICR\r\n", strlen("AT+CIICR\r\n"));
    rt_thread_delay(RT_TICK_PER_SECOND * 5);
}

for (i = 0; i < 1; i++)
{
    rt_device_write(gsm_dev, 0, "AT+CIFSR\r\n", strlen("AT+CIFSR\r\n"));
    rt_thread_delay(RT_TICK_PER_SECOND * 1);
}

rt_device_write(gsm_dev,
                0,
                "AT+CIPSTART=\"TCP\",\"202.201.1.49\",12345\r\n",
                strlen("AT+CIPSTART=\"TCP\",\"202.201.1.49\",12345\r\n"));
rt_thread_delay(RT_TICK_PER_SECOND * 5);

rt_device_write(gsm_dev, 0, "AT+CIPSEND=6\r\n", strlen("AT+CIPSEND=6\r\n"));
rt_thread_delay(RT_TICK_PER_SECOND * 3);

rt_device_write(gsm_dev, 0, "DEMO\r\n", strlen("DEMO\r\n"));
rt_thread_delay(RT_TICK_PER_SECOND * 5);

gsm_inited = RT_TRUE;
}

AT指令步骤和作用

AT指令的步骤和作用如下所示:

  1. AT 测试连接是否正确
  2. ATE1 打开回显
  3. AT+CSQ 返回值是信号质量,越大越质量越好。
  4. AT+CGREG 可以查询GPRS状态 一般注册上运营商,附着GPRS都是自动进行 查询模块是否有注册网络
  5. AT+CGATT 开机后,如果“AT+CGATT?”命令的返回值为1,说明SIM卡已经开通了GRPS服务
  6. AT+CSTT 设置APN
  7. AT+CIICR 激活移动场景
  8. AT+CIFSR 获得本地IP地址
  9. AT+CIPSTART="TCP","202.201.xx.xx",12345\r\n 建立TCP连接
  10. AT+CIPSEND=6 开始发送数据,数据长度为6
  11. 发送测试数据“DEMO\r\n”

服务器端

服务器采用CentOS操作系统,安装JVM。因为GPRS来的数据是TCP报文格式,可以采用Socket编程进行接收,接收到的数据可以插入到数据库中进行保存。这样就可以保存和检索传感器节点的采样数据。

Server端代码采用Java编写,很容易。


 import java.net.*;
import java.io.*;
public class Server
{
private ServerSocket ss;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Server()
{
try
{
ss = new ServerSocket(12345);
socket = ss.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
while (true)
{
String line = in.readLine();
System.out.println("Monitoring data :" + line);
//out.close();
// in.close();
//socket.close();
}
ss.close();
}
catch (IOException e)
{}
}
public static void main(String[] args)
{
new Server();
}
}

需要注意的是千万不要使用out.println,可能会阻塞通信。

socket = ss.accept()要放在while循环外面持续接收数据。

也不要关闭socket和in输入流。Zigbee传来的数据是一个每隔3S的数据流。

在此输入图片描述

RTOS简介[1]

RT-Threayd RTOS是一款来自中国的开源实时操作系统,由国内一些专业开发人员开发、维护。它不仅仅是一款高效、稳定的实时核心,也是一套面向嵌入式系统的软件平台,覆盖了全抢占的实时操作系统内核,小巧而与底层具体实现无关的文件系统,轻型的TCP/IP协议栈以及轻型的多窗口多线程图形用户界面。

RTOS应用

这个例子里面有三个任务(进程):一个是DEMO进程,一个是RF进程,一个是GSM进程。我们看看任务的写法:

<!-- lang: cpp -->
//设置和DEMO进程相关的堆栈、数据结构和声明相关的函数
ALIGN(RT_ALIGN_SIZE)  //DEMO线程,点灯线程
static rt_uint8_t demo_stack[ 2048 ];
static struct rt_thread thread_demo; 
extern void thread_demo_entry(void *parameter);

ALIGN(RT_ALIGN_SIZE)  //RF线程,接收Zigbee分节点的数据,通过GPRS与Server Socket通信
static rt_uint8_t rf_stack[ 2048 ];
static struct rt_thread thread_rf;
void thread_rf_entry(void *parameter);

ALIGN(RT_ALIGN_SIZE)  //GSM线程,初始化GSM设置,初次通信,发送“DEMO”字符。
static rt_uint8_t gsm_stack[ 2048 ];
static struct rt_thread thread_gsm; 
void thread_gsm_entry(void *parameter);

int rt_application_init(void)
{
rt_err_t result;

/* init demo thread */
result = rt_thread_init(&thread_demo,
                        "demo",
                        thread_demo_entry,
                        RT_NULL,
                        (rt_uint8_t*)&demo_stack[0],
                        sizeof(demo_stack),
                        30,
                        5);
if (result == RT_EOK)
{
    rt_thread_startup(&thread_demo);
}

/* init rf thread */
result = rt_thread_init(&thread_rf,
                        "rf",
                        thread_rf_entry,
                        RT_NULL,
                        (rt_uint8_t*)&rf_stack[0],
                        sizeof(rf_stack),
                        10,
                        5);
if (result == RT_EOK)
{
    rt_thread_startup(&thread_rf);
}

/* init gsm thread */
result = rt_thread_init(&thread_gsm,
                        "gsm",
                        thread_gsm_entry,
                        RT_NULL,
                        (rt_uint8_t*)&gsm_stack[0],
                        sizeof(gsm_stack),
                        20,
                        5);
if (result == RT_EOK)
{
    rt_thread_startup(&thread_gsm);
}
 return 0;
}

核心收据收发

<!-- lang: cpp -->
if (gsm_inited)
        {
            rt_device_write(gsm_dev, 0, "AT+CIPSEND=", strlen("AT+CIPSEND="));
            rt_device_write(gsm_dev, 0, num_temp, strlen(num_temp));
            rt_device_write(gsm_dev, 0, "\r\n", strlen("\r\n"));

            rt_thread_delay(RT_TICK_PER_SECOND * 1);

            rt_device_write(gsm_dev, 0, data_temp, strlen(data_temp));

            rt_thread_delay(RT_TICK_PER_SECOND * 3);
        }

其中gsm_inited在GSM线程中被置位(gsm_inited = RT_TRUE),表明模块调试和初始化完毕,开始收发数据。

这是在RF线程(任务)中写的数据核心收发程序,data_temp中存储的是节点发来的数据, rt_device_write(gsm_dev, 0, data_temp, strlen(data_temp))使得数据传到服务器上。

Reference

[1].http://www.rt-thread.org/

[2].http://www.linuxidc.com/Linux/2012-09/69974.htm

你可能感兴趣的:(AT指令控制GSM/GPRS模块上网连接服务器)