当前位置:   article > 正文

SIM800/SIM900/SIM7000/SIM7600底层操作接口_句柄方式完全分离通信底层_sim900 at cipsr simcom_gprs.c

sim900 at cipsr simcom_gprs.c

使用SIMCOM公司通信模块已经好几年了,周末抽空把底层重新写了,将底层的通信与应用完全进行了分离,便于移植。

SIMCOM.h //定义了相关的结构体与类型。

SIMCOM_AT.c//定义了底层的AT接口

SIMCOM_GSM.c//需要的模块GSM相关命令

SIMCOM_GPRS.c//上网相关-未移植

SIMCOM_SMS.c//短信收发相关-未移植

SIMCOM_USER.c//用户最终接口

//需要自己实现数据收发相关接口,DCD,DTR,PWRKEY,STATUS相关IO接口,需要一个ms延时支持


//SIMCOM.h

  1. /*************************************************************************************************************
  2. * 文件名: SIMCOM.h
  3. * 功能: SIMCOM 底层定义
  4. * 作者: cp1300@139.com
  5. * 创建时间: 2015-02-15
  6. * 最后修改时间: 2018-03-23
  7. * 详细: 注意:底层通信接口使用的是回调函数,但是必须提供系统延时函数 void SYS_DelayMS(u32 ms);
  8. *************************************************************************************************************/
  9. #ifndef _SIMCOM_H_
  10. #define _SIMCOM_H_
  11. #include "system.h"
  12. //SIMCOM通信模块定义
  13. typedef enum
  14. {
  15. SIMCOM_SIM900 = 0 , //默认为SIM900
  16. SIMCOM_SIM800 = 1 , //SIM800
  17. SIMCOM_SIM2000 = 2 , //SIM2000
  18. SIMCOM_SIM7600 = 3 , //SIM7600
  19. SIMCOM_SIM868 = 4 , //SIM868
  20. SIMCOM_SIM7000C = 5 , //SIM7000C
  21. LYNQ_L700 = 10 , //LYNQ_L700
  22. SIMCOM_INVALID = 0XFF , //无效则默认
  23. }SIMCOM_MODE_TYPE;
  24. //网络注册状态
  25. typedef enum
  26. {
  27. SIMCOM_NET_NOT = 0, //未注册
  28. SIMCOM_NET_YES = 1, //已经注册
  29. SIMCOM_NET_SEA = 2, //未注册,正在搜索
  30. SIMCOM_NET_TUR = 3, //注册被拒绝
  31. SIMCOM_NET_UNK = 4, //未知
  32. SIMCOM_NET_ROA = 5, //已经注册,但是漫游
  33. SIMCOM_NET_ERROR=0XFF //错误
  34. }SIMCOM_NETSTATUS;
  35. //SIMCOM网络制式
  36. typedef enum
  37. {
  38. SIMCOM_NETMODE_NOT = 0, //未注册
  39. SIMCOM_NETMODE_GSM = 1, //GSM
  40. SIMCOM_NETMODE_GPRS = 2, //GPRS
  41. SIMCOM_NETMODE_EGPRS = 3, //EGPRS (EDGE)
  42. SIMCOM_NETMODE_WCDMA = 4, //WCDMA
  43. SIMCOM_NETMODE_HSDPA = 5, //HSDPA only(WCDMA)
  44. SIMCOM_NETMODE_HSUPA = 6, //HSUPA only(WCDMA)
  45. SIMCOM_NETMODE_HSPA = 7, //HSPA (HSDPA and HSUPA, WCDMA)
  46. SIMCOM_NETMODE_LTE = 8, //LTE
  47. SIMCOM_NETMODE_TDS_CDMA = 9, //TDS-CDMA
  48. SIMCOM_NETMODE_TDS_HSDPA = 10, //TDS-HSDPA only(SIM7000C 电信NB也是这个)
  49. SIMCOM_NETMODE_TDS_HSUPA = 11, //TDS-HSUPA only
  50. SIMCOM_NETMODE_TDS_HSPA = 12, //TDS- HSPA (HSDPA and HSUPA)
  51. SIMCOM_NETMODE_CDMA = 13, //CDMA
  52. SIMCOM_NETMODE_EVDO = 14, //EVDO
  53. SIMCOM_NETMODE_HYBRID = 15, //HYBRID (CDMA and EVDO)
  54. SIMCOM_NETMODE_1XLTE = 16, //1XLTE(CDMA and LTE)
  55. SIMCOM_NETMODE_NULL = 0xff, //未知
  56. }SIMCOM_NETMODE_TYPE;
  57. //SIM卡就绪状态
  58. typedef enum
  59. {
  60. SIM_READY = 0, //SIM卡就绪
  61. SIM_NOT_READY = 1, //SIM卡未就绪
  62. SIM_UNKNOWN = 2 //SIM卡状态未知
  63. }SIM_CARD_STATUS;
  64. //控制IO电平定义
  65. #define SIMCOM_H_LEVEL 1 //高电平
  66. #define SIMCOM_L_LEVEL 0 //低电平
  67. //DCD状态定义
  68. #define DCD_DATA_MODE 0 //数据透传模式
  69. #define DCD_AT_MODE 1 //AT指令模式
  70. //相关信息长度限制
  71. #define SIMCOM_INFO_SIZE 24 //信息长度
  72. #define SIMCOM_VER_SIZE 24 //软件版本长度定义
  73. //重试次数,防止AT指令操作失败
  74. #define SIMCOM_DEFAULT_RETRY 2
  75. //SIMCOM模块相关信息
  76. typedef struct
  77. {
  78. char Manu[SIMCOM_INFO_SIZE+1]; //制造商
  79. char Model[SIMCOM_INFO_SIZE+1]; //型号
  80. char Ver[SIMCOM_VER_SIZE+1]; //软件版本
  81. char IMEI[SIMCOM_INFO_SIZE+1]; //序列号
  82. }SIMCOM_INFO;
  83. //NBIOT模式定义
  84. typedef enum
  85. {
  86. NB_IOT_MODE = 0, //NBIOT模式
  87. CAT_M_MODE = 1, //CAT-M模式
  88. }NBIOT_MODE_TYPE;
  89. //网络模式设置
  90. typedef struct
  91. {
  92. SIMCOM_MODE_TYPE ModeType; //模块型号
  93. NBIOT_MODE_TYPE NB_Mode; //NB模式
  94. s8 NB_EnableMode; //NB模式使能模式,-1:无需设置;0:关闭NB,使能GSM模式;1:使能NB模式
  95. bool isNB_ScarEnable; //NB模式扰码使能
  96. }NETWORK_CONFIG_TYPE;
  97. //SIMCOM通信模块句柄
  98. typedef struct
  99. {
  100. //所需变量
  101. SIMCOM_MODE_TYPE SimcomModeType; //模块型号
  102. char TelecomCarr[SIMCOM_INFO_SIZE+1]; //运营商名称
  103. SIMCOM_INFO SIMCOM_Info; //SIMCOM通信模块相关信息结构体
  104. NETWORK_CONFIG_TYPE NetworkConfig; //网络模式设置
  105. SIMCOM_NETMODE_TYPE NetworkMode; //当前网络制式
  106. u8 Singal; //网络信号强度
  107. char LocalPhoneNumber[16]; //本机电话号码
  108. char ServiceCenterPhoneNumber[16]; //短信中心电话号码
  109. char SIM_CIMI[16]; //SIM卡唯一CIMI号码
  110. //底层通信接口
  111. bool (* pSendData)(u8 *pDataBuff, u16 DataLen); //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
  112. int (* pReadData)(u8 **pDataBuff, u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelay); //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
  113. void (*pClearRxData)(void); //清除接收缓冲区函数,用于清除接收数据缓冲区数据
  114. void (*pSetDTR_Pin)(u8 Level); //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
  115. void (*pSetPWRKEY_Pin)(u8 Level); //PWRKEY开机引脚电平控制-用于开机
  116. u8 (*pGetSTATUS_Pin)(void); //获取STATUS引脚电平-用于指示模块上电状态
  117. u8 (*pGetDCD_Pin)(void); //获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
  118. //系统接口
  119. void (*pDelayMS)(u32 ms); //系统延时函数
  120. void (*pIWDG_Feed)(void); //清除系统看门狗(可以为空)
  121. //内部状态定义
  122. bool s_isInitStatus; //用于记录模块初始化状态,复位或上电后变为无效
  123. }SIMCOM_HANDLE;
  124. #endif /*_SIMCOM_H_*/

//SIMCOM_AT.c

  1. /*************************************************************************************************************
  2. * 文件名: SIMCOM_AT.c
  3. * 功能: SIMCOM底层AT指令接口
  4. * 作者: cp1300@139.com
  5. * 创建时间: 2015-02-15
  6. * 最后修改时间: 2018-03-23
  7. * 详细:
  8. *************************************************************************************************************/
  9. #include "system.h"
  10. #include "usart.h"
  11. #include "SIMCOM_AT.h"
  12. #include "SIMCOM.h"
  13. #include "string.h"
  14. #include "ucos_ii.h"
  15. bool g_SIMC0M_AT_Debug = TRUE; //底层AT指令调试状态
  16. //调试开关
  17. #define SIMCOM_DBUG 1
  18. #if SIMCOM_DBUG
  19. #include "system.h"
  20. #define SIMCOM_debug(format,...) {if(g_SIMC0M_AT_Debug){uart_printf(format,##__VA_ARGS__);}}
  21. #else
  22. #define SIMCOM_debug(format,...) /\
  23. /
  24. #endif //SIMCOM_DBUG
  25. /*************************************************************************************************************************
  26. * 函数 : bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr)
  27. * 功能 : 发送一个AT指令(会添加结束符\r\n),不会等待响应
  28. * 参数 : pHandle:SIMCOM句柄;pStr:指令字符串
  29. * 返回 : 接口发送状态
  30. * 依赖 : 无
  31. * 作者 : cp1300@139.com
  32. * 时间 : 2018-03-23
  33. * 最后修改时间 : 2018-03-23
  34. * 说明 : 用于底层AT指令发送
  35. *************************************************************************************************************************/
  36. bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr)
  37. {
  38. pHandle->pSendData((u8 *)pStr, strlen(pStr)); //发送指令
  39. return pHandle->pSendData((u8 *)"\r\n", 2); //发送结束符
  40. }
  41. /*************************************************************************************************************************
  42. * 函数 : bool SIMCOM_TestAT(SIMCOM_HANDLE *pHandle, u32 retry)
  43. * 功能 : SIMCOM AT 命令通信测试
  44. * 参数 : pHandle:SIMCOM句柄;retry:重试次数
  45. * 返回 : FALSE:通信失败;TRUE:通信成功
  46. * 依赖 : 底层
  47. * 作者 : cp1300@139.com
  48. * 时间 : 2013-10-20
  49. * 最后修改时间 : 2018-03-23
  50. * 说明 : 每隔100ms向SIMCOM通信模块发送一个"AT",等待响应返回
  51. *************************************************************************************************************************/
  52. bool SIMCOM_TestAT(SIMCOM_HANDLE *pHandle, u32 retry)
  53. {
  54. u32 cnt;
  55. u8 *pRxBuff;
  56. //检测模块存在
  57. do
  58. {
  59. SIMCOM_SendAT(pHandle, "AT"); //发送"AT",同步波特率,并且等待应答
  60. pHandle->pClearRxData(); //清除计数器
  61. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pRxBuff, &cnt, "OK", 10, 150)) //等待响应,超时150ms
  62. {
  63. pHandle->pDelayMS(100);
  64. return TRUE;
  65. }
  66. retry --;
  67. }while(retry);
  68. pHandle->pDelayMS(100);
  69. return FALSE;
  70. }
  71. /*************************************************************************************************************************
  72. * 函数 : bool SIMCOM_WaitSleep(SIMCOM_HANDLE *pHandle, u32 TimeOutMs)
  73. * 功能 : 等待模块空闲,并重新唤醒
  74. * 参数 : pHandle:句柄;TimeOut:等待超时,时间单位ms
  75. * 返回 : TRUE:成功;FALSE:超时
  76. * 依赖 : 无
  77. * 作者 : cp1300@139.com
  78. * 时间 : 2013-10-25
  79. * 最后修改时间 : 2018-03-24
  80. * 说明 : 用于等待操作完成,防止快速操作造成模块不响应
  81. *************************************************************************************************************************/
  82. bool SIMCOM_WaitSleep(SIMCOM_HANDLE *pHandle, u32 TimeOutMs)
  83. {
  84. u32 i;
  85. u32 cnt;
  86. u8 *pData;
  87. if(TimeOutMs < 100) TimeOutMs = 100; //最少100ms
  88. pHandle->pSetDTR_Pin(SIMCOM_H_LEVEL); //等待模块空闲后进入SLEEP模式
  89. //循环发送命令,直到命令超时了则认为进入了sleep模式
  90. for(i = 0;i < (TimeOutMs/100);i ++)
  91. {
  92. pHandle->pDelayMS(100); //延时100ms
  93. SIMCOM_SendAT(pHandle, "AT"); //发送"AT",同步波特率,并且等待应答
  94. pHandle->pClearRxData(); //清除接收计数器
  95. if(AT_RETURN_TIME_OUT == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 100)) //等待响应,超时100ms
  96. {
  97. break;
  98. }
  99. }
  100. pHandle->pSetDTR_Pin(SIMCOM_L_LEVEL); //唤醒
  101. if(i == (TimeOutMs/100))
  102. {
  103. SIMCOM_debug("模块进入空闲模式失败!\r\n");
  104. pHandle->pClearRxData(); //清除接收计数器
  105. return FALSE;
  106. }
  107. pHandle->pDelayMS(100); //延时100ms
  108. SIMCOM_debug("模块进入空闲模式成功!\r\n");
  109. SIMCOM_TestAT(pHandle, 10);
  110. pHandle->pClearRxData(); //清除接收计数器
  111. return TRUE;
  112. }
  113. /*************************************************************************************************************************
  114. * 函数 : SIMCOM_AT_ERROR SIMCOM_GetATResp(SIMCOM_HANDLE *pHandle, u8 **pRxBuff, u32 *pLen, const char *pKeyword, u8 ByteTimeOutMs, u16 TimeOutMs)
  115. * 功能 : 获取SIMCOM的AT指令响应
  116. * 参数 : pHandle:句柄
  117. pRxBuff:接收缓冲区指针(输出);pLen:接收到的数据大小(输出),
  118. pKeyword:关键字,为字符串,比如"OK",如果在接收到的字符串中有OK字符,就返回成功,否则失败(输入)
  119. ByteTimeOutMs:字节超时时间,单位ms最大255ms
  120. TimeOutMs:等待超时时间,单位毫秒
  121. * 返回 : SIM900_ERROR
  122. * 依赖 : 无
  123. * 作者 : cp1300@139.com
  124. * 时间 : 2018-03-24
  125. * 最后修改时间 : 2018-03-24
  126. * 说明 : 本函数会在接收缓冲区字符串结束添加'\0'
  127. 本函数不能清除缓冲区
  128. *************************************************************************************************************************/
  129. SIMCOM_AT_ERROR SIMCOM_GetATResp(SIMCOM_HANDLE *pHandle, u8 **pRxBuff, u32 *pLen, const char *pKeyword, u8 ByteTimeOutMs, u16 TimeOutMs)
  130. {
  131. int len;
  132. u16 ReceiveDelay;
  133. if(ByteTimeOutMs < 1) ByteTimeOutMs = 1;
  134. len = pHandle->pReadData(pRxBuff, ByteTimeOutMs, TimeOutMs, &ReceiveDelay); //调用回调接口,读取数据
  135. //等待超时
  136. if(len == 0)
  137. {
  138. return AT_RETURN_TIME_OUT; //返回超时错误
  139. }
  140. //数据接收完毕
  141. *pLen = len; //返回接收数据长度
  142. if((*pRxBuff)[len-1] != 0)
  143. {
  144. (*pRxBuff)[len] = '\0'; //将数据结尾添加结束字符串
  145. }
  146. SIMCOM_debug("\r\nSIMCOM(%dB)->%s\r\n",len, *pRxBuff); //打印返回信息
  147. if(strstr((const char*)(*pRxBuff), pKeyword) != NULL) //搜索关键字
  148. {
  149. SIMCOM_debug("%s 返回成功!\r\n",pKeyword);
  150. return AT_RETURN_OK;
  151. }
  152. else if(strstr((const char*)(*pRxBuff), "ERROR") != NULL)
  153. {
  154. SIMCOM_debug("%s 返回错误!\r\n",pKeyword);
  155. return AT_RETURN_ERROR;
  156. }
  157. else
  158. {
  159. SIMCOM_debug("%s 返回未知!\r\n",pKeyword);
  160. return AT_RETURN_UNKNOWN;
  161. }
  162. }
  163. /*************************************************************************************************************************
  164. * 函数 : bool SIM900_SetParametersReturnBool(char *pATCom, u8 retry, u16 TimeOutx10MS, const char *pErrorDebug)
  165. * 功能 : 设置SIM900一个参数,返回一个bool状态
  166. * 参数 : pATCom:AT命令;retry:重试次数;TimeOut:命令超时时间,单位10ms;pErrorDebug:失败后提示的调试信息
  167. * 返回 : TRUE:执行成功了,返回了OK,FALSE:执行失败了,返回了ERROR或其它
  168. * 依赖 : SIM900
  169. * 作者 : cp1300@139.com
  170. * 时间 : 2014-12-19
  171. * 最后修改时间 : 2014-12-19
  172. * 说明 : 用于简化命名发送,防止代码重复
  173. *************************************************************************************************************************/
  174. bool SIMCOM_SetParametersReturnBool(SIMCOM_HANDLE *pHandle, char *pATCom, u8 retry, u16 TimeOutMs, const char *pErrorDebug)
  175. {
  176. u32 cnt;
  177. u8 *pData;
  178. retry += 1; //重试次数
  179. do
  180. {
  181. SIMCOM_SendAT(pHandle,pATCom); //发送AT命令
  182. pHandle->pClearRxData(); //清除接收计数器
  183. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, TimeOutMs)) //等待响应,超时10s
  184. {
  185. pHandle->pClearRxData(); //清除接收计数器
  186. return TRUE;
  187. }
  188. SIMCOM_Ready(pHandle); //等待就绪
  189. retry --;
  190. }while(retry);
  191. if(pErrorDebug!=NULL)
  192. {
  193. uart_printf("%s",pErrorDebug); //输出调试信息
  194. }
  195. pHandle->pClearRxData(); //清除接收计数器
  196. return FALSE;
  197. }
  198. /*************************************************************************************************************************
  199. *函数 : u32 GSM_StringToHex(char *pStr, u8 NumDigits)
  200. *功能 : 将16进制样式字符串转换为16进制整型数(必须保证字符串字母都是大写)
  201. *参数 : pStr:字符串起始指针
  202. * NumDigits:数字位数,16进制数字位数
  203. *返回 : 转换后的数字
  204. *依赖 : 无
  205. *作者 : cp1300@139.com
  206. *时间 : 2013-04-30
  207. *最后修改时间 : 2013-10-17
  208. *说明 : 比如字符串"A865"转换后为0xA865,位数为4位
  209. 必须保证字符串字母都是大写
  210. *************************************************************************************************************************/
  211. u32 GSM_StringToHex(char *pStr, u8 NumDigits)
  212. {
  213. u8 temp;
  214. u32 HEX = 0;
  215. u8 i;
  216. NumDigits = (NumDigits > 8) ? 8 : NumDigits; //最大支持8位16进制数
  217. for(i = 0;i < NumDigits;i ++)
  218. {
  219. HEX <<= 4;
  220. temp = pStr[i];
  221. temp = (temp > '9') ? temp - 'A' + 10 : temp - '0';
  222. HEX |= temp;
  223. }
  224. return HEX;
  225. }
  226. /*************************************************************************************************************************
  227. *函数 : void GSM_HexToString(u32 HexNum,c har *pStr, u8 NumDigits)
  228. *功能 : 将整型数字转换为16进制样式字符串(字母为大写,不带结束符)
  229. *参数 : HexNum:16进制数字
  230. pStr:字符缓冲区指针
  231. * NumDigits:数字位数,16进制数字位数
  232. *返回 : 无
  233. *依赖 : 无
  234. *作者 : cp1300@139.com
  235. *时间 : 2013-04-30
  236. *最后修改时间 : 2013-04-30
  237. *说明 : 比如字符串0xA865转换后为"A865",位数为4位
  238. *************************************************************************************************************************/
  239. void GSM_HexToString(u32 HexNum,char *pStr, u8 NumDigits)
  240. {
  241. u8 temp;
  242. u8 i;
  243. NumDigits = (NumDigits > 8) ? 8 : NumDigits; //最大支持8位16进制数
  244. for(i = 0;i < NumDigits;i ++)
  245. {
  246. temp = 0x0f & (HexNum >> (4 * (NumDigits - 1 - i)));
  247. temp = (temp > 0x09) ? (temp - 0x0A + 'A') : (temp + '0');
  248. pStr[i] = temp;
  249. }
  250. }
  251. /*************************************************************************************************************************
  252. *函数 : u32 GSM_StringToDec(char *pStr, u8 NumDigits)
  253. *功能 : 将10进制样式字符串转换为整型数(必须保证完全为数字字符)
  254. *参数 : pStr:字符串起始指针
  255. * NumDigits:数字位数,10进制数字位数
  256. *返回 : 转换后的数字
  257. *依赖 : 无
  258. *作者 : cp1300@139.com
  259. *时间 : 2013-04-30
  260. *最后修改时间 : 2013-04-30
  261. *说明 : 比如字符串"1865"转换后为1865,位数为4位
  262. 必须保证完全为数字字符
  263. *************************************************************************************************************************/
  264. u32 GSM_StringToDec(char *pStr, u8 NumDigits)
  265. {
  266. u32 temp;
  267. u32 DEC = 0;
  268. u8 i;
  269. u8 j;
  270. NumDigits = (NumDigits > 10) ? 10 : NumDigits; //最大支持10位10进制数
  271. for(i = 0;i < NumDigits;i ++)
  272. {
  273. temp = pStr[i] - '0';
  274. if(temp > 9) //只能是数字范围
  275. return 0;
  276. for(j = 1;j < (NumDigits - i);j ++)
  277. {
  278. temp *= 10;
  279. }
  280. DEC += temp;
  281. }
  282. return DEC;
  283. }

