GSM/GPRS/3G/4G
1、状态机机制的gprs拨号
像GPRS/3G模块之类的应用,需要连接,登陆,初始化等步骤完成后才能传输数据,而这些步骤又比较耗时。
所以用 状态机 + 超时 的机制来实现比较合理。
如下代码片段来描述数据透传 : 状态机 + 超时 这种机制(代码片段,仅用来描述一种思路)
以下程序是在没有操作系统调度机制下调试的,所以超时用的心跳,如果是linux下,有sleep更方便。
#include <stdio.h> #include <string.h> #include <stdlib.h> #define SERVER_IP "115.29.140.xxx" #define SERVER_PORT "8082" #define BUFF_LEN 64 char aUart5RxBuffer[BUFF_LEN]; static int gprs_init_ok= 0; static int ppp_config_ok = 0; void gprs_init(void) { if((strstr(aUart5RxBuffer, "command ready") == NULL) /*||(strstr(aUart5RxBuffer, "+SIM READY") == NULL)*/) { gprs_init_ok = 0; } else { gprs_init_ok = 1; } } void reset_gprs(void) { memset(aUart5RxBuffer, 0, BUFF_LEN); gprs_init_ok= 0; ppp_config_ok = 0; //reset 3g module; } void ppp_config(void) { static uint32_t ppp_config_step = 0; static uint32_t gprs_tick = 0; switch (ppp_config_step) { case 0: gprs_puts("AT+GTSET=\"LPMMODE\",0\r\n"); gprs_tick = msTicks; ppp_config_step = 1; break; case 1: if((msTicks - gprs_tick) > 500) { if(strstr(aUart5RxBuffer, "OK") == NULL) { ppp_config_step = 0; } else { ppp_config_step = 2; } memset(aUart5RxBuffer, 0, BUFF_LEN); } break; case 2: gprs_puts("AT+CPIN?\r\n"); ppp_config_step = 3; gprs_tick = msTicks; break; case 3: if((msTicks - gprs_tick) > 500) { if((strstr(aUart5RxBuffer, "OK") == NULL) || (strstr(aUart5RxBuffer, "+CPIN: READY") == NULL)) { ppp_config_step = 2; } else { ppp_config_step = 4; } memset(aUart5RxBuffer, 0, BUFF_LEN); } break; case 4: gprs_puts("AT+CSQ\r\n"); ppp_config_step = 5; gprs_tick = msTicks; break; case 5: if((msTicks - gprs_tick) > 500) { if(strstr(aUart5RxBuffer, "OK") == NULL) { ppp_config_step = 4; } else { ppp_config_step = 6; } memset(aUart5RxBuffer, 0, BUFF_LEN); } break; case 6: gprs_puts("AT+CREG?\r\n"); ppp_config_step = 7; gprs_tick = msTicks; break; case 7: if((msTicks - gprs_tick) > 500) { if(strstr(aUart5RxBuffer, "+CREG: 0,0") == NULL) { ppp_config_step = 8; } else { ppp_config_step = 6; } memset(aUart5RxBuffer, 0, BUFF_LEN); } break; case 8: //gprs_puts("AT+MIPCALL=1,\"3GNET\"\r\n"); gprs_puts("AT+MIPCALL=1,\"xagfzqx.ydoa.snapn\"\r\n"); ppp_config_step = 9; gprs_tick = msTicks; break; case 9: if((msTicks - gprs_tick) > 3000) { if(strstr(aUart5RxBuffer, "+MIPCALL: 0") == NULL) { ppp_config_step = 0; ppp_config_ok = 1; } else { ppp_config_step = 8; } memset(aUart5RxBuffer, 0, BUFF_LEN); } break; default: break; } } void http_Send_test(char *data) { static unsigned char http_send_step = 0; static int send_err_cnt = 0; switch (http_send_step) { case 0: memset(data_tx_buf, 0, sizeof(data_tx_buf)); strcat(data_tx_buf, data); gprs_puts("GET /app/pulse-wave/commit?"); gprs_puts("%s",data_tx_buf); gprs_puts("\r\n"); http_send_step = 1; gprs_tick = msTicks; break; case 1: if((strstr(aUart5RxBuffer, "{\"msg\":\"commit pulse-wave data success.\",\"result\":true}") != NULL) &&(strstr(aUart5RxBuffer, "+MIPSTAT: 1,1") != NULL) &&((msTicks - gprs_tick) < 1000)) { } else { if(++send_err_cnt > 3) { reset_gprs(); send_err_cnt = 0; } }
memset(aUart5RxBuffer, 0, BUFF_LEN);
http_send_step = 0; break; default: break; } } void main(void) { while(1) { if(!gprs_init_ok) { gprs_init(); } if((gprs_init_ok)&&(!ppp_config_ok)) { ppp_config(); } if(ppp_config_ok) { http_Send_test("hello,world"); } } }
初始化成功了就可以传输数据了,数据发送和接收都跟串口一样。主要工作都在初始化 ,和异常修复机制的实现。因为网络传输每一步都可能会失败,而且外部因素太多,所以异常修复机制尤其重要。
2、用开源的ppp/pppoe指令拨号也一样
ppp
https://download.samba.org/pub/ppp/
pppoe
https://www.roaringpenguin.com/products/pppoe
eg:
https://blog.csdn.net/a746742897/article/details/52421461
1) 3g
https://blog.csdn.net/qq_21792169/article/details/51271833
https://blog.csdn.net/yangzheng_yz/article/details/9315287
2) 4g
https://www.cnblogs.com/cryhuang/p/5649372.html
http://blog.sina.com.cn/s/blog_7880d3350102wb92.html
3g/4g一样的
end