如今已是3G、4G的天下,但古老的GSM模式中有一个GPRS数据承载服务,是在2G网络下对上网需求的优化。java
##GSM和GPRS## GSM是全球移动通信系统Global System of Mobile communication,分属于2G通讯。linux
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指令的步骤和做用以下所示:app
##服务器端##socket
服务器采用CentOS操做系统,安装JVM。由于GPRS来的数据是TCP报文格式,能够采用Socket编程进行接收,接收到的数据能够插入到数据库中进行保存。这样就能够保存和检索传感器节点的采样数据。
Server端代码采用Java编写,很容易。
<!-- lang: 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##