//SIMCOM_AT.h

  1. /*************************************************************************************************************
  2. * 文件名: SIMCOM_AT.h
  3. * 功能: SIMCOM底层AT指令接口
  4. * 作者: cp1300@139.com
  5. * 创建时间: 2015-02-15
  6. * 最后修改时间: 2018-03-23
  7. * 详细:
  8. *************************************************************************************************************/
  9. #ifndef _SIMCOM_AT_H_
  10. #define _SIMCOM_AT_H_
  11. #include "system.h"
  12. #include "SIMCOM.h"
  13. extern bool g_SIMC0M_AT_Debug; //底层AT指令调试状态
  14. //SIM900返回错误
  15. typedef enum
  16. {
  17. AT_RETURN_OK = 0, //返回成功
  18. AT_RETURN_ERROR = 1, //返回错误
  19. AT_RETURN_UNKNOWN = 2, //返回结果未知
  20. AT_RETURN_TIME_OUT = 0xf, //等待返回超时
  21. }SIMCOM_AT_ERROR;
  22. //相关接口
  23. bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr); //发送一个AT指令(会添加结束符\r\n),不会等待响应
  24. SIMCOM_AT_ERROR SIMCOM_GetATResp(SIMCOM_HANDLE *pHandle, u8 **pRxBuff, u32 *pLen, const char *pKeyword, u8 ByteTimeOutMs, u16 TimeOutMs); //获取SIMCOM的AT指令响应
  25. bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr); //发送一个AT指令(会添加结束符\r\n),不会等待响应
  26. bool SIMCOM_WaitSleep(SIMCOM_HANDLE *pHandle, u32 TimeOutMs); //等待模块空闲,并重新唤醒
  27. bool SIMCOM_TestAT(SIMCOM_HANDLE *pHandle, u32 retry); //SIMCOM AT 命令通信测试
  28. #define SIMCOM_Ready(pHandle) if(SIMCOM_TestAT(pHandle, 5) == FALSE){SIMCOM_WaitSleep(pHandle, 1000);} //让SIMCOM就绪,防止卡住//串口同步失败,等待上一个操作完成
  29. bool SIMCOM_SetParametersReturnBool(SIMCOM_HANDLE *pHandle, char *pATCom, u8 retry, u16 TimeOutMs, const char *pErrorDebug); //设置SIM900一个参数,返回一个bool状态
  30. //通用工具
  31. u32 GSM_StringToHex(char *pStr, u8 NumDigits); //将16进制样式字符串转换为16进制整型数(必须保证字符串字母都是大写)
  32. u32 GSM_StringToDec(char *pStr, u8 NumDigits); //将10进制样式字符串转换为整型数(必须保证完全为数字字符)
  33. void GSM_HexToString(u32 HexNum,char *pStr, u8 NumDigits); //将整型数字转换为16进制样式字符串(字母为大写,不带结束符)
  34. #endif /*SIMCOM_AT*/

