MC20 模块是一款集成了高性能GNSS 引擎和四频段GSM/GPRS 引擎的多功能无线模块,本次在项目中使用MC20作为通信网关,开发其与服务器通信的功能以及定位功能,稍微学习了一下。
1.硬件部分
GSM/GPRS 部分主要特性:
MC20模块本身集成度较高,如果仅仅是使用的话其实非常简单,只需要了解模块内部的AT指令便可。
MC20和STM32的接口采用UART,MC20上面有3个串口,分别用不同的功能,但我们项目的硬件设计把GPRS和GPS的串口都设计在了一起,因此只使用一个串口便可以实现通信与定位的功能。
硬件不多讲,直接下载官方的手册参照设计即可,如果自己找不到手册,可以联系留下邮箱。
2.驱动部分
初始化:
MC20的初始化总体而言分为两个大部分:1.GRRS初始化 2.GPS初始化
首先解释GPRS初始化:
GPRS的初始化分为以下6个步骤:
1.模块硬件检查
2.SIM状态检查
3.网络状态检查
4.GPRS信号强度检查
5.TCPIP传送模式选择
6.建立TCP链接
所谓硬件检查,按照手册上描述,其实就是检查一下硬件有没有正常启动,在已经给电,并且通过脉冲激活了MC20的情况下,使用串口向MC20发送一个字符串“AT\r”。
发送字符串以后,会存在3种状态,1.什么也没收到 2.收到“OK” 3.收到其他字符串。
有且只有在第二种的情况下才代表通信正常,由于STM32与MC20的通信几乎都是这种一问一答的模式,因此特地做一个函数来进行这个工作的处理。
函数功能:使用串口发送一个字符串:AT_CMD,然后等待,在wait_time_ms时间内如果串口有信息返回,那么就进行判断,判断返回信息中是否包含自己需要的字符串:return_value,如果有返回TRUE,如果没有返回FALSE。
1 uint8_t MC20_SendAtCmd(char *AT_CMD, char *return_value, uint32_t wait_time_ms) 2 { 4 uint32_t time; 5 uint8_t res; 6 7 if(NULL == AT_CMD) 8 { 9 return 0; 10 } 11 12 MC20_ClearFlag(); 13 /* 发送命令 */ 14 MC20_SendData((uint8_t *)AT_CMD, strlen(AT_CMD)); 15 if(NULL == return_value) 16 { 17 return 1; 18 } 19 20 time = u32SysTime; 21 /* 延时溢出 */ 22 while(u32SysTime-time < wait_time_ms) 23 { 24 /* 收到模块返回信息 */ 25 if(1 == sMC20Rev.flag) 26 { /* 比较接收到的字符串 */ 29 res = Search_Str((uint8_t *)&sMC20Rev.buf[sMC20Rev.read], sMC20Rev.len,(uint8_t *)return_value, strlen(return_value)); 30 MC20_ClearFlag(); 31 if(1 == res) 32 { 33 return 1; 34 } 35 } 36 37 } 38 39 return 0; 40 }
参数AT_CMD:STM32向MC20发送的命令(字符串)
参数return_value:如果一切正常,那么MC20应该返回的命令(字符串)
参数wait_time_ms:延时时间(毫秒级别,使用系统滴答时钟)
函数功能:使用串口向MC20发送一个指令,然后等待MC20返回应答,在规定的时间内如果接收到了希望的命令,那么返回TURE,否则返回FALSE。
函数MC20_ClearFlag的功能是清空一些flag,等MC20的串口中断收到数据以后,会置位这些flag。
函数MC20_SendData的功能仅仅是包装了一下串口发送的函数。
函数Search_Str的功能仅仅是检查第一个字符串中是否包含第二个字符串的内容,可以简单的理解为比较,这样做是因为MC20返回的信息有时并不单纯,很多时候我们需要的信息并不是第一个字符,比如当他返回字符串“OK”的时候,也许会在前后各添加一个换行符号,如果直接进行两个字符串比较,结果肯定不同。
变量u32SysTime由系统滴答时钟控制,我的是每毫秒增加,根据系统的负荷,可以自己调整。
----------------------------------------------------------------------------
初始化过程如下:
1 /* 检查模块状态 */ 2 for(i=0;i<5;i++) 3 { 4 res = MC20_SendAtCmd("AT", "OK", 500); 5 if(1 == res) 6 { 7 return 1; 8 } 9 delay_ms(100); 10 } 11 12 /* 检查SIM卡状态 */ 13 time = u32SysTime; 14 while(1) 15 { 16 res = MC20_SendAtCmd("AT+CPIN?\r", "+CPIN: READY", 400); 17 if(1 == res) 18 { 19 break; 20 } 21 if(u32SysTime - time > 5000) 22 { 23 return ; 24 } 25 delay_ms(400); 26 } 27 28 /* 检查网络状态 */ 29 time = u32SysTime; 30 while(1) 31 { 32 /* 检查网络状态 本地网络 */ 33 res = MC20_SendAtCmd("AT+CREG?\r", "+CREG: 0,1", 400); 34 if(1 == res) 35 { 36 break; 37 } 38 /* 检查网络状态 漫游 */ 39 res = MC20_SendAtCmd("AT+CREG?\r", "+CREG: 0,5", 400); 40 if(1 == res) 41 { 42 break; 43 } 44 if(u32SysTime - time > 5000) 45 { 46 return ; 47 } 48 delay_ms(400); 49 } 50 51 /* 检查GPRS信号强度 */ 52 time = u32SysTime; 53 while(1) 54 { 55 res = MC20_SendAtCmd("AT+CGATT?\r", "+CGATT: 1", 400); 56 if(1 == res) 57 { 58 break; 59 } 60 res = MC20_SendAtCmd("AT+CGATT?\r", "+CGATT: 5", 400); 61 if(1 == res) 62 { 63 break; 64 } 65 if(u32SysTime - time > 120000) 66 { 67 return ; 68 } 69 delay_ms(500); 70 } 71 72 /* 选择TCPIP传送模式 */ 73 res = MC20_SendAtCmd("AT+QIMODE=1\r", "OK", 600); 74 if(0 == res) 75 { 76 return ; 77 }
当一切准备就绪之后,开始建立TCP连接。
1 res = MC20_SendAtCmd("AT+QIOPEN=\"TCP\",\"114.55.114.201\",9088\r", "CONNECT\r", 60000); // 具体数据格式请参考手册 2 if(1 == res) 3 { 5 return 1; 6 } 7 else 8 {10 return 0; 11 }
如果连接建立成功,接下来就可以往服务器发送数据了,例如:MC20_SendData("Test", 5);发送一个测试命令。