如今已是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##