//SIMCOM_GSM.c //通用的底层操作

  1. /*************************************************************************************************************
  2. * 文件名: SIMCOM_GSM.c
  3. * 功能: SIMCOM GSM相关接口
  4. * 作者: cp1300@139.com
  5. * 创建时间: 2015-02-15
  6. * 最后修改时间: 2018-03-23
  7. * 详细:
  8. *************************************************************************************************************/
  9. #include "system.h"
  10. #include "usart.h"
  11. #include "SIMCOM_GSM.h"
  12. #include "SIMCOM_AT.h"
  13. #include "string.h"
  14. #include "SIMCOM.h"
  15. #include <stdlib.h>
  16. bool g_SIMC0M_GSM_Debug = TRUE; //底层AT指令调试状态
  17. //调试开关
  18. #define SIMCOM_GSM_DBUG 1
  19. #if SIMCOM_GSM_DBUG
  20. #include "system.h"
  21. #define SIMCOM_GSM_debug(format,...) {if(g_SIMC0M_GSM_Debug){uart_printf(format,##__VA_ARGS__);}}
  22. #else
  23. #define SIMCOM_GSM_debug(format,...) /\
  24. /
  25. #endif //SIMCOM_GSM_DBUG
  26. /*************************************************************************************************************************
  27. * 函数 : bool SIMCOM_NetworkConfig(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, SIMCOM_SIM_SELECT SIM_Select)
  28. * 功能 : SIMCOM网络配置
  29. * 参数 : pHandle:句柄;ModeType:通信模块型号;SIM_Select:SIM卡选择;
  30. * 返回 : TRUE:成功,FALSE:失败
  31. * 依赖 : 底层
  32. * 作者 : cp1300@139.com
  33. * 时间 : 2018-01-17
  34. * 最后修改时间 : 2018-03-24
  35. * 详细 :
  36. *************************************************************************************************************************/
  37. bool SIMCOM_NetworkConfig(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, NETWORK_CONFIG_TYPE *pConfig)
  38. {
  39. char buff[16];
  40. pConfig->ModeType = ModeType; //记录通信模块型号
  41. if(ModeType == SIMCOM_SIM7000C) //SIM7000C需要选择工作模式
  42. {
  43. switch(pConfig->NB_EnableMode)
  44. {
  45. case 0: //GSM模式
  46. {
  47. uart_printf("[DTU]设置GSM网络模式!\r\n");
  48. if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CNMP=13", SIMCOM_DEFAULT_RETRY, 200, "\r\n设置SIM7000C GSM模式失败!\r\n") == FALSE) return FALSE; //GSM模式
  49. }break;
  50. case 1://NB模式
  51. {
  52. uart_printf("[DTU]设置NBIOT网络模式!\r\n");
  53. if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CNMP=38", SIMCOM_DEFAULT_RETRY, 200, "\r\n设置SIM7000C LTE NB模式失败!\r\n") == FALSE) return FALSE; //LTE only(使用NB-IOT网络时CNMP需要设置为38)
  54. //CAT NB模式设置
  55. switch(pConfig->ModeType)
  56. {
  57. case CAT_M_MODE: //CAT模式
  58. {
  59. sprintf(buff,"AT+CMNB=%d",1); //cat模式
  60. }break;
  61. default:
  62. {
  63. sprintf(buff,"AT+CMNB=%d",2); //NBIOT模式
  64. }break;
  65. }
  66. if(SIMCOM_SetParametersReturnBool(pHandle, buff, SIMCOM_DEFAULT_RETRY, 200, "\r\n设置SIM7000C CAT NB模式失败!\r\n") == FALSE) return FALSE; //1: CAT-M 2: NB-IOT
  67. //扰码设置
  68. if(pConfig->isNB_ScarEnable) //开启扰码
  69. {
  70. sprintf(buff,"AT+NBSC=%d",1);
  71. }
  72. else
  73. {
  74. sprintf(buff,"AT+NBSC=%d",0);
  75. }
  76. if(SIMCOM_SetParametersReturnBool(pHandle, buff, SIMCOM_DEFAULT_RETRY, 200, "\r\n设置SIM7000C NB 扰码模式失败!\r\n") == FALSE) return FALSE;
  77. }break;
  78. default:return TRUE; //忽略,无需设置
  79. }
  80. }
  81. return TRUE;
  82. }
  83. /*************************************************************************************************************************
  84. * 函数 : SIM_CARD_STATUS SIMCOM_GetCPIN(SIMCOM_HANDLE *pHandle)
  85. * 功能 : 获取SIM卡状态
  86. * 参数 : 无
  87. * 返回 : FALSE:失败;TRUE:成功
  88. * 依赖 : 底层
  89. * 作者 : cp1300@139.com
  90. * 时间 : 2014-06-26
  91. * 最后修改时间 : 2014-06-26
  92. * 说明 : 2017-09-05 : 增加SIM卡状态为3种状态
  93. *************************************************************************************************************************/
  94. SIM_CARD_STATUS SIMCOM_GetCPIN(SIMCOM_HANDLE *pHandle)
  95. {
  96. u32 cnt;
  97. char *p;
  98. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  99. int status;
  100. u8 *pData;
  101. do
  102. {
  103. //+CPIN: READY
  104. SIMCOM_SendAT(pHandle, "AT+CPIN?");
  105. pHandle->pClearRxData(); //清除接收计数器
  106. status = SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 200); //等待响应,超时200MS
  107. if(AT_RETURN_OK == status) //返回OK
  108. {
  109. p = strstr((const char*)pData, "+CPIN: READY"); //搜索字符"+CPIN: READY"
  110. if(p != NULL) //搜索成功
  111. {
  112. return SIM_READY; //SIM卡就绪
  113. }
  114. break;
  115. }
  116. else if(AT_RETURN_ERROR == status) //返回ERROR
  117. {
  118. p = strstr((const char*)pData, "ERROR"); //搜索卡未准备就绪标志
  119. if(p != NULL) //搜索成功
  120. {
  121. return SIM_NOT_READY; //SIM卡未就绪
  122. }
  123. break;
  124. }
  125. SIMCOM_Ready(pHandle); //等待就绪
  126. pHandle->pDelayMS(1000); //失败延时1秒后重试
  127. retry --;
  128. }while(retry);
  129. return SIM_UNKNOWN; //SIM卡未知
  130. }
  131. /*************************************************************************************************************************
  132. * 函数 : SIMCOM_NETSTATUS SIM900_GetGSMNetworkStatus(SIMCOM_HANDLE *pHandle)
  133. * 功能 : 获取GSM网络注册状态
  134. * 参数 : pHandle:句柄
  135. * 返回 : SIMCOM_NETSTATUS
  136. * 依赖 : 底层
  137. * 作者 : cp1300@139.com
  138. * 时间 : 2013-10-29
  139. * 最后修改时间 : 2018-03-24
  140. * 说明 : 当网络注册后,可能被拒绝,如果被拒绝,获取网络注册状态会提示
  141. 注册成功的,但是通过发送AT 后再去查询,会发现网络注册失败
  142. *************************************************************************************************************************/
  143. SIMCOM_NETSTATUS SIM900_GetGSMNetworkStatus(SIMCOM_HANDLE *pHandle)
  144. {
  145. u32 cnt;
  146. char *p;
  147. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  148. u8 *pData;
  149. do
  150. {
  151. //+CREG: 0,1
  152. SIMCOM_SendAT(pHandle, "AT+CREG?"); //发送"AT+CREG?",获取网络注册状态
  153. pHandle->pClearRxData(); //清除接收计数器
  154. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 200)) //等待响应,超时200MS
  155. {
  156. p = strstr((const char*)pData, "+CREG:"); //搜索字符"+CREG:"
  157. if(p != NULL) //搜索成功
  158. {
  159. SIMCOM_TestAT(pHandle, 1);
  160. return (SIMCOM_NETSTATUS)GSM_StringToDec(&p[9], 1);
  161. }
  162. break;
  163. }
  164. SIMCOM_Ready(pHandle); //等待就绪
  165. pHandle->pDelayMS(1000); //失败延时1秒后重试
  166. retry --;
  167. }while(retry);
  168. SIMCOM_TestAT(pHandle, 2);
  169. return SIMCOM_NET_ERROR;
  170. }
  171. /*************************************************************************************************************************
  172. * 函数 : SIMCOM_NETSTATUS SIMCOM_GetDataNetworkStatus(SIMCOM_HANDLE *pHandle)
  173. * 功能 : 获取数据网络注册状态
  174. * 参数 : pHandle:句柄
  175. * 返回 : SIMCOM_NETSTATUS
  176. * 依赖 : 底层
  177. * 作者 : cp1300@139.com
  178. * 时间 : 2013-10-29
  179. * 最后修改时间 : 2018-03-24
  180. * 说明 : 用于获取NB数据网络或GPRS数据网络注册状态
  181. *************************************************************************************************************************/
  182. SIMCOM_NETSTATUS SIMCOM_GetDataNetworkStatus(SIMCOM_HANDLE *pHandle)
  183. {
  184. u32 cnt;
  185. char *p;
  186. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  187. u8 *pData;
  188. do
  189. {
  190. //+CGREG: 0,1
  191. SIMCOM_SendAT(pHandle, "AT+CGREG?"); //发送"AT+CGREG?",获取网络注册状态
  192. pHandle->pClearRxData(); //清除接收计数器
  193. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 200)) //等待响应,超时200MS
  194. {
  195. p = strstr((const char*)pData, "+CGREG:"); //搜索字符"+CGREG:"
  196. if(p != NULL) //搜索成功
  197. {
  198. SIMCOM_TestAT(pHandle, 1);
  199. return (SIMCOM_NETSTATUS)GSM_StringToDec(&p[10], 1);
  200. }
  201. break;
  202. }
  203. SIMCOM_Ready(pHandle); //等待就绪
  204. pHandle->pDelayMS(1000); //失败延时1秒后重试
  205. retry --;
  206. }while(retry);
  207. SIMCOM_TestAT(pHandle, 2);
  208. return SIMCOM_NET_ERROR;
  209. }
  210. /*************************************************************************************************************************
  211. * 函数 : bool SIM900_SetGPRS_PackDatatSize(SIMCOM_HANDLE *pHandle)
  212. * 功能 : 设置SIM900/SIM800 GPRS发送数据缓冲区
  213. * 参数 : pHandle:句柄
  214. * 返回 : FALSE:失败;TRUE:成功
  215. * 依赖 : 底层
  216. * 作者 : cp1300@139.com
  217. * 时间 : 2014-09-11
  218. * 最后修改时间 : 2014-09-11
  219. * 说明 : 按照最大数据包1460B设置
  220. *************************************************************************************************************************/
  221. bool SIM900_SetGPRS_PackDatatSize(SIMCOM_HANDLE *pHandle)
  222. {
  223. char buff[36];
  224. //先开启透传模式才能设置
  225. SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPMODE=1", SIMCOM_DEFAULT_RETRY, 2000, "开启透传模式失败!\r\n"); //开启透传模式
  226. //设置GPRS传输数据包大小
  227. //AT+CIPCCFG=3,2,1024,1 //设置透传参数 //3-重传次数为3次,2-等待数据输入时间为 //2*200ms,1024-数据缓冲区为1024个字节 //1-支持转义退出透传
  228. sprintf(buff,"AT+CIPCCFG=3,2,%d,1",1460);
  229. return SIMCOM_SetParametersReturnBool(pHandle, buff, SIMCOM_DEFAULT_RETRY, 200, "GPRS发送数据缓冲区设置失败!\r\n"); //发送
  230. }
  231. /*************************************************************************************************************************
  232. * 函数 : bool SIMCOM_ModuleInit(SIMCOM_HANDLE *pHandle)
  233. * 功能 : 初始化SIMCOM模块基本配置(不允许失败)
  234. * 参数 : pHandle:句柄
  235. * 返回 : FALSE:初始化失败;TRUE:初始化成功
  236. * 依赖 : 底层
  237. * 作者 : cp1300@139.com
  238. * 时间 : 2013-10-16
  239. * 最后修改时间 : 2018-03-24
  240. * 说明 : 必须先上电,并获取模块型号,根据不同的型号模块分别进行初始化
  241. *************************************************************************************************************************/
  242. bool SIMCOM_ModuleInit(SIMCOM_HANDLE *pHandle)
  243. {
  244. u8 retry = 5; //重试次数
  245. pHandle->pSetDTR_Pin(SIMCOM_L_LEVEL); //DTR=0,退出低功耗模式
  246. //检测模块存在,并保证通信正常
  247. SIMCOM_Ready(pHandle);
  248. SIMCOM_TestAT(pHandle, 20);
  249. switch(pHandle->SimcomModeType) //不同的芯片存在不一样的初始化
  250. {
  251. case SIMCOM_SIM2000: //SIM2000需要先关闭URC,否则会提示Call Ready
  252. {
  253. SIMCOM_SetParametersReturnBool(pHandle, "AT+CIURC=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭Call Ready显示失败!\r\n");
  254. }break;
  255. default:break;
  256. }
  257. //设置关闭回显
  258. if(SIMCOM_SetParametersReturnBool(pHandle, "ATE 0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭AT回显模式失败!\r\n") == FALSE)
  259. {
  260. return FALSE;
  261. }
  262. //设置短消息格式为PDU格式
  263. if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CMGF=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n设置短消息格式为PDU格式失败!\r\n") == FALSE)
  264. {
  265. uart_printf("\r\n设置DCD功能模式失败!\r\n");
  266. return FALSE;
  267. }
  268. //设置DCD功能模式,DCD线只在数据载波存在时为ON。
  269. if(SIMCOM_SetParametersReturnBool(pHandle, "AT&C1", SIMCOM_DEFAULT_RETRY, 110, "\r\n设置DCD功能模式失败!\r\n") == FALSE)
  270. {
  271. uart_printf("\r\n设置DCD功能模式失败!\r\n");
  272. //return FALSE;
  273. }
  274. //设置 DTR 功能模式,DTR 由ON至OFF:TA在保持当前数据通话的同时,切换至命令模式
  275. if(SIMCOM_SetParametersReturnBool(pHandle, "AT&D1", SIMCOM_DEFAULT_RETRY, 110, "\r\n设置DTR功能模式失败!\r\n") == FALSE)
  276. {
  277. uart_printf("\r\n设置DTR功能模式失败!\r\n");
  278. //return FALSE;
  279. }
  280. // //使能RI引脚提示
  281. // if(SIM900_SetParametersReturnBool("AT+CFGRI=1", SIMCOM_DEFAULT_RETRY, 11, "\r\n启动RI引脚提示失败!\r\n") == FALSE)
  282. // {
  283. // return FALSE;
  284. // }
  285. //设置模块sleep模式使能//发送"AT+CSCLK",启动SLEEP模式;0:关闭;1:手动;2:自动空闲5S钟后休眠
  286. if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CSCLK=1", SIMCOM_DEFAULT_RETRY, 110, "\r\n设置SLEEP失败!\r\n") == FALSE)
  287. {
  288. return FALSE;
  289. }
  290. //检查卡是否就绪
  291. retry = 8; //重试次数
  292. do
  293. {
  294. if(SIMCOM_GetCPIN(pHandle)==SIM_READY)
  295. {
  296. uart_printf("\r\nSIM卡准备就绪!\r\n");
  297. break;
  298. }
  299. else
  300. {
  301. uart_printf("\r\nSIM卡未准备就绪!\r\n");
  302. }
  303. SIMCOM_Ready(pHandle); //等待就绪
  304. pHandle->pDelayMS(1000); //失败延时1秒后重试
  305. retry --;
  306. }while(retry);
  307. if(retry == 0)
  308. {
  309. uart_printf("\r\nSIM卡未准备就绪!\r\n");
  310. pHandle->pClearRxData(); //清除接收计数器
  311. return FALSE;
  312. }
  313. // //上电删除所有短信
  314. // retry = SIMCOM_DEFAULT_RETRY; //重试次数
  315. // do
  316. // {
  317. // if(SIM900_DelMultiSMS(DelSMS) == TRUE)//删除短信
  318. // {
  319. // //uart_printf("上电删除短信成功!\r\n");
  320. // break;
  321. // }
  322. // SIM900_Ready(); //等待就绪
  323. // retry --;
  324. // }while(retry);
  325. // if(retry == 0)
  326. // {
  327. // uart_printf("上电删除短信失败!\r\n");
  328. // SIM900_ClearRxCnt(); //清除计数器
  329. // return FALSE;
  330. // }
  331. //2016-09-20:设置等待消息上报超时时间为1分钟,因为西宁项目卡出现超时情况
  332. switch(pHandle->SimcomModeType) //不同的芯片存在不一样的初始化
  333. {
  334. case SIMCOM_SIM800: //SIM800需要等待就绪时间长一些
  335. {
  336. retry = 65;
  337. }break;
  338. default:retry=35;break;
  339. }
  340. //关闭新消息自动上报
  341. while(retry)
  342. {
  343. if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CNMI=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭新消息自动上报失败!\r\n") == FALSE)
  344. {
  345. //return FALSE;
  346. }
  347. else break;
  348. pHandle->pDelayMS(1000); //延时1秒
  349. retry --;
  350. }
  351. if(retry == 0) return FALSE;
  352. switch(pHandle->SimcomModeType) //不同的芯片存在不一样的初始化
  353. {
  354. case LYNQ_L700: break;
  355. case SIMCOM_SIM7600:
  356. {
  357. //设置TCP收发相关
  358. retry = SIMCOM_DEFAULT_RETRY; //重试次数
  359. while(retry)
  360. {
  361. //设置重试次数为3次,并且发送延时为120ms
  362. if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPCCFG=3,100,,1,0,,1000", SIMCOM_DEFAULT_RETRY, 110, "\r\n配置TCP/IP失败!\r\n") == FALSE)
  363. {
  364. //return FALSE;
  365. }
  366. else break;
  367. pHandle->pDelayMS(1000); //延时1秒
  368. retry --;
  369. }
  370. if(retry == 0)
  371. {
  372. uart_printf("\r\n设置TCP重发次数以及发送延时失败!\r\n");
  373. pHandle->pClearRxData(); //清除接收计数器
  374. return FALSE;
  375. }
  376. //设置不用等到发送响应
  377. retry = SIMCOM_DEFAULT_RETRY; //重试次数
  378. while(retry)
  379. {
  380. //设置重试次数为3次,并且发送延时为120ms
  381. if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPSENDMODE=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n不用等待发送ACK设置失败!\r\n") == FALSE)
  382. {
  383. //return FALSE;
  384. }
  385. else break;
  386. pHandle->pDelayMS(1000); //延时1秒
  387. retry --;
  388. }
  389. if(retry == 0)
  390. {
  391. uart_printf("\r\n设置不用等待发送ACK失败!\r\n");
  392. pHandle->pClearRxData(); //清除接收计数器
  393. }
  394. //显示接收数据长度
  395. retry = SIMCOM_DEFAULT_RETRY; //重试次数
  396. while(retry)
  397. {
  398. //设置重试次数为3次,并且发送延时为120ms
  399. if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPHEAD=1", SIMCOM_DEFAULT_RETRY, 110, "\r\n显示接收数据长度设置失败!\r\n") == FALSE)
  400. {
  401. //return FALSE;
  402. }
  403. else break;
  404. pHandle->pDelayMS(1000); //延时1秒
  405. retry --;
  406. }
  407. if(retry == 0)
  408. {
  409. uart_printf("\r\n设置显示接收数据长度失败!\r\n");
  410. pHandle->pClearRxData(); //清除接收计数器
  411. return FALSE;
  412. }
  413. //不显示接收数据IP头
  414. retry = SIMCOM_DEFAULT_RETRY; //重试次数
  415. while(retry)
  416. {
  417. //设置重试次数为3次,并且发送延时为120ms
  418. if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPSRIP=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n不显示接收数据IP头设置失败!\r\n") == FALSE)
  419. {
  420. //return FALSE;
  421. }
  422. else break;
  423. pHandle->pDelayMS(1000); //延时1秒
  424. retry --;
  425. }
  426. if(retry == 0)
  427. {
  428. uart_printf("\r\n不显示接收数据IP头失败!\r\n");
  429. pHandle->pClearRxData(); //清除接收计数器
  430. return FALSE;
  431. }
  432. }break;
  433. default: //2G模块均需要进行设置的
  434. {
  435. //设置GPRS发送数据缓冲区大小
  436. retry = SIMCOM_DEFAULT_RETRY; //重试次数
  437. do
  438. {
  439. if(SIM900_SetGPRS_PackDatatSize(pHandle) == TRUE)
  440. {
  441. break;
  442. }
  443. retry --;
  444. }while(retry);
  445. if(retry == 0)
  446. {
  447. uart_printf("\r\n设置GPRS传输大小失败!\r\n");
  448. pHandle->pClearRxData(); //清除接收计数器
  449. return FALSE;
  450. }
  451. }break;
  452. }
  453. pHandle->s_isInitStatus = TRUE; //模块成功初始化
  454. pHandle->pClearRxData(); //清除接收计数器
  455. return TRUE;
  456. }
  457. /*************************************************************************************************************************
  458. * 函数 : bool SIMCOM_GetModuleInfo(SIMCOM_HANDLE *pHandle, SIMCOM_INFO *pInfo)
  459. * 功能 : 获取模块的相关信息
  460. * 参数 : pHandle:句柄;pInfo:信息结构体指针
  461. * 返回 : FALSE:失败;TRUE:成功
  462. * 依赖 : 底层
  463. * 作者 : cp1300@139.com
  464. * 时间 : 2014-07-29
  465. * 最后修改时间 : 2014-10-08
  466. * 说明 : SIMCOM_INFO_SIZE:限制最大长度
  467. SIMCOM_VER_SIZE:软件版本长度限制
  468. 2014-10-08:在个别模块上面遇到发送AT+GMI后返回了AT+GMI,导致获取失败,如果发现返回了AT+则重新获取,可以避免此问题
  469. 2016-12-07:修改获取模块型号指令为AT+CGMM,用于兼容SIM7600
  470. *************************************************************************************************************************/
  471. bool SIMCOM_GetModuleInfo(SIMCOM_HANDLE *pHandle, SIMCOM_INFO *pInfo)
  472. {
  473. u32 i,cnt;
  474. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  475. char *p;
  476. u8 *pData;
  477. //清空缓冲区
  478. pInfo->Manu[0] = 0;
  479. pInfo->Model[0] = 0;
  480. pInfo->Ver[0] = 0;
  481. pInfo->IMEI[0] = 0;
  482. retry = SIMCOM_DEFAULT_RETRY; //重试次数
  483. //获取制造商信息
  484. do
  485. {
  486. SIMCOM_TestAT(pHandle, 10);
  487. SIMCOM_SendAT(pHandle, "AT+GMI"); //请求制造商身份
  488. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
  489. {
  490. //uart_printf("%s\r\n",pData);
  491. if(strstr((const char*)pData, "AT+") == NULL) //搜索关键字
  492. {
  493. for(i = 0;i < (SIMCOM_INFO_SIZE-1);i ++)
  494. {
  495. if((pData[2+i] == '\r') || (pData[2+i] == '\n') || (pData[2+i] == '\0')) break;
  496. pInfo->Manu[i] = pData[2+i];
  497. }
  498. pInfo->Manu[i] = 0;
  499. break;
  500. }
  501. }
  502. SIMCOM_Ready(pHandle); //等待就绪
  503. pHandle->pDelayMS(1000); //失败延时1秒后重试
  504. retry --;
  505. }while(retry);
  506. if(retry == 0) return FALSE;
  507. retry = SIMCOM_DEFAULT_RETRY; //重试次数
  508. //获取型号
  509. do
  510. {
  511. SIMCOM_SendAT(pHandle, "AT+CGMM");
  512. pHandle->pClearRxData(); //清除接收计数器
  513. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
  514. {
  515. for(i = 0;i < (SIMCOM_INFO_SIZE-1);i ++)
  516. {
  517. if((pData[2+i] == '\r') || (pData[2+i] == '\n') || (pData[2+i] == '\0')) break;
  518. pInfo->Model[i] = pData[2+i];
  519. }
  520. pInfo->Model[i] = 0;
  521. break;
  522. }
  523. SIMCOM_Ready(pHandle); //等待就绪
  524. pHandle->pDelayMS(1000); //失败延时1秒后重试
  525. retry --;
  526. }while(retry);
  527. if(retry == 0) return FALSE;
  528. retry = SIMCOM_DEFAULT_RETRY; //重试次数
  529. //获取软件版本
  530. do
  531. {
  532. SIMCOM_SendAT(pHandle, "AT+GMR");
  533. pHandle->pClearRxData(); //清除接收计数器
  534. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
  535. {
  536. p = strstr((char *)pData, "+GMR: ");
  537. if(p != NULL)
  538. {
  539. p+= strlen("+GMR: "); //SIM7600前面会有 +GMR: ,跳过即可
  540. for(i = 0;i < (SIMCOM_VER_SIZE-1);i ++)
  541. {
  542. if((p[i] == '\r') || (p[i] == '\n') || (p[i] == '\0')) break;
  543. pInfo->Ver[i] = p[i];
  544. }
  545. pInfo->Ver[i] = 0;
  546. }
  547. else
  548. {
  549. for(i = 0;i < (SIMCOM_VER_SIZE-1);i ++)
  550. {
  551. if((pData[2+i] == '\r') || (pData[2+i] == '\n') || (pData[2+i] == '\0')) break;
  552. pInfo->Ver[i] = pData[2+i];
  553. }
  554. pInfo->Ver[i] = 0;
  555. }
  556. break;
  557. }
  558. SIMCOM_Ready(pHandle); //等待就绪
  559. pHandle->pDelayMS(1000); //失败延时1秒后重试
  560. retry --;
  561. }while(retry);
  562. if(retry == 0) return FALSE;
  563. retry = SIMCOM_DEFAULT_RETRY; //重试次数
  564. //获取序列号
  565. do
  566. {
  567. SIMCOM_SendAT(pHandle, "AT+GSN");
  568. pHandle->pClearRxData(); //清除接收计数器
  569. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
  570. {
  571. for(i = 0;i < (SIMCOM_INFO_SIZE-1);i ++)
  572. {
  573. if((pData[2+i] == '\r') || (pData[2+i] == '\n') || (pData[2+i] == '\0')) break;
  574. pInfo->IMEI[i] = pData[2+i];
  575. }
  576. pInfo->IMEI[i] = 0;
  577. break;
  578. }
  579. SIMCOM_Ready(pHandle); //等待就绪
  580. pHandle->pDelayMS(1000); //失败延时1秒后重试
  581. retry --;
  582. }while(retry);
  583. return TRUE;
  584. }
  585. /*************************************************************************************************************************
  586. * 函数 : bool SIMCOM_COPS(SIMCOM_HANDLE *pHandle, char pCOPS_Buff[SIMCOM_INFO_SIZE])
  587. * 功能 : 获取运营商名称
  588. * 参数 : pHandle:句柄;pCOPS_Buff:运营商名称
  589. * 返回 : FALSE:失败;TRUE:成功
  590. * 依赖 : 底层
  591. * 作者 : cp1300@139.com
  592. * 时间 : 2014-07-29
  593. * 最后修改时间 : 2018-03-24
  594. * 说明 : SIMCOM_INFO_SIZE 限制最大长度
  595. *************************************************************************************************************************/
  596. bool SIMCOM_COPS(SIMCOM_HANDLE *pHandle, char pCOPS_Buff[SIMCOM_INFO_SIZE])
  597. {
  598. u32 i,cnt;
  599. u8 retry = 5; //重试次数
  600. char *p;
  601. u8 *pData;
  602. //清空缓冲区
  603. pCOPS_Buff[0] = 0;
  604. switch(pHandle->SimcomModeType) //不同的芯片存在不一样的初始化
  605. {
  606. case SIMCOM_SIM2000: //SIM2000需要多次读取,等待的时间比较长
  607. {
  608. retry = 28;
  609. }break;
  610. default:break;
  611. }
  612. //获取运营商
  613. do
  614. {
  615. SIMCOM_SendAT(pHandle, "AT+COPS?"); //显示模块当前注册的网络运营商
  616. pHandle->pClearRxData(); //清除接收计数器
  617. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 150)) //等待响应,超时300MS
  618. {
  619. p = strstr((const char*)pData, "\"");
  620. if(p != NULL)
  621. {
  622. p ++;
  623. for(i = 0;i < (SIMCOM_INFO_SIZE-1);i ++)
  624. {
  625. if((p[i] == '\r') || (p[i] == '\n') || (p[i] == '\0') || (p[i] == '\"')) break;
  626. pCOPS_Buff[i] = p[i];
  627. }
  628. pCOPS_Buff[i] = 0;
  629. return TRUE;
  630. }
  631. }
  632. SIMCOM_Ready(pHandle); //等待就绪
  633. pHandle->pDelayMS(1000); //延时1秒
  634. retry --;
  635. }while(retry);
  636. return FALSE; //超时//错误
  637. }
  638. /*************************************************************************************************************************
  639. * 函数 : SIMCOM_NETMODE_TYPE SIM7XXX_GetNetworkMode(SIMCOM_HANDLE *pHandle)
  640. * 功能 : 获取SIM7XXX系列模块网络制式
  641. * 参数 : pHandle:句柄
  642. * 返回 : SIMCOM_NETMODE_TYPE
  643. * 依赖 : 底层
  644. * 作者 : cp1300@139.com
  645. * 时间 : 2016-12-29
  646. * 最后修改时间 : 2018-03-24
  647. * 说明 : 用于从SIM7600模块网络制式
  648. 必须在网络注册成功后进行获取,正常返回
  649. +CNSMOD: 0,15
  650. 用于SIM7000系列获取网制式
  651. *************************************************************************************************************************/
  652. SIMCOM_NETMODE_TYPE SIM7XXX_GetNetworkMode(SIMCOM_HANDLE *pHandle)
  653. {
  654. u32 cnt;
  655. u8 retry = 3;
  656. char *p;
  657. int temp;
  658. u8 *pData;
  659. //获取型号
  660. do
  661. {
  662. SIMCOM_SendAT(pHandle, "AT+CNSMOD?");
  663. pHandle->pClearRxData(); //清除接收计数器
  664. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
  665. {
  666. p = strstr((char *)pData, "+CNSMOD: 0,");
  667. if(p==NULL) p = strstr((char *)pData, "+CNSMOD: 1,");
  668. p += strlen("+CNSMOD: 0,");
  669. temp = atoi(p);
  670. if(temp > 16) continue;
  671. else return (SIMCOM_NETMODE_TYPE)temp;
  672. }
  673. SIMCOM_Ready(pHandle); //等待就绪
  674. pHandle->pDelayMS(1000); //失败延时1秒后重试
  675. retry --;
  676. }while(retry);
  677. return SIMCOM_NETMODE_NULL;
  678. }
  679. /*************************************************************************************************************************
  680. * 函数 : bool SIMCOM_HardwarePowerUP(SIMCOM_HANDLE *pHandle, bool isTest)
  681. * 功能 : SIMCOM模块硬件开机
  682. * 参数 : pHandle:句柄;isTest:是否检测开机是否成功,通过STATUS脚变为高电平可以检测是否开机成功
  683. * 返回 : 开机是否成功
  684. * 依赖 : 无
  685. * 作者 : cp1300@139.com
  686. * 时间 : 2013-10-29
  687. * 最后修改时间 : 2018-03-24
  688. * 说明 : 用于SIM900模块开机,拉低PWR
  689. 2016-12-07:修改动态监测是否上电成功,增加SIM7600CE兼容
  690. *************************************************************************************************************************/
  691. bool SIMCOM_HardwarePowerUP(SIMCOM_HANDLE *pHandle, bool isTest)
  692. {
  693. u8 i,j;
  694. pHandle->pSetDTR_Pin(SIMCOM_L_LEVEL); //DTR=0,退出低功耗模式
  695. pHandle->s_isInitStatus = FALSE; //模块没有初始化,需要重新初始化
  696. if(isTest) //需要检测是否开机成功
  697. {
  698. if(pHandle->pGetSTATUS_Pin() == SIMCOM_H_LEVEL) //开机脚已经是高电平了
  699. {
  700. return TRUE;
  701. }
  702. for(i = 0;i < 2;i ++)
  703. {
  704. pHandle->pSetPWRKEY_Pin(SIMCOM_L_LEVEL); //拉低1200ms开机
  705. pHandle->pDelayMS(1200);
  706. pHandle->pSetPWRKEY_Pin(SIMCOM_H_LEVEL); //恢复高电平
  707. for(j = 0;j < 6;j ++)
  708. {
  709. pHandle->pDelayMS(1000);
  710. if(pHandle->pGetSTATUS_Pin() == SIMCOM_H_LEVEL) //开机脚已经是高电平了
  711. {
  712. return TRUE;
  713. }
  714. }
  715. }
  716. return FALSE;
  717. }
  718. else //无需检测是否开机成功
  719. {
  720. pHandle->pSetPWRKEY_Pin(SIMCOM_L_LEVEL); //拉低1200ms开机
  721. pHandle->pDelayMS(1200);
  722. pHandle->pSetPWRKEY_Pin(SIMCOM_H_LEVEL); //恢复高电平
  723. pHandle->pDelayMS(3000);; //延时3S等待开机完毕
  724. return TRUE;
  725. }
  726. }
  727. /*************************************************************************************************************************
  728. * 函数 : bool SIMCOM_HardwarePowerDOWN(SIMCOM_HANDLE *pHandle, bool isTest)
  729. * 功能 : SIMCOM模块硬件关机
  730. * 参数 : pHandle:句柄;isTest:是否检测开机是否成功,通过STATUS脚变为高电平可以检测是否关机成功
  731. * 返回 : 关机是否成功
  732. * 依赖 : 无
  733. * 作者 : cp1300@139.com
  734. * 时间 : 2013-10-29
  735. * 最后修改时间 : 2018-03-24
  736. * 说明 : 用于SIM900模块关机机,拉低PWR大于1S小于5S
  737. 2016-12-07:优化关机,兼容SIM7600
  738. 一定要先获取模块型号,不同模块关机时间不一样
  739. *************************************************************************************************************************/
  740. bool SIMCOM_HardwarePowerDOWN(SIMCOM_HANDLE *pHandle, bool isTest)
  741. {
  742. u8 i,j;
  743. pHandle->s_isInitStatus = FALSE; //模块没有初始化,需要重新初始化
  744. if(isTest) //需要检测是否开机成功
  745. {
  746. if(pHandle->pGetSTATUS_Pin() == SIMCOM_L_LEVEL) //开机脚已经是低电平了
  747. {
  748. return TRUE;
  749. }
  750. for(i = 0;i < 2;i ++)
  751. {
  752. pHandle->pSetPWRKEY_Pin(SIMCOM_L_LEVEL); //拉低1200ms关机
  753. switch(pHandle->SimcomModeType)
  754. {
  755. case SIMCOM_SIM7600:
  756. {
  757. pHandle->pDelayMS(3000); //SIM7600关机至少2.5S
  758. }break;
  759. default:
  760. {
  761. pHandle->pDelayMS(1000);
  762. }break;
  763. }
  764. pHandle->pDelayMS(200);
  765. pHandle->pSetPWRKEY_Pin(SIMCOM_H_LEVEL); //恢复高电平
  766. for(j = 0;j < 5;j ++)
  767. {
  768. pHandle->pDelayMS(3000); //延时3S等待关机完毕
  769. if(pHandle->pGetSTATUS_Pin() == SIMCOM_L_LEVEL) //开机脚已经是低电平了
  770. {
  771. return TRUE;
  772. }
  773. }
  774. }
  775. return FALSE;
  776. }
  777. else //无需检测是否开机成功
  778. {
  779. pHandle->pSetPWRKEY_Pin(SIMCOM_L_LEVEL); //拉低1200ms关机
  780. pHandle->pDelayMS(1200);
  781. pHandle->pSetPWRKEY_Pin(SIMCOM_H_LEVEL); //恢复高电平
  782. pHandle->pDelayMS(3000);; //延时3S等待关机完毕
  783. return TRUE;
  784. }
  785. }
  786. /*************************************************************************************************************************
  787. * 函数 : SIMCOM_MODE_TYPE SIMCOM_GetMode(SIMCOM_HANDLE *pHandle)
  788. * 功能 : 获取SIMCOM模块的型号
  789. * 参数 : pHandle:句柄
  790. * 返回 : 型号,见SIMCOM_MODE_TYPE
  791. * 依赖 : 底层
  792. * 作者 : cp1300@139.com
  793. * 时间 : 2015-09-12
  794. * 最后修改时间 : 2015-09-12
  795. * 说明 : 用于识别型号,对应初始化
  796. 2016-12-07:修改指令为AT+CGMM,兼容SIM7600,(旧指令:AT+GOI)
  797. *************************************************************************************************************************/
  798. SIMCOM_MODE_TYPE SIMCOM_GetMode(SIMCOM_HANDLE *pHandle)
  799. {
  800. u32 cnt;
  801. u8 retry = SIMCOM_DEFAULT_RETRY+1;
  802. u8 *pData;
  803. //获取型号
  804. do
  805. {
  806. SIMCOM_SendAT(pHandle, "AT+CGMM");
  807. pHandle->pClearRxData(); //清除接收计数器
  808. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
  809. {
  810. if(strstr((char *)pData, "SIM900") != NULL) return SIMCOM_SIM900;
  811. else if(strstr((char *)pData, "SIM800") != NULL) return SIMCOM_SIM800;
  812. else if(strstr((char *)pData, "SIM2000") != NULL) return SIMCOM_SIM2000;
  813. else if(strstr((char *)pData, "SIM7600") != NULL) return SIMCOM_SIM7600;
  814. else if(strstr((char *)pData, "SIMCOM_SIM868") != NULL) return SIMCOM_SIM868;
  815. else if(strstr((char *)pData, "SIMCOM_SIM7000C") != NULL) return SIMCOM_SIM7000C;
  816. else if(strstr((char *)pData, "LYNQ_L700") != NULL) return LYNQ_L700;
  817. else
  818. {
  819. uart_printf("未知通信模块:%s\r\n",pData);
  820. return SIMCOM_INVALID;
  821. }
  822. }
  823. SIMCOM_Ready(pHandle); //等待就绪
  824. pHandle->pDelayMS(1000); //失败延时1秒后重试
  825. retry --;
  826. }while(retry);
  827. return SIMCOM_INVALID;
  828. }
  829. /*************************************************************************************************************************
  830. * 函数 : bool SIMCOM_GetServeNumber(PHONE_NUMBER *pServeNumber)
  831. * 功能 : 获取短信服务中心号码(会去掉前面的86,限制长度15位,不能用于SIM7000,SIM2000以及电信卡)
  832. * 参数 : pServeNumber:电话号码存储缓冲区指针
  833. * 返回 : FALSE:通信失败;TRUE:通信成功
  834. * 依赖 : 底层
  835. * 作者 : cp1300@139.com
  836. * 时间 : 2013-10-20
  837. * 最后修改时间 : 2013-10-20
  838. * 说明 : 获取SIM卡内部的短信服务中心号码,一般在办理SIM卡的时候已经进行了设置.
  839. 如果没有预置短信中心号码需要使用手机进行设置
  840. 2014-07-12:只要返回OK则认为成功,因为有可能没有设置短信中心号码
  841. 2016-01-26:自动选择是否跳过+86
  842. *************************************************************************************************************************/
  843. bool SIMCOM_GetServeNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16])
  844. {
  845. u8 i,n;
  846. u32 cnt;
  847. char *p,*p1;
  848. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  849. u8 *pData;
  850. do
  851. {
  852. //+CSCA: "+8613800270500",145
  853. SIMCOM_SendAT(pHandle, "AT+CSCA?"); //发送"AT+CSCA",获取短信服务中心号码
  854. pHandle->pClearRxData(); //清除接收计数器
  855. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 30, 600)) //等待响应,超时600MS
  856. {
  857. p = strstr((const char*)pData, "+CSCA:"); //搜索字符"+CSCA:"
  858. if(p != NULL) //搜索成功
  859. {
  860. p = strstr(p+1, "+"); //搜索"+"
  861. if(p != NULL)
  862. {
  863. p1 = strstr(p+1, "\""); //搜索"\""
  864. if(p1 != NULL)
  865. {
  866. if(p[0] == '+') //如果是+开头,则跳过加号
  867. {
  868. p+=3; //跳过+86
  869. }
  870. else if(p[0]=='8' && p[1] == '6') //跳过86
  871. {
  872. p+=2;
  873. }
  874. n = p1 - p; //计算电话号码长度
  875. if(n > 15) n = 15; //限制号码长度为15字节
  876. for(i = 0;i < n;i ++)
  877. {
  878. pPhoneNumber[i] = p[i]; //复制电话号码
  879. }
  880. pPhoneNumber[i] = '\0'; //添加结束符
  881. SIMCOM_GSM_debug("短信中心号码:%s\r\n",pPhoneNumber);
  882. return TRUE;
  883. }
  884. }
  885. }
  886. else
  887. {
  888. pPhoneNumber[0] = '\0';
  889. SIMCOM_GSM_debug("短信中心号码:为空,没有设置\r\n");
  890. return TRUE;
  891. }
  892. }
  893. SIMCOM_Ready(pHandle); //等待就绪
  894. pHandle->pDelayMS(1000); //失败延时1秒后重试
  895. retry --;
  896. }while(retry);
  897. return FALSE;
  898. }
  899. /*************************************************************************************************************************
  900. * 函数 : bool SIMCOM_GetPhoneNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16])
  901. * 功能 : 获取本机号码(会去掉前面的86,限制长度15位,不能用于SIM7000,SIM2000以及电信卡)
  902. * 参数 : pHandle:句柄;pPhoneNumber:号码缓冲区
  903. * 返回 : FALSE:通信失败;TRUE:通信成功
  904. * 依赖 : 底层
  905. * 作者 : cp1300@139.com
  906. * 时间 : 2013-10-20
  907. * 最后修改时间 : 2018-03-24
  908. * 说明 : 通常会预存本机号码到SIM卡,也可能没有(不能用于SIM7000,SIM2000C,不能用于电信卡)
  909. 2014-07-12:只要返回OK则认为成功,因为有可能没有设置电话号码
  910. 2016-01-26:修改字节超时,否则某些卡会出现超时,没有收到OK
  911. 自动选择是否跳过+86
  912. *************************************************************************************************************************/
  913. bool SIMCOM_GetPhoneNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16])
  914. {
  915. u8 n;
  916. u8 i;
  917. u32 cnt;
  918. char *p,*p1;
  919. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  920. u8 *pData;
  921. do
  922. {
  923. //+CNUM: "","15871750634",129,7,4
  924. SIMCOM_SendAT(pHandle, "AT+CNUM"); //发送"AT++CNUM",获取号码
  925. pHandle->pClearRxData(); //清除接收计数器
  926. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 30, 600)) //等待响应,超时600MS
  927. {
  928. p = strstr((const char*)pData, "+CNUM:"); //搜索字符"+CNUM:"
  929. if(p != NULL) //搜索成功
  930. {
  931. p = strstr(p+1, "\",\""); //搜索"," //开始
  932. if(p != NULL)
  933. {
  934. p1 = strstr(p+3, "\","); //搜索",//结束
  935. if(p1 != NULL)
  936. {
  937. p+=3; //跳过","
  938. if(p[0] == '+') //如果是+开头,则跳过加号
  939. {
  940. p+=3; //跳过+86
  941. }
  942. else if(p[0]=='8' && p[1] == '6') //跳过86
  943. {
  944. p+=2;
  945. }
  946. n = p1 - p; //计算电话号码长度
  947. if(n > 15) n = 15; //限制号码长度为15字节
  948. for(i = 0;i < n;i ++)
  949. {
  950. pPhoneNumber[i] = p[i]; //复制电话号码
  951. }
  952. pPhoneNumber[i] = '\0'; //添加结束符
  953. SIMCOM_GSM_debug("本机号码:%s\r\n",pPhoneNumber);
  954. return TRUE;
  955. }
  956. }
  957. }
  958. else
  959. {
  960. pPhoneNumber[0] = '\0';
  961. SIMCOM_GSM_debug("本机号码:为空,没有设置\r\n");
  962. return TRUE;
  963. }
  964. }
  965. SIMCOM_Ready(pHandle); //等待就绪
  966. pHandle->pDelayMS(1000); //失败延时1秒后重试
  967. retry --;
  968. }while(retry);
  969. return FALSE;
  970. }
  971. /*************************************************************************************************************************
  972. * 函数 : bool SIMCOM_GetBookNumber(SIMCOM_HANDLE *pHandle, u8 index, char pPhoneNumber[16])
  973. * 功能 : 从电话簿获取一个电话号码(不能用于SIM7000)
  974. * 参数 : pHandle:句柄;index:电话号码所有,1-255;CenterPhone:电话号码存储缓冲区指针
  975. * 返回 : FALSE:通信失败;TRUE:通信成功
  976. * 依赖 : 底层
  977. * 作者 : cp1300@139.com
  978. * 时间 : 2013-10-20
  979. * 最后修改时间 : 2016-06-15
  980. * 说明 : 用于从电话簿读取一个电话号码,常用语电信卡SIM2000C模块存储本机号码到第一个索引
  981. *************************************************************************************************************************/
  982. bool SIMCOM_GetBookNumber(SIMCOM_HANDLE *pHandle, u8 index, char pPhoneNumber[16])
  983. {
  984. u8 i,n;
  985. u32 cnt;
  986. char *p,*p1;
  987. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  988. u8 *pData;
  989. char buff[32];
  990. if(index < 1) return FALSE; //索引从1开始
  991. do
  992. {
  993. //+CPBR: 1,"152778787878",129,"Phone"
  994. sprintf(buff,"AT+CPBR=%d",index);
  995. SIMCOM_SendAT(pHandle, buff); //发送"AT+CPBR=1",获取号码
  996. pHandle->pClearRxData(); //清除接收计数器
  997. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 30, 600)) //等待响应,超时600MS
  998. {
  999. p = strstr((const char*)pData, "+CPBR:"); //搜索字符"+CPBR:"
  1000. if(p != NULL) //搜索成功
  1001. {
  1002. p = strstr(p+1, ",\""); //搜索," //开始
  1003. if(p != NULL)
  1004. {
  1005. p1 = strstr(p+2, "\","); //搜索",//结束
  1006. if(p1 != NULL)
  1007. {
  1008. p+=2; //跳过,"
  1009. if(p[0] == '+') //如果是+开头,则跳过加号
  1010. {
  1011. p+=3; //跳过+86
  1012. }
  1013. else if(p[0]=='8' && p[1] == '6') //跳过86
  1014. {
  1015. p+=2;
  1016. }
  1017. n = p1 - p; //计算电话号码长度
  1018. if(n > 15) n = 15; //限制号码长度为15字节
  1019. for(i = 0;i < n;i ++)
  1020. {
  1021. pPhoneNumber[i] = p[i]; //复制电话号码
  1022. }
  1023. pPhoneNumber[i] = '\0'; //添加结束符
  1024. SIMCOM_GSM_debug("号码:%s\r\n",pPhoneNumber);
  1025. return TRUE;
  1026. }
  1027. }
  1028. }
  1029. else
  1030. {
  1031. pPhoneNumber[0] = '\0';
  1032. SIMCOM_GSM_debug("号码:为空\r\n");
  1033. return TRUE;
  1034. }
  1035. }
  1036. SIMCOM_Ready(pHandle); //等待就绪
  1037. pHandle->pDelayMS(1000); //失败延时1秒后重试
  1038. retry --;
  1039. }while(retry);
  1040. return FALSE;
  1041. }
  1042. /*************************************************************************************************************************
  1043. * 函数 : int SIMCOM_GetSignal(SIMCOM_HANDLE *pHandle)
  1044. * 功能 : 获取信号强度
  1045. * 参数 : pHandle:句柄
  1046. * 返回 : <0:获取失败;0-31:信号强度;
  1047. * 依赖 : 底层
  1048. * 作者 : cp1300@139.com
  1049. * 时间 : 2013-10-21
  1050. * 最后修改时间 : 2013-10-21
  1051. * 说明 : 无
  1052. *************************************************************************************************************************/
  1053. int SIMCOM_GetSignal(SIMCOM_HANDLE *pHandle)
  1054. {
  1055. u8 temp;
  1056. u32 cnt;
  1057. char *p;
  1058. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  1059. u8 *pData;
  1060. do
  1061. {
  1062. //+CSQ: 27,0
  1063. //+CSQ: 5,0
  1064. //+CSQ: 16,99
  1065. SIMCOM_SendAT(pHandle,"AT+CSQ"); //发送"AT++CSQ",获取号码
  1066. pHandle->pClearRxData(); //清除接收计数器
  1067. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 400)) //等待响应,超时400MS
  1068. {
  1069. p = strstr((const char*)pData, "+CSQ:"); //搜索字符"+CSQ:"
  1070. if(p != NULL) //搜索成功
  1071. {
  1072. if(p[7] != ',' && p[8] != ',') p[8] = '\0';
  1073. temp = atoi(&p[6]);
  1074. return temp;
  1075. }
  1076. break;
  1077. }
  1078. SIMCOM_Ready(pHandle); //等待就绪
  1079. pHandle->pDelayMS(1000); //失败延时1秒后重试
  1080. retry --;
  1081. }while(retry);
  1082. return -1;
  1083. }
  1084. /*************************************************************************************************************************
  1085. * 函数 : bool SIMCOM_GetCIMI(SIMCOM_HANDLE *pHandle, char pCIMI[16])
  1086. * 功能 : 获取SIM卡CIMI号码(SIM卡唯一id,必须存在)
  1087. * 参数 : pHandle:句柄;pCIMI:CIMI缓冲区,长15字节
  1088. * 返回 : FALSE:通信失败;TRUE:通信成功
  1089. * 依赖 : 底层
  1090. * 作者 : cp1300@139.com
  1091. * 时间 : 2017-11-16
  1092. * 最后修改时间 : 2018-03-24
  1093. * 说明 : 用于获取卡唯一CIMI编号,防止某些卡无法读取本机号码,这个与卡号一一对应
  1094. *************************************************************************************************************************/
  1095. bool SIMCOM_GetCIMI(SIMCOM_HANDLE *pHandle, char pCIMI[16])
  1096. {
  1097. u32 cnt;
  1098. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  1099. u8 *pData;
  1100. do
  1101. {
  1102. //460041037206894
  1103. SIMCOM_SendAT(pHandle, "AT+CIMI"); //发送"AT+CIMI"
  1104. pHandle->pClearRxData(); //清除接收计数器
  1105. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 200)) //等待响应,超时200MS
  1106. {
  1107. if(pData[0]!='\r' || pData[1]!='\n') continue;
  1108. memcpy(pCIMI, &pData[2], 15); //跳过前面\r\n
  1109. pCIMI[15] = 0; //添加结束符
  1110. SIMCOM_GSM_debug("获取CIMI成功:%s\r\n", pCIMI);
  1111. return TRUE;
  1112. }
  1113. SIMCOM_Ready(pHandle); //等待就绪
  1114. pHandle->pDelayMS(1000); //失败延时1秒后重试
  1115. retry --;
  1116. }while(retry);
  1117. return FALSE;
  1118. }
  1119. /*************************************************************************************************************************
  1120. * 函数 : bool SIM7000C_GetNB_APN(SIMCOM_HANDLE *pHandle, char pAPN[17])
  1121. * 功能 : 获取SIM7000C NBIOT 接入点
  1122. * 参数 : pHandle:句柄;pAPN:接入点缓冲区
  1123. * 返回 : TRUE:成功;FALSE:失败
  1124. * 依赖 : 底层
  1125. * 作者 : cp1300@139.com
  1126. * 时间 : 2018-01-16
  1127. * 最后修改时间 : 2018-01-16
  1128. * 说明 : 必须是NBIOT模式才能使用
  1129. *************************************************************************************************************************/
  1130. bool SIM7000C_GetNB_APN(SIMCOM_HANDLE *pHandle, char pAPN[17])
  1131. {
  1132. u32 cnt;
  1133. char *p;
  1134. u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
  1135. u8 *pData;
  1136. u8 i;
  1137. do
  1138. {
  1139. //+CGNAPN: 1,"ctnb"
  1140. SIMCOM_SendAT(pHandle, "AT+CGNAPN"); //发送AT指令
  1141. pHandle->pClearRxData(); //清除接收计数器
  1142. if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 2000)) //等待响应,超时2000MS
  1143. {
  1144. p = strstr((const char*)pData, "+CGNAPN: 1,\""); //搜索字符+CGNAPN: 1,"
  1145. if(p != NULL) //搜索成功
  1146. {
  1147. p += strlen("+CGNAPN: 1,\"");
  1148. for(i = 0;i < 17;i ++)
  1149. {
  1150. if(p[i] == '\"') //结束符号位 ”
  1151. {
  1152. pAPN[i] = 0;
  1153. if(i == 0) break; //太短了
  1154. return TRUE;
  1155. }
  1156. pAPN[i] = p[i];
  1157. }
  1158. }
  1159. }
  1160. SIMCOM_Ready(pHandle); //等待就绪
  1161. pHandle->pDelayMS(1000); //失败延时1秒后重试
  1162. retry --;
  1163. }while(retry);
  1164. return FALSE;
  1165. }

//SIMCOM_GSM.h

  1. /*************************************************************************************************************
  2. * 文件名: SIMCOM_GSM.h
  3. * 功能: SIMCOM GSM相关接口
  4. * 作者: cp1300@139.com
  5. * 创建时间: 2015-02-15
  6. * 最后修改时间: 2018-03-23
  7. * 详细:
  8. *************************************************************************************************************/
  9. #ifndef _SIMCOM_GSM_H_
  10. #define _SIMCOM_GSM_H_
  11. #include "system.h"
  12. #include "simcom.h"
  13. bool SIMCOM_NetworkConfig(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, NETWORK_CONFIG_TYPE *pConfig); //SIMCOM网络配置
  14. SIM_CARD_STATUS SIMCOM_GetCPIN(SIMCOM_HANDLE *pHandle); //获取SIM卡状态
  15. SIMCOM_NETSTATUS SIM900_GetGSMNetworkStatus(SIMCOM_HANDLE *pHandle); //获取GSM网络注册状态
  16. SIMCOM_NETSTATUS SIMCOM_GetDataNetworkStatus(SIMCOM_HANDLE *pHandle); //获取数据网络注册状态
  17. bool SIMCOM_ModuleInit(SIMCOM_HANDLE *pHandle); //初始化SIMCOM模块基本配置(不允许失败)
  18. bool SIMCOM_GetModuleInfo(SIMCOM_HANDLE *pHandle, SIMCOM_INFO *pInfo); //获取模块的相关信息
  19. bool SIMCOM_COPS(SIMCOM_HANDLE *pHandle, char pCOPS_Buff[SIMCOM_INFO_SIZE]); //获取运营商名称
  20. SIMCOM_NETMODE_TYPE SIM7XXX_GetNetworkMode(SIMCOM_HANDLE *pHandle); //获取SIM7XXX系列模块网络制式
  21. bool SIMCOM_HardwarePowerUP(SIMCOM_HANDLE *pHandle, bool isTest); //SIMCOM模块硬件开机
  22. bool SIMCOM_HardwarePowerDOWN(SIMCOM_HANDLE *pHandle, bool isTest); //SIMCOM模块硬件关机
  23. SIMCOM_MODE_TYPE SIMCOM_GetMode(SIMCOM_HANDLE *pHandle); //获取SIMCOM模块的型号
  24. int SIMCOM_GetSignal(SIMCOM_HANDLE *pHandle); //获取信号强度
  25. bool SIMCOM_GetBookNumber(SIMCOM_HANDLE *pHandle, u8 index, char pPhoneNumber[16]); //从电话簿获取一个电话号码(不能用于SIM7000)
  26. bool SIMCOM_GetPhoneNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16]); //获取本机号码(会去掉前面的86,限制长度15位,不能用于SIM7000,SIM2000以及电信卡)
  27. bool SIMCOM_GetServeNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16]); //获取短信服务中心号码(会去掉前面的86,限制长度15位,不能用于SIM7000,SIM2000以及电信卡)
  28. bool SIMCOM_GetCIMI(SIMCOM_HANDLE *pHandle, char pCIMI[16]); //获取SIM卡CIMI号码(SIM卡唯一id,必须存在)
  29. bool SIM7000C_GetNB_APN(SIMCOM_HANDLE *pHandle, char pAPN[17]); //获取SIM7000C NBIOT 接入点
  30. #endif /*_SIMCOM_GSM_H_*/

//SIMCOM_USER.c

  1. /*************************************************************************************************************
  2. * 文件名: SIMCOM_USER.c
  3. * 功能: SIMCOM用户层函数
  4. * 作者: cp1300@139.com
  5. * 创建时间: 2015-02-15
  6. * 最后修改时间: 2018-03-23
  7. * 详细:
  8. *************************************************************************************************************/
  9. #include "system.h"
  10. #include "usart.h"
  11. #include "string.h"
  12. #include "ucos_ii.h"
  13. #include "SIMCOM_USER.h"
  14. #include "SIMCOM_GSM.h"
  15. #include "SIMCOM_GPRS.h"
  16. #include "SIMCOM_AT.h"
  17. #include "SIMCOM.h"
  18. bool g_SIMC0M_USER_Debug = TRUE; //应用层指令调试状态
  19. //调试开关
  20. #define SIMCOM_USER_DBUG 1
  21. #if SIMCOM_USER_DBUG
  22. #include "system.h"
  23. #define SIMCOM_USER_debug(format,...) {if(g_SIMC0M_USER_Debug){uart_printf(format,##__VA_ARGS__);}}
  24. #else
  25. #define SIMCOM_USER_debug(format,...) /\
  26. /
  27. #endif //SIMCOM_USER_DBUG
  28. const char *const SIMCOM_NETWORK_NAME[18] = {"未注册","GSM","GPRS","EGPRS (EDGE)","WCDMA","HSDPA only(WCDMA)","HSUPA only(WCDMA)","HSPA (HSDPA and HSUPA, WCDMA)",
  29. "LTE","TDS-CDMA","TDS-HSDPA only","TDS-HSUPA only","TDS- HSPA (HSDPA and HSUPA)","CDMA","EVDO","HYBRID (CDMA and EVDO)","1XLTE(CDMA and LTE)","未知,错误"};
  30. /*************************************************************************************************************************
  31. * 函数 : bool SIMCOM_Init(SIMCOM_HANDLE *pHandle,
  32. bool (* pSendData)(u8 *pDataBuff, u16 DataLen),
  33. int (* pReadData)(u8 **pDataBuff, u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelay),
  34. void (*pClearRxData)(void),
  35. void (*pSetDTR_Pin)(u8 Level),
  36. void (*pSetPWRKEY_Pin)(u8 Level),
  37. u8 (*pGetSTATUS_Pin)(void),
  38. u8 (*pGetDCD_Pin)(void),
  39. void (*pDelayMS)(u32 ms),
  40. void (*pIWDG_Feed)(void)
  41. * 功能 : 初始化SIMCOM句柄接口
  42. * 参数 : pSl651_Handle:句柄;
  43. pSendCallBack:发送回调函数(pDataBuff:发送数据缓冲区,DataLen:发送数据长度)
  44. pReadCallBack:接收数据回调函数,会等待直到数据被写入到接收缓冲区(pDataBuff:接收数据缓冲区,ByteTimeOut:等待的字节超时时间,单位ms,TimeOut:数据包超时时间,单位ms)
  45. pClearRxData:清除接收缓冲区函数,用于清除接收数据缓冲区数据
  46. pSetDTR_Pin:DTR引脚电平控制-用于控制sleep模式或者退出透传模式
  47. pSetPWRKEY_Pin:PWRKEY开机引脚电平控制-用于开机
  48. pGetSTATUS_Pin:获取STATUS引脚电平-用于指示模块上电状态
  49. pGetDCD_Pin:获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
  50. pDelayMS:系统延时函数
  51. pIWDG_Feed:清除系统看门狗(可以为空)
  52. * 返回 : 无
  53. * 依赖 : TRUE:成功,FALSE:失败
  54. * 作者 : cp1300@139.com
  55. * 时间 : 2018-03-24
  56. * 最后修改时间 : 2018-03-24
  57. * 说明 : 除pIWDG_Feed接口可以为空,其余接口均不能为空,否则程序会崩溃
  58. *************************************************************************************************************************/
  59. bool SIMCOM_Init(SIMCOM_HANDLE *pHandle,
  60. bool (* pSendData)(u8 *pDataBuff, u16 DataLen), //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
  61. int (* pReadData)(u8 **pDataBuff, u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelay), //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
  62. void (*pClearRxData)(void), //清除接收缓冲区函数,用于清除接收数据缓冲区数据
  63. void (*pSetDTR_Pin)(u8 Level), //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
  64. void (*pSetPWRKEY_Pin)(u8 Level), //PWRKEY开机引脚电平控制-用于开机
  65. u8 (*pGetSTATUS_Pin)(void), //获取STATUS引脚电平-用于指示模块上电状态
  66. u8 (*pGetDCD_Pin)(void), //获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
  67. void (*pDelayMS)(u32 ms), //系统延时函数
  68. void (*pIWDG_Feed)(void) //清除系统看门狗(可以为空)
  69. )
  70. {
  71. if(pHandle == NULL)
  72. {
  73. DEBUG("无效的句柄!\r\n");
  74. return FALSE;
  75. }
  76. //所需变量
  77. pHandle->SimcomModeType = SIMCOM_INVALID; //模块型号
  78. pHandle->TelecomCarr[0] = 0; //运营商名称
  79. memset(&pHandle->SIMCOM_Info, 0, sizeof(SIMCOM_INFO)); //SIMCOM通信模块相关信息结构体
  80. memset(&pHandle->NetworkConfig, 0, sizeof(NETWORK_CONFIG_TYPE)); //网络模式设置
  81. pHandle->NetworkMode = SIMCOM_NETMODE_NULL; //当前网络制式
  82. //底层通信接口
  83. pHandle->pSendData = pSendData; //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
  84. pHandle->pReadData = pReadData; //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
  85. pHandle->pClearRxData = pClearRxData; //清除接收缓冲区函数,用于清除接收数据缓冲区数据
  86. pHandle->pSetDTR_Pin = pSetDTR_Pin; //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
  87. pHandle->pSetPWRKEY_Pin = pSetPWRKEY_Pin; //PWRKEY开机引脚电平控制-用于开机
  88. pHandle->pGetSTATUS_Pin = pGetSTATUS_Pin; //获取STATUS引脚电平-用于指示模块上电状态
  89. pHandle->pGetDCD_Pin = pGetDCD_Pin; //获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
  90. //系统接口
  91. pHandle->pDelayMS = pDelayMS; //系统延时函数
  92. pHandle->pIWDG_Feed = pIWDG_Feed; //清除系统看门狗(可以为空)
  93. //内部状态定义
  94. pHandle->s_isInitStatus = FALSE; //用于记录模块初始化状态,复位或上电后变为无效
  95. //检查是否有接口为空
  96. if(pHandle->pSendData==NULL || pHandle->pReadData==NULL || pHandle->pClearRxData==NULL || pHandle->pSetDTR_Pin==NULL || pHandle->pSetPWRKEY_Pin==NULL ||
  97. pHandle->pGetSTATUS_Pin==NULL || pHandle->pGetDCD_Pin==NULL || pHandle->pDelayMS==NULL)
  98. {
  99. DEBUG("错误,有回调接口为空!\r\n");
  100. return FALSE;
  101. }
  102. return TRUE;
  103. }
  104. /*************************************************************************************************************************
  105. * 函数 : void SIMCOM_PrintfModel(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, const char **pModeInof)
  106. * 功能 : 显示并打印模块型号
  107. * 参数 : pHandle:句柄;ModeType:模块型号;pModeInof:返回模块型号信息(不需要可以为空)
  108. * 返回 : 无
  109. * 依赖 : 底层
  110. * 作者 : cp1300@139.com
  111. * 时间 : 2017-10-17
  112. * 最后修改时间 : 2018-03-24
  113. * 说明 :
  114. *************************************************************************************************************************/
  115. void SIMCOM_PrintfModel(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, const char **pModeInof)
  116. {
  117. switch(ModeType)
  118. {
  119. case SIMCOM_SIM900 : //默认为SIM900
  120. {
  121. if(pModeInof!=NULL) *pModeInof = "SIM900系列";//通信模块型号
  122. uart_printf("[DTU]通信模块为SIM900\r\n");
  123. }break;
  124. case SIMCOM_SIM800 : //SIM800
  125. {
  126. if(pModeInof!=NULL) *pModeInof = "SIM800系列"; //通信模块型号
  127. uart_printf("[DTU]通信模块为SIM800\r\n");
  128. }break;
  129. case SIMCOM_SIM2000 : //SIM2000
  130. {
  131. if(pModeInof!=NULL) *pModeInof = "SIM2000系列"; //通信模块型号
  132. uart_printf("[DTU]通信模块为SIM2000\r\n");
  133. }break;
  134. case SIMCOM_SIM7600 : //SIM7600
  135. {
  136. if(pModeInof!=NULL) *pModeInof = "SIM7600系列"; //通信模块型号
  137. uart_printf("[DTU]通信模块为SIM7600\r\n");
  138. }break;
  139. case SIMCOM_SIM868: //SIM868
  140. {
  141. if(pModeInof!=NULL) *pModeInof = "SIM868系列"; //通信模块型号
  142. uart_printf("[DTU]通信模块为SIM868模块\r\n");
  143. }break;
  144. case SIMCOM_SIM7000C: //SIM7000C
  145. {
  146. if(pModeInof!=NULL) *pModeInof = "SIM7000C系列"; //通信模块型号
  147. uart_printf("[DTU]通信模块为SIM7000C\r\n");
  148. }break;
  149. case LYNQ_L700: //LYNQ_L700
  150. {
  151. if(pModeInof!=NULL) *pModeInof = "L700系列"; //通信模块型号
  152. uart_printf("[DTU]通信模块为L700模块\r\n");
  153. }break;
  154. case SIMCOM_INVALID : //无效则默认
  155. {
  156. if(pModeInof!=NULL) *pModeInof = "未知"; //通信模块型号
  157. uart_printf("[DTU]通信模块未知!\r\n");
  158. }break;
  159. }
  160. }
  161. /*************************************************************************************************************************
  162. * 函数 : SIMCOM_USER_ERROR SIMCOM_RegisNetwork(SIMCOM_HANDLE *pHandle, u16 Retry, u16 NetworkDelay,const char **pModeInof)
  163. * 功能 : SIMCOM模块上电初始化并注册网络
  164. * 参数 : pHandle:句柄;Retry:初始化重试次数>0;NetworkDelay:注册网络延时时间,单位S;pModeInof:返回模块型号信息(不需要可以为空)
  165. * 返回 : SIMCOM_USER_ERROR
  166. * 依赖 : 底层
  167. * 作者 : cp1300@139.com
  168. * 时间 : 2014-08-18
  169. * 最后修改时间 : 2018-03-24
  170. * 说明 : 用于通信模块上电并初始化操作
  171. *************************************************************************************************************************/
  172. SIMCOM_USER_ERROR SIMCOM_RegisNetwork(SIMCOM_HANDLE *pHandle, u16 Retry, u16 NetworkDelay,const char **pModeInof)
  173. {
  174. SIMCOM_NETSTATUS NetStatus;
  175. SIMCOM_MODE_TYPE ModeType = SIMCOM_INVALID; //初始化模块型号无效
  176. SIMCOM_NETMODE_TYPE NetworkMode = SIMCOM_NETMODE_NULL; //初始化为未知模式
  177. SIMCOM_USER_ERROR Error = SIMCOM_NULL_ERROR; //初始化状态
  178. u16 pcnt,cnt;
  179. u8 NotCnt,SeaCnt,TurCnt,UnkCnt,ErrCnt;
  180. bool isCart = FALSE;
  181. u8 SIM_NotReadyCnt = 0; //SIM卡未准备就绪计数器
  182. Retry += 1; //重试次数至少1次
  183. //模块上电
  184. for(pcnt = 0;pcnt < Retry;pcnt ++) //上电循环
  185. {
  186. SIM_NotReadyCnt = 0; //SIM卡未准备就绪计数器复位
  187. if(pHandle->pIWDG_Feed!=NULL) pHandle->pIWDG_Feed(); //喂狗
  188. if(pHandle->pGetSTATUS_Pin()==SIMCOM_L_LEVEL) //模块没有上电
  189. {
  190. pHandle->s_isInitStatus = FALSE; //模块没有初始化
  191. SIMCOM_USER_debug("[SIMCOM]:模块没有上电!\r\n");
  192. if(SIMCOM_HardwarePowerUP(pHandle, TRUE) == TRUE) //上电
  193. {
  194. SIMCOM_USER_debug("[SIMCOM]:开机成功!\r\n");
  195. if(SIMCOM_TestAT(pHandle, 50) != TRUE) //发送AT测试命令
  196. {
  197. if(pModeInof!=NULL) *pModeInof = "模块未知";
  198. SIMCOM_USER_debug("[SIMCOM]:通信错误,串口错误!\r\n");
  199. }
  200. }
  201. else
  202. {
  203. if(pModeInof!=NULL) *pModeInof = "模块未知";
  204. SIMCOM_USER_debug("[SIMCOM]:开机失败!\r\n");
  205. Error = SIMCOM_POWER_UP_ERROR; //开机失败
  206. }
  207. }
  208. //上电完毕后初始化模块
  209. if(pHandle->pGetSTATUS_Pin() == SIMCOM_H_LEVEL)
  210. {
  211. //模块初始化网络
  212. if(NetworkDelay == 0) NetworkDelay = 0xffff; //为0,一直等待
  213. NotCnt=SeaCnt=TurCnt=UnkCnt=ErrCnt=0; //初始化注册状态计数器为0
  214. //获取模块型号
  215. if(ModeType == SIMCOM_INVALID)
  216. {
  217. SIMCOM_SetParametersReturnBool(pHandle, "ATE 0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭AT回显模式失败!\r\n");
  218. pHandle->pDelayMS(500);
  219. ModeType = SIMCOM_GetMode(pHandle); //获取模块型号
  220. SIMCOM_PrintfModel(pHandle, ModeType, pModeInof); //打印显示通信模块型号
  221. }
  222. //型号获取成功了,更新信息
  223. if(ModeType!=SIMCOM_INVALID)
  224. {
  225. pHandle->SimcomModeType = ModeType; //上电初始化设置通信模块型号
  226. }
  227. //根据模块类型进行初始化,如果是SIM7000C,需要选择工作在GSM模式还是NBIOT模式
  228. if(SIMCOM_NetworkConfig(pHandle, ModeType, &pHandle->NetworkConfig)==FALSE)
  229. {
  230. uart_printf("[DTU]初始化通信模块网络模式失败了!\r\n");
  231. }
  232. //初始化获取网络信息
  233. for(cnt = 0;cnt < NetworkDelay;cnt ++)
  234. {
  235. if(pHandle->pGetSTATUS_Pin()==SIMCOM_L_LEVEL)
  236. {
  237. Error = SIMCOM_POWER_UP_ERROR; //异常断电
  238. uart_printf("[DTU]异常断电了,请检查供电是否稳定!\r\n");
  239. break; //模块没有上电,初始化
  240. }
  241. if(ModeType == SIMCOM_INVALID)
  242. {
  243. SIMCOM_SetParametersReturnBool(pHandle, "ATE 0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭AT回显模式失败!\r\n");
  244. pHandle->pDelayMS(500);
  245. ModeType = SIMCOM_GetMode(pHandle); //获取模块型号
  246. pHandle->SimcomModeType = ModeType; //上电初始化设置通信模块型号
  247. SIMCOM_PrintfModel(pHandle, ModeType, pModeInof); //打印显示通信模块型号
  248. }
  249. if(isCart == FALSE) //卡未检测到,则一直重新检测
  250. {
  251. if(SIMCOM_GetCPIN(pHandle)==SIM_READY)
  252. {
  253. isCart = TRUE; //卡检测成功
  254. uart_printf("\r\nSIM卡准备就绪!\r\n");
  255. }
  256. else
  257. {
  258. uart_printf("\r\nSIM卡未准备就绪!\r\n");
  259. Error = SIMCOM_SIM_NOT_REALYE; //卡未就绪
  260. }
  261. }
  262. //2018-01-18 增加SIM7000C NB模式网络注册状态获取支持
  263. if((ModeType == SIMCOM_SIM7000C) && (pHandle->NetworkConfig.NB_EnableMode==1)) //如果是SIM7000C,并且开启了NB模式
  264. {
  265. NetStatus = SIMCOM_GetDataNetworkStatus(pHandle); //获取数据网络网络注册状态
  266. }
  267. else
  268. {
  269. NetStatus = SIM900_GetGSMNetworkStatus(pHandle); //获取GSM网络注册状态
  270. }
  271. SIMCOM_USER_debug("[DTU]网络注册状态%d!\r\n",NetStatus);
  272. //一直出现网络未注册以及注册拒绝,重启,有些卡会先出现拒绝,然后出现注册成功
  273. switch(NetStatus)
  274. {
  275. case SIMCOM_NET_NOT :
  276. {
  277. NotCnt++;
  278. //2017-09-09 增加如果连续15次未检测到卡,并且未注册,则直接退出,返回未插卡
  279. if(SIMCOM_GetCPIN(pHandle)==SIM_NOT_READY)
  280. {
  281. Error = SIMCOM_SIM_NOT_REALYE; //卡未就绪
  282. SIM_NotReadyCnt ++; //SIM卡未准备就绪计数器增加
  283. }
  284. else
  285. {
  286. SIM_NotReadyCnt = 0; //SIM卡未就绪计数器复位
  287. }
  288. }break; //未注册
  289. case SIMCOM_NET_ROA : //已经注册,但是漫游
  290. case SIMCOM_NET_YES : //已经注册
  291. {
  292. SIM_NotReadyCnt = 0; //SIM卡未就绪计数器复位
  293. if(pHandle->s_isInitStatus == FALSE)//模块没有初始化
  294. {
  295. if(SIMCOM_ModuleInit(pHandle) == FALSE) //上电后初始化模块基本配置
  296. {
  297. SIMCOM_USER_debug("[DTU]初始化失败!\r\n");
  298. if(isCart==TRUE) Error = SIMCOM_INIT_ERROR; //卡初始化成功了,才返回初始化错误
  299. goto reset;
  300. }
  301. }
  302. //获取模块信息
  303. if( SIMCOM_GetModuleInfo(pHandle, &pHandle->SIMCOM_Info) == TRUE) //获取模块的相关信息
  304. {
  305. SIMCOM_USER_debug("\r\n制造商:%s\r\n",pHandle->SIMCOM_Info.Manu);
  306. SIMCOM_USER_debug("模块型号:%s\r\n",pHandle->SIMCOM_Info.Model);
  307. SIMCOM_USER_debug("软件版本:%s\r\n",pHandle->SIMCOM_Info.Ver);
  308. SIMCOM_USER_debug("模块序列号:%s\r\n",pHandle->SIMCOM_Info.IMEI);
  309. }
  310. else
  311. {
  312. SIMCOM_USER_debug("\r\n获取模块信息失败!\r\n");
  313. }
  314. //获取运营商信息
  315. if(SIMCOM_COPS(pHandle, pHandle->TelecomCarr) == TRUE) //获取运营商名称
  316. {
  317. SIMCOM_USER_debug("运营商信息:%s\r\n", pHandle->TelecomCarr);
  318. }
  319. else
  320. {
  321. SIMCOM_USER_debug("获取运营商信息失败!\r\n");
  322. }
  323. //如果是SIM7600 SIM7000C模块,则需要获取网络制式
  324. switch(ModeType)
  325. {
  326. case SIMCOM_SIM7600:
  327. case SIMCOM_SIM7000C:
  328. {
  329. NetworkMode = SIM7XXX_GetNetworkMode(pHandle); //获取SIM7XXX系列模块网络制式
  330. pHandle->NetworkMode = NetworkMode; //记录全局网络制式,必须在获取短信中心号码之前进行获取,因为电信卡无短信中心号码用于初始化
  331. if(NetworkMode > 16)
  332. {
  333. SIMCOM_USER_debug("网络制式:获取失败\r\n");
  334. }
  335. else
  336. {
  337. SIMCOM_USER_debug("网络制式:%s\r\n",SIMCOM_NETWORK_NAME[NetworkMode]);
  338. }
  339. }break;
  340. default: //2G
  341. {
  342. pHandle->NetworkMode = SIMCOM_NETMODE_GSM; //其它2G模块默认GSM网络
  343. }break;
  344. }
  345. Error = SIMCOM_INIT_OK; //初始化成功
  346. return Error; //已经注册并初始化了
  347. }
  348. case SIMCOM_NET_SEA : SeaCnt++;break; //未注册,正在搜索
  349. case SIMCOM_NET_TUR : TurCnt++;break; //注册被拒绝
  350. case SIMCOM_NET_UNK : UnkCnt++;break; //未知
  351. default : ErrCnt++;break; //错误
  352. }
  353. if((TurCnt > 60) || (UnkCnt > 20) || (ErrCnt > 20)) //注册被拒绝,或者错误
  354. {
  355. if(isCart==TRUE) Error = SIMCOM_REG_ERROR; //卡初始化成功了,才返回初注册失败
  356. SIMCOM_USER_debug("[DTU]模块重启!\r\n");
  357. if(SIMCOM_HardwarePowerDOWN(pHandle, TRUE) == FALSE)
  358. {
  359. SIMCOM_USER_debug("[DTU]:关机失败!\r\n");
  360. }
  361. break;
  362. }
  363. //SIM卡未就绪次数过多
  364. if(SIM_NotReadyCnt > 16)
  365. {
  366. uart_printf("[DTU]:多次检测到卡未就绪!模块重启!\r\n");
  367. if(SIMCOM_HardwarePowerDOWN(pHandle, TRUE) == FALSE)
  368. {
  369. SIMCOM_USER_debug("[DTU]:关机失败!\r\n");
  370. }
  371. break;
  372. }
  373. //延时
  374. pHandle->pDelayMS(800);
  375. if(pHandle->pIWDG_Feed!=NULL) pHandle->pIWDG_Feed(); //喂狗
  376. }
  377. //网络注册失败或模块初始化失败
  378. reset:
  379. if(SIMCOM_HardwarePowerDOWN(pHandle, TRUE) == TRUE) //关闭电源
  380. {
  381. uart_printf("[DTU]:网络初始化失败,模块关机成功!\r\n");
  382. }
  383. else
  384. {
  385. uart_printf("[DTU]:网络初始化失败,模块关机失败!\r\n");
  386. }
  387. }
  388. else
  389. {
  390. Error = SIMCOM_POWER_UP_ERROR; //开机失败
  391. }
  392. }
  393. //显示错误信息
  394. switch(Error)
  395. {
  396. case SIMCOM_INIT_OK : //初始化成功
  397. {
  398. uart_printf("[DTU]:模块上电或初始成功!\r\n");
  399. }break;
  400. case SIMCOM_POWER_UP_ERROR : //上电错误
  401. {
  402. uart_printf("[DTU]:模块上电错误!\r\n");
  403. }break;
  404. case SIMCOM_REG_ERROR : //注册出错(超时)
  405. {
  406. uart_printf("[DTU]:模块注册网络出错(超时)!\r\n");
  407. }break;
  408. case SIMCOM_INIT_ERROR : //初始化配置错误
  409. {
  410. uart_printf("[DTU]:模块初始化配置出错!\r\n");
  411. }break;
  412. case SIMCOM_SIM_NOT_REALYE : //SIM卡未就绪导致上电失败
  413. {
  414. uart_printf("[DTU]:模块SIM卡未就绪!\r\n");
  415. }break;
  416. default:
  417. {
  418. uart_printf("[DTU]:未知的错误!\r\n");
  419. }break;
  420. }
  421. return Error;
  422. }
  423. /*************************************************************************************************************************
  424. * 函数 : bool SIMCOM_PhoneMessageNumberInitialize(SIMCOM_HANDLE *pHandle, u8 retry)
  425. * 功能 : SIMCOM 初始化获取短信中心号码以及本机号码,信号强度,CIMI(结果存放在句柄pHandle中)
  426. * 参数 : pHandle:句柄;Retry:初始化重试次数>0
  427. * 返回 : TRUE成功,FALSE:失败
  428. * 依赖 : 底层
  429. * 作者 : cp1300@139.com
  430. * 时间 : 2014-08-18
  431. * 最后修改时间 : 2018-03-24
  432. * 说明 : 用于网络初始化之后进行初始化获取相关信息,需要提前初始化网络模块型号以及网络制式
  433. 短信中心号码存放在:pHandle->ServiceCenterPhoneNumber;
  434. 电话号码存放在:pHandle->LocalPhoneNumber;
  435. 信号强度存放在:pHandle->Singal;
  436. SIM卡CIMI号码存放在pHandle->SIM_CIMI;
  437. 2016-06-15:SIM2000C使用电信SIM卡时,过快读取本机号码会失败,增加延时,确保读取成功
  438. 2016-11-16:增加获取短信中心号码延时
  439. 2017-12-05:NBIO 模块不读取电话号码
  440. *************************************************************************************************************************/
  441. bool SIMCOM_PhoneMessageNumberInitialize(SIMCOM_HANDLE *pHandle, u8 retry)
  442. {
  443. u8 i; //重试计数器
  444. int Singal;
  445. bool status;
  446. bool isReadServerNumber = TRUE; //是否需要获取短信中心号码,电信卡无需获取
  447. //测试AT指令
  448. SIMCOM_Ready(pHandle);
  449. if(SIMCOM_TestAT(pHandle, 20) != TRUE)
  450. {
  451. return FALSE;
  452. }
  453. retry += 1;
  454. //获取短信中心号码
  455. if(pHandle->SimcomModeType == SIMCOM_SIM2000) //电信模块无需获取短信中心号码
  456. {
  457. isReadServerNumber = FALSE;
  458. }
  459. else if(pHandle->SimcomModeType == LYNQ_L700) //L700 NBIOT 无需获取短信中心号码
  460. {
  461. isReadServerNumber = FALSE;
  462. }
  463. else if(pHandle->SimcomModeType==SIMCOM_SIM7000C) //SIM7000C
  464. {
  465. isReadServerNumber = FALSE; //sim7000不支持
  466. }
  467. else if(pHandle->SimcomModeType==SIMCOM_SIM7600) //SIM7600
  468. {
  469. switch(pHandle->NetworkMode) //查看网络制式,如果是CDMA(电信卡)则不需要获取短信中心号码
  470. {
  471. case SIMCOM_NETMODE_CDMA ://CDMA
  472. case SIMCOM_NETMODE_EVDO ://EVDO
  473. case SIMCOM_NETMODE_HYBRID ://HYBRID (CDMA and EVDO)
  474. case SIMCOM_NETMODE_1XLTE ://1XLTE(CDMA and LTE)
  475. {
  476. isReadServerNumber = FALSE;
  477. }break;
  478. }
  479. }
  480. if(isReadServerNumber) //需要获取短信中心号码
  481. {
  482. for(i = 0;i < retry;i ++)
  483. {
  484. if(SIMCOM_GetServeNumber(pHandle, pHandle->ServiceCenterPhoneNumber) == TRUE) //获取短信服务中心号码成功
  485. {
  486. if(pHandle->ServiceCenterPhoneNumber[0] == 0)
  487. {
  488. SIMCOM_USER_debug("短信中心号码为空\r\n");
  489. }
  490. else
  491. {
  492. SIMCOM_USER_debug("短信中心号码:%s\r\n",pHandle->ServiceCenterPhoneNumber);
  493. }
  494. break;
  495. }
  496. else
  497. {
  498. SIMCOM_WaitSleep(pHandle, 100);
  499. SIMCOM_Ready(pHandle);
  500. pHandle->pDelayMS(1000);
  501. }
  502. }
  503. if(i==retry) return FALSE;
  504. }
  505. else
  506. {
  507. pHandle->pDelayMS(2000); //等待2s钟
  508. strcpy(pHandle->ServiceCenterPhoneNumber, "13800818500"); //短信中心号码-固定值,防止为空
  509. SIMCOM_USER_debug("[缺省]短信中心号码:%s\r\n",pHandle->ServiceCenterPhoneNumber);
  510. }
  511. //获取信号强度
  512. for(i = 0;i < retry;i ++)
  513. {
  514. Singal = SIMCOM_GetSignal(pHandle); //获取信号强度
  515. if((Singal > 0) && (Singal!=99))
  516. {
  517. pHandle->Singal = (u8)Singal;
  518. SIMCOM_USER_debug("信号强度 <%02d>!\r\n" ,Singal);
  519. break;
  520. }
  521. else
  522. {
  523. pHandle->Singal = 0; //没有读取到,延时2秒
  524. pHandle->pDelayMS(2000); //等待2s钟
  525. }
  526. SIMCOM_WaitSleep(pHandle, 100);
  527. SIMCOM_Ready(pHandle);
  528. pHandle->pDelayMS(1000); //等待1s钟
  529. }
  530. //获取本机号码
  531. for(i = 0;i < retry;i ++)
  532. {
  533. if(pHandle->NetworkMode == LYNQ_L700) //L700 NBIOT 无法获取
  534. {
  535. pHandle->pDelayMS(1000); //等待1s钟
  536. pHandle->LocalPhoneNumber[0] = 0;
  537. return TRUE;
  538. }
  539. else if(pHandle->NetworkMode == SIMCOM_SIM7000C) //SIM7000C 无法获取
  540. {
  541. pHandle->pDelayMS(1000); //等待1s钟
  542. pHandle->LocalPhoneNumber[0] = 0;
  543. return TRUE;
  544. }
  545. else if(pHandle->SimcomModeType==SIMCOM_SIM7600) //SIM7600,SIM7000C
  546. {
  547. switch(pHandle->NetworkMode) //查看网络制式,如果是CDMA(电信卡)则不需要获取短信中心号码
  548. {
  549. case SIMCOM_NETMODE_CDMA ://CDMA
  550. case SIMCOM_NETMODE_EVDO ://EVDO
  551. case SIMCOM_NETMODE_HYBRID ://HYBRID (CDMA and EVDO)
  552. case SIMCOM_NETMODE_1XLTE ://1XLTE(CDMA and LTE)
  553. {
  554. status = SIMCOM_GetBookNumber(pHandle, 1, pHandle->LocalPhoneNumber); //从电话簿中读取一个电话号码
  555. }break;
  556. default: //其他制式可以读取
  557. {
  558. status = SIMCOM_GetPhoneNumber(pHandle, pHandle->LocalPhoneNumber); //读取本机号码
  559. }break;
  560. }
  561. }
  562. else if(pHandle->SimcomModeType == SIMCOM_SIM2000) //SIM2000
  563. {
  564. status = SIMCOM_GetBookNumber(pHandle, 1, pHandle->LocalPhoneNumber); //从电话簿中读取一个电话号码
  565. }
  566. else //其它模块
  567. {
  568. status = SIMCOM_GetPhoneNumber(pHandle, pHandle->LocalPhoneNumber); //读取本机号码
  569. }
  570. if(status== TRUE) //获取本机号码成功
  571. {
  572. pHandle->LocalPhoneNumber[15] = 0;
  573. if(pHandle->LocalPhoneNumber[0] == 0)
  574. {
  575. SIMCOM_USER_debug("本机号码为空\r\n");
  576. }
  577. else
  578. {
  579. SIMCOM_USER_debug("本机号码:%s\r\n",pHandle->LocalPhoneNumber);
  580. }
  581. break;
  582. }
  583. else
  584. {
  585. SIMCOM_WaitSleep(pHandle, 100);
  586. SIMCOM_Ready(pHandle);
  587. pHandle->pDelayMS(2000); //等待2s钟
  588. }
  589. }
  590. if(i==retry) return FALSE;
  591. //获取SIM卡CIMI号码
  592. for(i = 0;i < retry;i ++)
  593. {
  594. //获取SIM卡CIMI号码(SIM卡唯一id,必须存在)
  595. if(SIMCOM_GetCIMI(pHandle, pHandle->SIM_CIMI) == TRUE) break;
  596. SIMCOM_WaitSleep(pHandle, 100);
  597. SIMCOM_Ready(pHandle);
  598. pHandle->pDelayMS(1000); //等待1s钟
  599. }
  600. if(i==retry) return FALSE;
  601. return TRUE;
  602. }

//SIMCOM_USER.h

  1. /*************************************************************************************************************
  2. * 文件名: SIMCOM_USER.h
  3. * 功能: SIMCOM用户层函数
  4. * 作者: cp1300@139.com
  5. * 创建时间: 2015-02-15
  6. * 最后修改时间: 2018-03-23
  7. * 详细:
  8. *************************************************************************************************************/
  9. #ifndef _SIMCOM_SUER_H_
  10. #define _SIMCOM_SUER_H_
  11. #include "system.h"
  12. #include "simcom.h"
  13. //SIMCOM 初始化错误
  14. typedef enum
  15. {
  16. SIMCOM_INIT_OK = 0, //初始化成功
  17. SIMCOM_POWER_UP_ERROR = 1, //上电错误
  18. SIMCOM_REG_ERROR = 2, //注册出错(超时)
  19. SIMCOM_INIT_ERROR = 3, //初始化配置错误
  20. SIMCOM_SIM_NOT_REALYE = 4, //SIM卡未就绪导致上电失败
  21. SIMCOM_NULL_ERROR = 255 //状态无效
  22. }SIMCOM_USER_ERROR;
  23. //API
  24. //初始化SIMCOM句柄接口
  25. bool SIMCOM_Init(SIMCOM_HANDLE *pHandle,
  26. bool (* pSendData)(u8 *pDataBuff, u16 DataLen), //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
  27. int (* pReadData)(u8 **pDataBuff, u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelay), //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
  28. void (*pClearRxData)(void), //清除接收缓冲区函数,用于清除接收数据缓冲区数据
  29. void (*pSetDTR_Pin)(u8 Level), //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
  30. void (*pSetPWRKEY_Pin)(u8 Level), //PWRKEY开机引脚电平控制-用于开机
  31. u8 (*pGetSTATUS_Pin)(void), //获取STATUS引脚电平-用于指示模块上电状态
  32. u8 (*pGetDCD_Pin)(void), //获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
  33. void (*pDelayMS)(u32 ms), //系统延时函数
  34. void (*pIWDG_Feed)(void) //清除系统看门狗(可以为空)
  35. );
  36. SIMCOM_USER_ERROR SIMCOM_RegisNetwork(SIMCOM_HANDLE *pHandle, u16 Retry, u16 NetworkDelay,const char **pModeInof);//SIMCOM模块上电初始化并注册网络
  37. bool SIMCOM_PhoneMessageNumberInitialize(SIMCOM_HANDLE *pHandle, u8 retry); //SIMCOM 初始化获取短信中心号码以及本机号码,信号强度,CIMI(结果存放在句柄pHandle中)
  38. #endif /*_SIMCOM_SUER_H_*/

//底层相关接口,自己根据自己的平台进行开发的接口

  1. //发送数据接口
  2. static bool GPRS_UART_SendData(u8 DataBuff[], u16 DataLen)
  3. {
  4. UARTx_SendData(SIMCOM_UART_CH, DataBuff, DataLen);
  5. return TRUE;
  6. }
  7. //接收数据接口
  8. static int GPRS_UART_ReadData(u8 **pDataBuff,u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelayMs)
  9. {
  10. u32 cnt = 0;
  11. u16 TempTime;
  12. if(ByteTimeOutMs < 1) ByteTimeOutMs = 1; //字节超时时间,2个帧之间的间隔最小时间
  13. TimeOutMs /= ByteTimeOutMs;
  14. TimeOutMs += 1;
  15. TempTime = TimeOutMs;
  16. while(TimeOutMs --)
  17. {
  18. cnt = UARTx_GetRxCnt(SIMCOM_UART_CH);
  19. OSTimeDlyHMSM(0,0,0,ByteTimeOutMs);;
  20. if((cnt > 0) && (cnt == UARTx_GetRxCnt(SIMCOM_UART_CH)))
  21. {
  22. if(pReceiveDelayMs!=NULL) //需要返回延时
  23. {
  24. *pReceiveDelayMs = (TempTime-TimeOutMs)*ByteTimeOutMs;
  25. }
  26. *pDataBuff = g_SIMCOM_Buff; //接收缓冲区
  27. return cnt;
  28. }
  29. #if SYS_WDG_EN_
  30. IWDG_Feed(); //喂狗
  31. #endif
  32. }
  33. return 0;
  34. }
  35. //清除接收缓冲区
  36. static void GPRS_UART_ClearData(void)
  37. {
  38. UARTx_ClearRxCnt(SIMCOM_UART_CH); //清除串口缓冲区
  39. }
  1. /
  2. //SIM900/SIM800通信支持
  3. //GSM模块相关定义
  4. #define SIMCOM_UART_CH UART_CH3 //串口3
  5. #define SIMCOM_UART_BAUD 115200 //波特率
  6. #define SIMCOM_UART_BUFF_SIZE (1024*4) //接收缓冲区大小
  7. //相关控制引脚
  8. __inline void SIMCOM_SetDTR(u8 Level) {(PGout(4)=Level);} //DTR
  9. __inline void SIMCOM_SetPWRKEY(u8 Level) {(PGout(3)=Level);} //PWRKEY
  10. __inline u8 SIMCOM_GetSTATUS(void) {return PGin(5)?1:0;} //STATUS
  11. __inline u8 SIMCOM_GetDCD(void) {return PDin(11)?1:0;} //DCD-上拉输入,高电平AT指令模式,低电平为透传模式
  12. //引脚初始化
  13. __inline void SIMCOM_IO_Init(void)
  14. {
  15. SYS_DeviceClockEnable(DEV_GPIOD, TRUE); //使能GPIOD时钟
  16. SYS_DeviceClockEnable(DEV_GPIOG, TRUE); //使能GPIOG时钟
  17. SYS_GPIOx_Init(GPIOG, BIT3|BIT4, OUT_PP, SPEED_2M); //推挽输出
  18. SYS_GPIOx_OneInit(GPIOD, 11, IN_IPU, IN_NONE); //DCD 上拉输入
  19. SYS_GPIOx_OneInit(GPIOG, 5, IN_IPD, IN_NONE); //STATUS 下拉输入
  20. }

另外还有一个看门狗清除的回调函数

  1. //喂独立看门狗
  2. __inline void IWDG_Feed(void) {IWDG->KR=0XAAAA;}

//实现了以上的接口就可以调用了

//下面是应用层调用,使用了ucos的一个任务

  1. SIMCOM_HANDLE g_SIMCOM_Handle; //SIMCOM通信模块句柄
  2. u8 g_SIMCOM_Buff[SIMCOM_UART_BUFF_SIZE+1]; //串口接收缓冲区
  3. static bool GPRS_UART_SendData(u8 DataBuff[], u16 DataLen); //发送数据接口
  4. static int GPRS_UART_ReadData(u8 **pDataBuff,u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelayMs); //接收数据接口
  5. static void GPRS_UART_ClearData(void); //清除接收缓冲区
  6. //GPRS通信任务
  7. void GPRS_Task(void *pdata)
  8. {
  9. const char *pModeInof;
  10. UARTx_Init(SIMCOM_UART_CH, SIMCOM_UART_BAUD, ENABLE); //初始化串口
  11. UARTx_SetRxBuff(SIMCOM_UART_CH, g_SIMCOM_Buff, SIMCOM_UART_BUFF_SIZE); //设置串口接收缓冲区
  12. SIMCOM_IO_Init(); //SIMCOM相关IO初始化
  13. OSTimeDlyHMSM(0,0,0,20);
  14. //初始化SIMCOM句柄接口
  15. SIMCOM_Init(&g_SIMCOM_Handle,
  16. GPRS_UART_SendData, //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
  17. GPRS_UART_ReadData, //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
  18. GPRS_UART_ClearData, //清除接收缓冲区函数,用于清除接收数据缓冲区数据
  19. SIMCOM_SetDTR, //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
  20. SIMCOM_SetPWRKEY, //PWRKEY开机引脚电平控制-用于开机
  21. SIMCOM_GetSTATUS, //获取STATUS引脚电平-用于指示模块上电状态
  22. SIMCOM_GetDCD, //DCD-上拉输入,高电平AT指令模式,低电平为透传模式
  23. SYS_DelayMS, //系统延时函数
  24. IWDG_Feed //清除系统看门狗(可以为空)
  25. );
  26. while(1)
  27. {
  28. SIMCOM_RegisNetwork(&g_SIMCOM_Handle, 6, 60, &pModeInof);//SIMCOM模块上电初始化并注册网络
  29. //SIMCOM 初始化获取短信中心号码以及本机号码,信号强度,CIMI(结果存放在句柄pHandle中)
  30. if(SIMCOM_PhoneMessageNumberInitialize(&g_SIMCOM_Handle, 3) == FALSE)
  31. {
  32. uart_printf("\r\n警告:初始化获取相关信息失败!\r\n");
  33. }
  34. OSTimeDlyHMSM(0,5,0,20);
  35. }
  36. }

//以上代码实现了通信模块的初始化,开机,联网,读取本机号码,中心站号码,SIMI码,信号等操作,感兴趣的朋友可以依照此模板进行后续的开发,使用底层分离的方式可以让代码解耦便于在各个平台上面移植,同时增加了稳定性。

//下面是串口打印的信息,命令执行的很快,我使用的是SIM7600CE模块,全网通4G,初始化非常快,每个文件都有定义调试开关,可以动态使用一个变量控制开关,也可以使用宏定义控制调试信息开关。

SIMCOM(26B)->
SIMCOM_SIM7600CE

OK

OK 返回成功!
[DTU]通信模块为SIM7600

SIMCOM(22B)->
+CPIN: READY

OK

OK 返回成功!

SIM卡准备就绪!

SIMCOM(20B)->
+CREG: 0,1

OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!
[DTU]网络注册状态1!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(22B)->
+CPIN: READY

OK

OK 返回成功!

SIM卡准备就绪!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(35B)->
OK

SIMCOM INCORPORATED

OK

OK 返回成功!

SIMCOM(26B)->
SIMCOM_SIM7600CE

OK

OK 返回成功!

SIMCOM(34B)->
+GMR: LE11B02SIM7600CE-A

OK

OK 返回成功!

SIMCOM(25B)->
861477030032237

OK

OK 返回成功!

制造商:OK
模块型号:SIMCOM_SIM7600CE
软件版本:LE11B02SIM7600CE-A
模块序列号:861477030032237

SIMCOM(42B)->
+COPS: 0,0,"CHINA MOBILE CMCC",7

OK

OK 返回成功!
运营商信息:CHINA MOBILE CMCC

SIMCOM(22B)->
+CNSMOD: 0,8

OK

OK 返回成功!
网络制式:LTE

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(6B)->
OK

OK 返回成功!

SIMCOM(37B)->
+CSCA: "+8613800100569",145

OK

OK 返回成功!
短信中心号码:13800100569
短信中心号码:13800100569

SIMCOM(21B)->
+CSQ: 20,99

OK

OK 返回成功!
信号强度 <20>!

SIMCOM(41B)->
+CNUM: "","1064838905852",129


OK

OK 返回成功!
本机号码:1064838905852
本机号码:1064838905852

SIMCOM(25B)->
460040389005852

OK

OK 返回成功!
获取CIMI成功:460040389005852


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/361129
推荐阅读
相关标签
  

闽ICP备14008679号