赞
踩
使用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
- /*************************************************************************************************************
- * 文件名: SIMCOM.h
- * 功能: SIMCOM 底层定义
- * 作者: cp1300@139.com
- * 创建时间: 2015-02-15
- * 最后修改时间: 2018-03-23
- * 详细: 注意:底层通信接口使用的是回调函数,但是必须提供系统延时函数 void SYS_DelayMS(u32 ms);
- *************************************************************************************************************/
- #ifndef _SIMCOM_H_
- #define _SIMCOM_H_
- #include "system.h"
-
-
- //SIMCOM通信模块定义
- typedef enum
- {
- SIMCOM_SIM900 = 0 , //默认为SIM900
- SIMCOM_SIM800 = 1 , //SIM800
- SIMCOM_SIM2000 = 2 , //SIM2000
- SIMCOM_SIM7600 = 3 , //SIM7600
- SIMCOM_SIM868 = 4 , //SIM868
- SIMCOM_SIM7000C = 5 , //SIM7000C
- LYNQ_L700 = 10 , //LYNQ_L700
- SIMCOM_INVALID = 0XFF , //无效则默认
- }SIMCOM_MODE_TYPE;
-
- //网络注册状态
- typedef enum
- {
- SIMCOM_NET_NOT = 0, //未注册
- SIMCOM_NET_YES = 1, //已经注册
- SIMCOM_NET_SEA = 2, //未注册,正在搜索
- SIMCOM_NET_TUR = 3, //注册被拒绝
- SIMCOM_NET_UNK = 4, //未知
- SIMCOM_NET_ROA = 5, //已经注册,但是漫游
- SIMCOM_NET_ERROR=0XFF //错误
- }SIMCOM_NETSTATUS;
-
-
-
- //SIMCOM网络制式
- typedef enum
- {
- SIMCOM_NETMODE_NOT = 0, //未注册
- SIMCOM_NETMODE_GSM = 1, //GSM
- SIMCOM_NETMODE_GPRS = 2, //GPRS
- SIMCOM_NETMODE_EGPRS = 3, //EGPRS (EDGE)
- SIMCOM_NETMODE_WCDMA = 4, //WCDMA
- SIMCOM_NETMODE_HSDPA = 5, //HSDPA only(WCDMA)
- SIMCOM_NETMODE_HSUPA = 6, //HSUPA only(WCDMA)
- SIMCOM_NETMODE_HSPA = 7, //HSPA (HSDPA and HSUPA, WCDMA)
- SIMCOM_NETMODE_LTE = 8, //LTE
- SIMCOM_NETMODE_TDS_CDMA = 9, //TDS-CDMA
- SIMCOM_NETMODE_TDS_HSDPA = 10, //TDS-HSDPA only(SIM7000C 电信NB也是这个)
- SIMCOM_NETMODE_TDS_HSUPA = 11, //TDS-HSUPA only
- SIMCOM_NETMODE_TDS_HSPA = 12, //TDS- HSPA (HSDPA and HSUPA)
- SIMCOM_NETMODE_CDMA = 13, //CDMA
- SIMCOM_NETMODE_EVDO = 14, //EVDO
- SIMCOM_NETMODE_HYBRID = 15, //HYBRID (CDMA and EVDO)
- SIMCOM_NETMODE_1XLTE = 16, //1XLTE(CDMA and LTE)
- SIMCOM_NETMODE_NULL = 0xff, //未知
- }SIMCOM_NETMODE_TYPE;
-
-
- //SIM卡就绪状态
- typedef enum
- {
- SIM_READY = 0, //SIM卡就绪
- SIM_NOT_READY = 1, //SIM卡未就绪
- SIM_UNKNOWN = 2 //SIM卡状态未知
- }SIM_CARD_STATUS;
-
- //控制IO电平定义
- #define SIMCOM_H_LEVEL 1 //高电平
- #define SIMCOM_L_LEVEL 0 //低电平
-
- //DCD状态定义
- #define DCD_DATA_MODE 0 //数据透传模式
- #define DCD_AT_MODE 1 //AT指令模式
-
- //相关信息长度限制
- #define SIMCOM_INFO_SIZE 24 //信息长度
- #define SIMCOM_VER_SIZE 24 //软件版本长度定义
-
- //重试次数,防止AT指令操作失败
- #define SIMCOM_DEFAULT_RETRY 2
-
-
- //SIMCOM模块相关信息
- typedef struct
- {
- char Manu[SIMCOM_INFO_SIZE+1]; //制造商
- char Model[SIMCOM_INFO_SIZE+1]; //型号
- char Ver[SIMCOM_VER_SIZE+1]; //软件版本
- char IMEI[SIMCOM_INFO_SIZE+1]; //序列号
- }SIMCOM_INFO;
-
-
- //NBIOT模式定义
- typedef enum
- {
- NB_IOT_MODE = 0, //NBIOT模式
- CAT_M_MODE = 1, //CAT-M模式
- }NBIOT_MODE_TYPE;
-
- //网络模式设置
- typedef struct
- {
- SIMCOM_MODE_TYPE ModeType; //模块型号
- NBIOT_MODE_TYPE NB_Mode; //NB模式
- s8 NB_EnableMode; //NB模式使能模式,-1:无需设置;0:关闭NB,使能GSM模式;1:使能NB模式
- bool isNB_ScarEnable; //NB模式扰码使能
- }NETWORK_CONFIG_TYPE;
-
-
-
- //SIMCOM通信模块句柄
- typedef struct
- {
- //所需变量
- SIMCOM_MODE_TYPE SimcomModeType; //模块型号
- char TelecomCarr[SIMCOM_INFO_SIZE+1]; //运营商名称
- SIMCOM_INFO SIMCOM_Info; //SIMCOM通信模块相关信息结构体
- NETWORK_CONFIG_TYPE NetworkConfig; //网络模式设置
- SIMCOM_NETMODE_TYPE NetworkMode; //当前网络制式
- u8 Singal; //网络信号强度
- char LocalPhoneNumber[16]; //本机电话号码
- char ServiceCenterPhoneNumber[16]; //短信中心电话号码
- char SIM_CIMI[16]; //SIM卡唯一CIMI号码
-
- //底层通信接口
- bool (* pSendData)(u8 *pDataBuff, u16 DataLen); //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
- int (* pReadData)(u8 **pDataBuff, u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelay); //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
- void (*pClearRxData)(void); //清除接收缓冲区函数,用于清除接收数据缓冲区数据
- void (*pSetDTR_Pin)(u8 Level); //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
- void (*pSetPWRKEY_Pin)(u8 Level); //PWRKEY开机引脚电平控制-用于开机
- u8 (*pGetSTATUS_Pin)(void); //获取STATUS引脚电平-用于指示模块上电状态
- u8 (*pGetDCD_Pin)(void); //获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
- //系统接口
- void (*pDelayMS)(u32 ms); //系统延时函数
- void (*pIWDG_Feed)(void); //清除系统看门狗(可以为空)
- //内部状态定义
- bool s_isInitStatus; //用于记录模块初始化状态,复位或上电后变为无效
- }SIMCOM_HANDLE;
-
-
-
- #endif /*_SIMCOM_H_*/
//SIMCOM_AT.c
- /*************************************************************************************************************
- * 文件名: SIMCOM_AT.c
- * 功能: SIMCOM底层AT指令接口
- * 作者: cp1300@139.com
- * 创建时间: 2015-02-15
- * 最后修改时间: 2018-03-23
- * 详细:
- *************************************************************************************************************/
- #include "system.h"
- #include "usart.h"
- #include "SIMCOM_AT.h"
- #include "SIMCOM.h"
- #include "string.h"
- #include "ucos_ii.h"
-
- bool g_SIMC0M_AT_Debug = TRUE; //底层AT指令调试状态
-
- //调试开关
- #define SIMCOM_DBUG 1
- #if SIMCOM_DBUG
- #include "system.h"
- #define SIMCOM_debug(format,...) {if(g_SIMC0M_AT_Debug){uart_printf(format,##__VA_ARGS__);}}
- #else
- #define SIMCOM_debug(format,...) /\
- /
- #endif //SIMCOM_DBUG
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr)
- * 功能 : 发送一个AT指令(会添加结束符\r\n),不会等待响应
- * 参数 : pHandle:SIMCOM句柄;pStr:指令字符串
- * 返回 : 接口发送状态
- * 依赖 : 无
- * 作者 : cp1300@139.com
- * 时间 : 2018-03-23
- * 最后修改时间 : 2018-03-23
- * 说明 : 用于底层AT指令发送
- *************************************************************************************************************************/
- bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr)
- {
- pHandle->pSendData((u8 *)pStr, strlen(pStr)); //发送指令
- return pHandle->pSendData((u8 *)"\r\n", 2); //发送结束符
- }
-
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_TestAT(SIMCOM_HANDLE *pHandle, u32 retry)
- * 功能 : SIMCOM AT 命令通信测试
- * 参数 : pHandle:SIMCOM句柄;retry:重试次数
- * 返回 : FALSE:通信失败;TRUE:通信成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-20
- * 最后修改时间 : 2018-03-23
- * 说明 : 每隔100ms向SIMCOM通信模块发送一个"AT",等待响应返回
- *************************************************************************************************************************/
- bool SIMCOM_TestAT(SIMCOM_HANDLE *pHandle, u32 retry)
- {
- u32 cnt;
- u8 *pRxBuff;
-
- //检测模块存在
- do
- {
- SIMCOM_SendAT(pHandle, "AT"); //发送"AT",同步波特率,并且等待应答
- pHandle->pClearRxData(); //清除计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pRxBuff, &cnt, "OK", 10, 150)) //等待响应,超时150ms
- {
- pHandle->pDelayMS(100);
- return TRUE;
- }
- retry --;
- }while(retry);
-
- pHandle->pDelayMS(100);
- return FALSE;
- }
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_WaitSleep(SIMCOM_HANDLE *pHandle, u32 TimeOutMs)
- * 功能 : 等待模块空闲,并重新唤醒
- * 参数 : pHandle:句柄;TimeOut:等待超时,时间单位ms
- * 返回 : TRUE:成功;FALSE:超时
- * 依赖 : 无
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-25
- * 最后修改时间 : 2018-03-24
- * 说明 : 用于等待操作完成,防止快速操作造成模块不响应
- *************************************************************************************************************************/
- bool SIMCOM_WaitSleep(SIMCOM_HANDLE *pHandle, u32 TimeOutMs)
- {
- u32 i;
- u32 cnt;
- u8 *pData;
-
- if(TimeOutMs < 100) TimeOutMs = 100; //最少100ms
- pHandle->pSetDTR_Pin(SIMCOM_H_LEVEL); //等待模块空闲后进入SLEEP模式
-
- //循环发送命令,直到命令超时了则认为进入了sleep模式
- for(i = 0;i < (TimeOutMs/100);i ++)
- {
- pHandle->pDelayMS(100); //延时100ms
- SIMCOM_SendAT(pHandle, "AT"); //发送"AT",同步波特率,并且等待应答
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_TIME_OUT == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 100)) //等待响应,超时100ms
- {
- break;
- }
- }
- pHandle->pSetDTR_Pin(SIMCOM_L_LEVEL); //唤醒
-
- if(i == (TimeOutMs/100))
- {
- SIMCOM_debug("模块进入空闲模式失败!\r\n");
- pHandle->pClearRxData(); //清除接收计数器
-
- return FALSE;
- }
- pHandle->pDelayMS(100); //延时100ms
-
- SIMCOM_debug("模块进入空闲模式成功!\r\n");
- SIMCOM_TestAT(pHandle, 10);
- pHandle->pClearRxData(); //清除接收计数器
-
- return TRUE;
- }
-
-
-
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : SIMCOM_AT_ERROR SIMCOM_GetATResp(SIMCOM_HANDLE *pHandle, u8 **pRxBuff, u32 *pLen, const char *pKeyword, u8 ByteTimeOutMs, u16 TimeOutMs)
- * 功能 : 获取SIMCOM的AT指令响应
- * 参数 : pHandle:句柄
- pRxBuff:接收缓冲区指针(输出);pLen:接收到的数据大小(输出),
- pKeyword:关键字,为字符串,比如"OK",如果在接收到的字符串中有OK字符,就返回成功,否则失败(输入)
- ByteTimeOutMs:字节超时时间,单位ms最大255ms
- TimeOutMs:等待超时时间,单位毫秒
- * 返回 : SIM900_ERROR
- * 依赖 : 无
- * 作者 : cp1300@139.com
- * 时间 : 2018-03-24
- * 最后修改时间 : 2018-03-24
- * 说明 : 本函数会在接收缓冲区字符串结束添加'\0'
- 本函数不能清除缓冲区
- *************************************************************************************************************************/
- SIMCOM_AT_ERROR SIMCOM_GetATResp(SIMCOM_HANDLE *pHandle, u8 **pRxBuff, u32 *pLen, const char *pKeyword, u8 ByteTimeOutMs, u16 TimeOutMs)
- {
- int len;
- u16 ReceiveDelay;
-
- if(ByteTimeOutMs < 1) ByteTimeOutMs = 1;
- len = pHandle->pReadData(pRxBuff, ByteTimeOutMs, TimeOutMs, &ReceiveDelay); //调用回调接口,读取数据
- //等待超时
- if(len == 0)
- {
- return AT_RETURN_TIME_OUT; //返回超时错误
- }
- //数据接收完毕
- *pLen = len; //返回接收数据长度
- if((*pRxBuff)[len-1] != 0)
- {
- (*pRxBuff)[len] = '\0'; //将数据结尾添加结束字符串
- }
-
- SIMCOM_debug("\r\nSIMCOM(%dB)->%s\r\n",len, *pRxBuff); //打印返回信息
- if(strstr((const char*)(*pRxBuff), pKeyword) != NULL) //搜索关键字
- {
- SIMCOM_debug("%s 返回成功!\r\n",pKeyword);
- return AT_RETURN_OK;
- }
- else if(strstr((const char*)(*pRxBuff), "ERROR") != NULL)
- {
- SIMCOM_debug("%s 返回错误!\r\n",pKeyword);
- return AT_RETURN_ERROR;
- }
- else
- {
- SIMCOM_debug("%s 返回未知!\r\n",pKeyword);
- return AT_RETURN_UNKNOWN;
- }
- }
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIM900_SetParametersReturnBool(char *pATCom, u8 retry, u16 TimeOutx10MS, const char *pErrorDebug)
- * 功能 : 设置SIM900一个参数,返回一个bool状态
- * 参数 : pATCom:AT命令;retry:重试次数;TimeOut:命令超时时间,单位10ms;pErrorDebug:失败后提示的调试信息
- * 返回 : TRUE:执行成功了,返回了OK,FALSE:执行失败了,返回了ERROR或其它
- * 依赖 : SIM900
- * 作者 : cp1300@139.com
- * 时间 : 2014-12-19
- * 最后修改时间 : 2014-12-19
- * 说明 : 用于简化命名发送,防止代码重复
- *************************************************************************************************************************/
- bool SIMCOM_SetParametersReturnBool(SIMCOM_HANDLE *pHandle, char *pATCom, u8 retry, u16 TimeOutMs, const char *pErrorDebug)
- {
- u32 cnt;
- u8 *pData;
-
- retry += 1; //重试次数
- do
- {
- SIMCOM_SendAT(pHandle,pATCom); //发送AT命令
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, TimeOutMs)) //等待响应,超时10s
- {
- pHandle->pClearRxData(); //清除接收计数器
- return TRUE;
- }
-
- SIMCOM_Ready(pHandle); //等待就绪
- retry --;
- }while(retry);
-
- if(pErrorDebug!=NULL)
- {
- uart_printf("%s",pErrorDebug); //输出调试信息
- }
- pHandle->pClearRxData(); //清除接收计数器
-
- return FALSE;
- }
-
-
-
-
- /*************************************************************************************************************************
- *函数 : u32 GSM_StringToHex(char *pStr, u8 NumDigits)
- *功能 : 将16进制样式字符串转换为16进制整型数(必须保证字符串字母都是大写)
- *参数 : pStr:字符串起始指针
- * NumDigits:数字位数,16进制数字位数
- *返回 : 转换后的数字
- *依赖 : 无
- *作者 : cp1300@139.com
- *时间 : 2013-04-30
- *最后修改时间 : 2013-10-17
- *说明 : 比如字符串"A865"转换后为0xA865,位数为4位
- 必须保证字符串字母都是大写
- *************************************************************************************************************************/
- u32 GSM_StringToHex(char *pStr, u8 NumDigits)
- {
- u8 temp;
- u32 HEX = 0;
- u8 i;
-
- NumDigits = (NumDigits > 8) ? 8 : NumDigits; //最大支持8位16进制数
-
- for(i = 0;i < NumDigits;i ++)
- {
- HEX <<= 4;
- temp = pStr[i];
- temp = (temp > '9') ? temp - 'A' + 10 : temp - '0';
- HEX |= temp;
- }
- return HEX;
- }
-
-
- /*************************************************************************************************************************
- *函数 : void GSM_HexToString(u32 HexNum,c har *pStr, u8 NumDigits)
- *功能 : 将整型数字转换为16进制样式字符串(字母为大写,不带结束符)
- *参数 : HexNum:16进制数字
- pStr:字符缓冲区指针
- * NumDigits:数字位数,16进制数字位数
- *返回 : 无
- *依赖 : 无
- *作者 : cp1300@139.com
- *时间 : 2013-04-30
- *最后修改时间 : 2013-04-30
- *说明 : 比如字符串0xA865转换后为"A865",位数为4位
- *************************************************************************************************************************/
- void GSM_HexToString(u32 HexNum,char *pStr, u8 NumDigits)
- {
- u8 temp;
- u8 i;
-
- NumDigits = (NumDigits > 8) ? 8 : NumDigits; //最大支持8位16进制数
-
- for(i = 0;i < NumDigits;i ++)
- {
- temp = 0x0f & (HexNum >> (4 * (NumDigits - 1 - i)));
- temp = (temp > 0x09) ? (temp - 0x0A + 'A') : (temp + '0');
- pStr[i] = temp;
- }
- }
-
-
-
-
- /*************************************************************************************************************************
- *函数 : u32 GSM_StringToDec(char *pStr, u8 NumDigits)
- *功能 : 将10进制样式字符串转换为整型数(必须保证完全为数字字符)
- *参数 : pStr:字符串起始指针
- * NumDigits:数字位数,10进制数字位数
- *返回 : 转换后的数字
- *依赖 : 无
- *作者 : cp1300@139.com
- *时间 : 2013-04-30
- *最后修改时间 : 2013-04-30
- *说明 : 比如字符串"1865"转换后为1865,位数为4位
- 必须保证完全为数字字符
- *************************************************************************************************************************/
- u32 GSM_StringToDec(char *pStr, u8 NumDigits)
- {
- u32 temp;
- u32 DEC = 0;
- u8 i;
- u8 j;
-
- NumDigits = (NumDigits > 10) ? 10 : NumDigits; //最大支持10位10进制数
-
- for(i = 0;i < NumDigits;i ++)
- {
- temp = pStr[i] - '0';
- if(temp > 9) //只能是数字范围
- return 0;
- for(j = 1;j < (NumDigits - i);j ++)
- {
- temp *= 10;
- }
- DEC += temp;
- }
- return DEC;
- }
//SIMCOM_AT.h
- /*************************************************************************************************************
- * 文件名: SIMCOM_AT.h
- * 功能: SIMCOM底层AT指令接口
- * 作者: cp1300@139.com
- * 创建时间: 2015-02-15
- * 最后修改时间: 2018-03-23
- * 详细:
- *************************************************************************************************************/
- #ifndef _SIMCOM_AT_H_
- #define _SIMCOM_AT_H_
- #include "system.h"
- #include "SIMCOM.h"
-
- extern bool g_SIMC0M_AT_Debug; //底层AT指令调试状态
-
-
-
- //SIM900返回错误
- typedef enum
- {
- AT_RETURN_OK = 0, //返回成功
- AT_RETURN_ERROR = 1, //返回错误
- AT_RETURN_UNKNOWN = 2, //返回结果未知
- AT_RETURN_TIME_OUT = 0xf, //等待返回超时
- }SIMCOM_AT_ERROR;
-
-
-
-
- //相关接口
- bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr); //发送一个AT指令(会添加结束符\r\n),不会等待响应
- SIMCOM_AT_ERROR SIMCOM_GetATResp(SIMCOM_HANDLE *pHandle, u8 **pRxBuff, u32 *pLen, const char *pKeyword, u8 ByteTimeOutMs, u16 TimeOutMs); //获取SIMCOM的AT指令响应
- bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr); //发送一个AT指令(会添加结束符\r\n),不会等待响应
- bool SIMCOM_WaitSleep(SIMCOM_HANDLE *pHandle, u32 TimeOutMs); //等待模块空闲,并重新唤醒
- bool SIMCOM_TestAT(SIMCOM_HANDLE *pHandle, u32 retry); //SIMCOM AT 命令通信测试
- #define SIMCOM_Ready(pHandle) if(SIMCOM_TestAT(pHandle, 5) == FALSE){SIMCOM_WaitSleep(pHandle, 1000);} //让SIMCOM就绪,防止卡住//串口同步失败,等待上一个操作完成
- bool SIMCOM_SetParametersReturnBool(SIMCOM_HANDLE *pHandle, char *pATCom, u8 retry, u16 TimeOutMs, const char *pErrorDebug); //设置SIM900一个参数,返回一个bool状态
-
-
-
- //通用工具
- u32 GSM_StringToHex(char *pStr, u8 NumDigits); //将16进制样式字符串转换为16进制整型数(必须保证字符串字母都是大写)
- u32 GSM_StringToDec(char *pStr, u8 NumDigits); //将10进制样式字符串转换为整型数(必须保证完全为数字字符)
- void GSM_HexToString(u32 HexNum,char *pStr, u8 NumDigits); //将整型数字转换为16进制样式字符串(字母为大写,不带结束符)
-
- #endif /*SIMCOM_AT*/
//SIMCOM_GSM.c //通用的底层操作
- /*************************************************************************************************************
- * 文件名: SIMCOM_GSM.c
- * 功能: SIMCOM GSM相关接口
- * 作者: cp1300@139.com
- * 创建时间: 2015-02-15
- * 最后修改时间: 2018-03-23
- * 详细:
- *************************************************************************************************************/
- #include "system.h"
- #include "usart.h"
- #include "SIMCOM_GSM.h"
- #include "SIMCOM_AT.h"
- #include "string.h"
- #include "SIMCOM.h"
- #include <stdlib.h>
-
- bool g_SIMC0M_GSM_Debug = TRUE; //底层AT指令调试状态
-
- //调试开关
- #define SIMCOM_GSM_DBUG 1
- #if SIMCOM_GSM_DBUG
- #include "system.h"
- #define SIMCOM_GSM_debug(format,...) {if(g_SIMC0M_GSM_Debug){uart_printf(format,##__VA_ARGS__);}}
- #else
- #define SIMCOM_GSM_debug(format,...) /\
- /
- #endif //SIMCOM_GSM_DBUG
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_NetworkConfig(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, SIMCOM_SIM_SELECT SIM_Select)
- * 功能 : SIMCOM网络配置
- * 参数 : pHandle:句柄;ModeType:通信模块型号;SIM_Select:SIM卡选择;
- * 返回 : TRUE:成功,FALSE:失败
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2018-01-17
- * 最后修改时间 : 2018-03-24
- * 详细 :
- *************************************************************************************************************************/
- bool SIMCOM_NetworkConfig(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, NETWORK_CONFIG_TYPE *pConfig)
- {
- char buff[16];
-
- pConfig->ModeType = ModeType; //记录通信模块型号
- if(ModeType == SIMCOM_SIM7000C) //SIM7000C需要选择工作模式
- {
- switch(pConfig->NB_EnableMode)
- {
- case 0: //GSM模式
- {
- uart_printf("[DTU]设置GSM网络模式!\r\n");
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CNMP=13", SIMCOM_DEFAULT_RETRY, 200, "\r\n设置SIM7000C GSM模式失败!\r\n") == FALSE) return FALSE; //GSM模式
- }break;
- case 1://NB模式
- {
- uart_printf("[DTU]设置NBIOT网络模式!\r\n");
- 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)
- //CAT NB模式设置
- switch(pConfig->ModeType)
- {
- case CAT_M_MODE: //CAT模式
- {
- sprintf(buff,"AT+CMNB=%d",1); //cat模式
- }break;
- default:
- {
- sprintf(buff,"AT+CMNB=%d",2); //NBIOT模式
- }break;
- }
- 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
- //扰码设置
- if(pConfig->isNB_ScarEnable) //开启扰码
- {
- sprintf(buff,"AT+NBSC=%d",1);
- }
- else
- {
- sprintf(buff,"AT+NBSC=%d",0);
- }
- if(SIMCOM_SetParametersReturnBool(pHandle, buff, SIMCOM_DEFAULT_RETRY, 200, "\r\n设置SIM7000C NB 扰码模式失败!\r\n") == FALSE) return FALSE;
- }break;
- default:return TRUE; //忽略,无需设置
- }
- }
- return TRUE;
- }
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : SIM_CARD_STATUS SIMCOM_GetCPIN(SIMCOM_HANDLE *pHandle)
- * 功能 : 获取SIM卡状态
- * 参数 : 无
- * 返回 : FALSE:失败;TRUE:成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2014-06-26
- * 最后修改时间 : 2014-06-26
- * 说明 : 2017-09-05 : 增加SIM卡状态为3种状态
- *************************************************************************************************************************/
- SIM_CARD_STATUS SIMCOM_GetCPIN(SIMCOM_HANDLE *pHandle)
- {
- u32 cnt;
- char *p;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- int status;
- u8 *pData;
-
- do
- {
- //+CPIN: READY
- SIMCOM_SendAT(pHandle, "AT+CPIN?");
- pHandle->pClearRxData(); //清除接收计数器
- status = SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 200); //等待响应,超时200MS
- if(AT_RETURN_OK == status) //返回OK
- {
- p = strstr((const char*)pData, "+CPIN: READY"); //搜索字符"+CPIN: READY"
- if(p != NULL) //搜索成功
- {
- return SIM_READY; //SIM卡就绪
- }
- break;
- }
- else if(AT_RETURN_ERROR == status) //返回ERROR
- {
- p = strstr((const char*)pData, "ERROR"); //搜索卡未准备就绪标志
- if(p != NULL) //搜索成功
- {
- return SIM_NOT_READY; //SIM卡未就绪
- }
- break;
- }
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- return SIM_UNKNOWN; //SIM卡未知
- }
-
-
-
- /*************************************************************************************************************************
- * 函数 : SIMCOM_NETSTATUS SIM900_GetGSMNetworkStatus(SIMCOM_HANDLE *pHandle)
- * 功能 : 获取GSM网络注册状态
- * 参数 : pHandle:句柄
- * 返回 : SIMCOM_NETSTATUS
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-29
- * 最后修改时间 : 2018-03-24
- * 说明 : 当网络注册后,可能被拒绝,如果被拒绝,获取网络注册状态会提示
- 注册成功的,但是通过发送AT 后再去查询,会发现网络注册失败
- *************************************************************************************************************************/
- SIMCOM_NETSTATUS SIM900_GetGSMNetworkStatus(SIMCOM_HANDLE *pHandle)
- {
- u32 cnt;
- char *p;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- u8 *pData;
-
- do
- {
- //+CREG: 0,1
- SIMCOM_SendAT(pHandle, "AT+CREG?"); //发送"AT+CREG?",获取网络注册状态
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 200)) //等待响应,超时200MS
- {
- p = strstr((const char*)pData, "+CREG:"); //搜索字符"+CREG:"
- if(p != NULL) //搜索成功
- {
- SIMCOM_TestAT(pHandle, 1);
- return (SIMCOM_NETSTATUS)GSM_StringToDec(&p[9], 1);
- }
- break;
- }
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- SIMCOM_TestAT(pHandle, 2);
- return SIMCOM_NET_ERROR;
- }
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : SIMCOM_NETSTATUS SIMCOM_GetDataNetworkStatus(SIMCOM_HANDLE *pHandle)
- * 功能 : 获取数据网络注册状态
- * 参数 : pHandle:句柄
- * 返回 : SIMCOM_NETSTATUS
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-29
- * 最后修改时间 : 2018-03-24
- * 说明 : 用于获取NB数据网络或GPRS数据网络注册状态
- *************************************************************************************************************************/
- SIMCOM_NETSTATUS SIMCOM_GetDataNetworkStatus(SIMCOM_HANDLE *pHandle)
- {
- u32 cnt;
- char *p;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- u8 *pData;
-
- do
- {
- //+CGREG: 0,1
- SIMCOM_SendAT(pHandle, "AT+CGREG?"); //发送"AT+CGREG?",获取网络注册状态
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 200)) //等待响应,超时200MS
- {
- p = strstr((const char*)pData, "+CGREG:"); //搜索字符"+CGREG:"
- if(p != NULL) //搜索成功
- {
- SIMCOM_TestAT(pHandle, 1);
- return (SIMCOM_NETSTATUS)GSM_StringToDec(&p[10], 1);
- }
- break;
- }
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- SIMCOM_TestAT(pHandle, 2);
- return SIMCOM_NET_ERROR;
- }
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIM900_SetGPRS_PackDatatSize(SIMCOM_HANDLE *pHandle)
- * 功能 : 设置SIM900/SIM800 GPRS发送数据缓冲区
- * 参数 : pHandle:句柄
- * 返回 : FALSE:失败;TRUE:成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2014-09-11
- * 最后修改时间 : 2014-09-11
- * 说明 : 按照最大数据包1460B设置
- *************************************************************************************************************************/
- bool SIM900_SetGPRS_PackDatatSize(SIMCOM_HANDLE *pHandle)
- {
- char buff[36];
-
- //先开启透传模式才能设置
- SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPMODE=1", SIMCOM_DEFAULT_RETRY, 2000, "开启透传模式失败!\r\n"); //开启透传模式
-
- //设置GPRS传输数据包大小
- //AT+CIPCCFG=3,2,1024,1 //设置透传参数 //3-重传次数为3次,2-等待数据输入时间为 //2*200ms,1024-数据缓冲区为1024个字节 //1-支持转义退出透传
- sprintf(buff,"AT+CIPCCFG=3,2,%d,1",1460);
- return SIMCOM_SetParametersReturnBool(pHandle, buff, SIMCOM_DEFAULT_RETRY, 200, "GPRS发送数据缓冲区设置失败!\r\n"); //发送
- }
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_ModuleInit(SIMCOM_HANDLE *pHandle)
- * 功能 : 初始化SIMCOM模块基本配置(不允许失败)
- * 参数 : pHandle:句柄
- * 返回 : FALSE:初始化失败;TRUE:初始化成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-16
- * 最后修改时间 : 2018-03-24
- * 说明 : 必须先上电,并获取模块型号,根据不同的型号模块分别进行初始化
- *************************************************************************************************************************/
- bool SIMCOM_ModuleInit(SIMCOM_HANDLE *pHandle)
- {
- u8 retry = 5; //重试次数
-
- pHandle->pSetDTR_Pin(SIMCOM_L_LEVEL); //DTR=0,退出低功耗模式
- //检测模块存在,并保证通信正常
- SIMCOM_Ready(pHandle);
- SIMCOM_TestAT(pHandle, 20);
-
- switch(pHandle->SimcomModeType) //不同的芯片存在不一样的初始化
- {
- case SIMCOM_SIM2000: //SIM2000需要先关闭URC,否则会提示Call Ready
- {
- SIMCOM_SetParametersReturnBool(pHandle, "AT+CIURC=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭Call Ready显示失败!\r\n");
- }break;
- default:break;
- }
- //设置关闭回显
- if(SIMCOM_SetParametersReturnBool(pHandle, "ATE 0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭AT回显模式失败!\r\n") == FALSE)
- {
- return FALSE;
- }
- //设置短消息格式为PDU格式
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CMGF=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n设置短消息格式为PDU格式失败!\r\n") == FALSE)
- {
- uart_printf("\r\n设置DCD功能模式失败!\r\n");
- return FALSE;
- }
- //设置DCD功能模式,DCD线只在数据载波存在时为ON。
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT&C1", SIMCOM_DEFAULT_RETRY, 110, "\r\n设置DCD功能模式失败!\r\n") == FALSE)
- {
- uart_printf("\r\n设置DCD功能模式失败!\r\n");
- //return FALSE;
- }
- //设置 DTR 功能模式,DTR 由ON至OFF:TA在保持当前数据通话的同时,切换至命令模式
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT&D1", SIMCOM_DEFAULT_RETRY, 110, "\r\n设置DTR功能模式失败!\r\n") == FALSE)
- {
- uart_printf("\r\n设置DTR功能模式失败!\r\n");
- //return FALSE;
- }
-
- // //使能RI引脚提示
- // if(SIM900_SetParametersReturnBool("AT+CFGRI=1", SIMCOM_DEFAULT_RETRY, 11, "\r\n启动RI引脚提示失败!\r\n") == FALSE)
- // {
- // return FALSE;
- // }
-
- //设置模块sleep模式使能//发送"AT+CSCLK",启动SLEEP模式;0:关闭;1:手动;2:自动空闲5S钟后休眠
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CSCLK=1", SIMCOM_DEFAULT_RETRY, 110, "\r\n设置SLEEP失败!\r\n") == FALSE)
- {
- return FALSE;
- }
-
-
-
- //检查卡是否就绪
- retry = 8; //重试次数
- do
- {
- if(SIMCOM_GetCPIN(pHandle)==SIM_READY)
- {
- uart_printf("\r\nSIM卡准备就绪!\r\n");
- break;
- }
- else
- {
- uart_printf("\r\nSIM卡未准备就绪!\r\n");
- }
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
- if(retry == 0)
- {
- uart_printf("\r\nSIM卡未准备就绪!\r\n");
- pHandle->pClearRxData(); //清除接收计数器
- return FALSE;
- }
-
- // //上电删除所有短信
- // retry = SIMCOM_DEFAULT_RETRY; //重试次数
- // do
- // {
- // if(SIM900_DelMultiSMS(DelSMS) == TRUE)//删除短信
- // {
- // //uart_printf("上电删除短信成功!\r\n");
- // break;
- // }
- // SIM900_Ready(); //等待就绪
- // retry --;
- // }while(retry);
- // if(retry == 0)
- // {
- // uart_printf("上电删除短信失败!\r\n");
- // SIM900_ClearRxCnt(); //清除计数器
- // return FALSE;
- // }
-
- //2016-09-20:设置等待消息上报超时时间为1分钟,因为西宁项目卡出现超时情况
- switch(pHandle->SimcomModeType) //不同的芯片存在不一样的初始化
- {
- case SIMCOM_SIM800: //SIM800需要等待就绪时间长一些
- {
- retry = 65;
- }break;
- default:retry=35;break;
- }
-
- //关闭新消息自动上报
- while(retry)
- {
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CNMI=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭新消息自动上报失败!\r\n") == FALSE)
- {
- //return FALSE;
- }
- else break;
- pHandle->pDelayMS(1000); //延时1秒
- retry --;
- }
- if(retry == 0) return FALSE;
-
-
- switch(pHandle->SimcomModeType) //不同的芯片存在不一样的初始化
- {
- case LYNQ_L700: break;
- case SIMCOM_SIM7600:
- {
- //设置TCP收发相关
- retry = SIMCOM_DEFAULT_RETRY; //重试次数
- while(retry)
- {
- //设置重试次数为3次,并且发送延时为120ms
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPCCFG=3,100,,1,0,,1000", SIMCOM_DEFAULT_RETRY, 110, "\r\n配置TCP/IP失败!\r\n") == FALSE)
- {
- //return FALSE;
- }
- else break;
- pHandle->pDelayMS(1000); //延时1秒
- retry --;
- }
- if(retry == 0)
- {
- uart_printf("\r\n设置TCP重发次数以及发送延时失败!\r\n");
- pHandle->pClearRxData(); //清除接收计数器
- return FALSE;
- }
- //设置不用等到发送响应
- retry = SIMCOM_DEFAULT_RETRY; //重试次数
- while(retry)
- {
- //设置重试次数为3次,并且发送延时为120ms
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPSENDMODE=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n不用等待发送ACK设置失败!\r\n") == FALSE)
- {
- //return FALSE;
- }
- else break;
- pHandle->pDelayMS(1000); //延时1秒
- retry --;
- }
- if(retry == 0)
- {
- uart_printf("\r\n设置不用等待发送ACK失败!\r\n");
- pHandle->pClearRxData(); //清除接收计数器
- }
-
- //显示接收数据长度
- retry = SIMCOM_DEFAULT_RETRY; //重试次数
- while(retry)
- {
- //设置重试次数为3次,并且发送延时为120ms
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPHEAD=1", SIMCOM_DEFAULT_RETRY, 110, "\r\n显示接收数据长度设置失败!\r\n") == FALSE)
- {
- //return FALSE;
- }
- else break;
- pHandle->pDelayMS(1000); //延时1秒
- retry --;
- }
- if(retry == 0)
- {
- uart_printf("\r\n设置显示接收数据长度失败!\r\n");
- pHandle->pClearRxData(); //清除接收计数器
- return FALSE;
- }
-
- //不显示接收数据IP头
- retry = SIMCOM_DEFAULT_RETRY; //重试次数
- while(retry)
- {
- //设置重试次数为3次,并且发送延时为120ms
- if(SIMCOM_SetParametersReturnBool(pHandle, "AT+CIPSRIP=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n不显示接收数据IP头设置失败!\r\n") == FALSE)
- {
- //return FALSE;
- }
- else break;
- pHandle->pDelayMS(1000); //延时1秒
- retry --;
- }
- if(retry == 0)
- {
- uart_printf("\r\n不显示接收数据IP头失败!\r\n");
- pHandle->pClearRxData(); //清除接收计数器
- return FALSE;
- }
-
- }break;
- default: //2G模块均需要进行设置的
- {
- //设置GPRS发送数据缓冲区大小
- retry = SIMCOM_DEFAULT_RETRY; //重试次数
- do
- {
- if(SIM900_SetGPRS_PackDatatSize(pHandle) == TRUE)
- {
- break;
- }
- retry --;
- }while(retry);
- if(retry == 0)
- {
- uart_printf("\r\n设置GPRS传输大小失败!\r\n");
- pHandle->pClearRxData(); //清除接收计数器
- return FALSE;
- }
- }break;
- }
-
-
- pHandle->s_isInitStatus = TRUE; //模块成功初始化
- pHandle->pClearRxData(); //清除接收计数器
-
- return TRUE;
- }
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_GetModuleInfo(SIMCOM_HANDLE *pHandle, SIMCOM_INFO *pInfo)
- * 功能 : 获取模块的相关信息
- * 参数 : pHandle:句柄;pInfo:信息结构体指针
- * 返回 : FALSE:失败;TRUE:成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2014-07-29
- * 最后修改时间 : 2014-10-08
- * 说明 : SIMCOM_INFO_SIZE:限制最大长度
- SIMCOM_VER_SIZE:软件版本长度限制
- 2014-10-08:在个别模块上面遇到发送AT+GMI后返回了AT+GMI,导致获取失败,如果发现返回了AT+则重新获取,可以避免此问题
- 2016-12-07:修改获取模块型号指令为AT+CGMM,用于兼容SIM7600
- *************************************************************************************************************************/
- bool SIMCOM_GetModuleInfo(SIMCOM_HANDLE *pHandle, SIMCOM_INFO *pInfo)
- {
- u32 i,cnt;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- char *p;
- u8 *pData;
-
- //清空缓冲区
- pInfo->Manu[0] = 0;
- pInfo->Model[0] = 0;
- pInfo->Ver[0] = 0;
- pInfo->IMEI[0] = 0;
-
- retry = SIMCOM_DEFAULT_RETRY; //重试次数
- //获取制造商信息
- do
- {
- SIMCOM_TestAT(pHandle, 10);
- SIMCOM_SendAT(pHandle, "AT+GMI"); //请求制造商身份
-
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
- {
- //uart_printf("%s\r\n",pData);
- if(strstr((const char*)pData, "AT+") == NULL) //搜索关键字
- {
- for(i = 0;i < (SIMCOM_INFO_SIZE-1);i ++)
- {
- if((pData[2+i] == '\r') || (pData[2+i] == '\n') || (pData[2+i] == '\0')) break;
- pInfo->Manu[i] = pData[2+i];
- }
- pInfo->Manu[i] = 0;
- break;
- }
- }
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
- if(retry == 0) return FALSE;
-
- retry = SIMCOM_DEFAULT_RETRY; //重试次数
- //获取型号
- do
- {
- SIMCOM_SendAT(pHandle, "AT+CGMM");
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
- {
- for(i = 0;i < (SIMCOM_INFO_SIZE-1);i ++)
- {
- if((pData[2+i] == '\r') || (pData[2+i] == '\n') || (pData[2+i] == '\0')) break;
- pInfo->Model[i] = pData[2+i];
- }
- pInfo->Model[i] = 0;
- break;
- }
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
- if(retry == 0) return FALSE;
-
- retry = SIMCOM_DEFAULT_RETRY; //重试次数
- //获取软件版本
- do
- {
- SIMCOM_SendAT(pHandle, "AT+GMR");
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
- {
- p = strstr((char *)pData, "+GMR: ");
- if(p != NULL)
- {
- p+= strlen("+GMR: "); //SIM7600前面会有 +GMR: ,跳过即可
- for(i = 0;i < (SIMCOM_VER_SIZE-1);i ++)
- {
- if((p[i] == '\r') || (p[i] == '\n') || (p[i] == '\0')) break;
- pInfo->Ver[i] = p[i];
- }
- pInfo->Ver[i] = 0;
- }
- else
- {
- for(i = 0;i < (SIMCOM_VER_SIZE-1);i ++)
- {
- if((pData[2+i] == '\r') || (pData[2+i] == '\n') || (pData[2+i] == '\0')) break;
- pInfo->Ver[i] = pData[2+i];
- }
- pInfo->Ver[i] = 0;
- }
-
- break;
- }
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
- if(retry == 0) return FALSE;
-
- retry = SIMCOM_DEFAULT_RETRY; //重试次数
- //获取序列号
- do
- {
- SIMCOM_SendAT(pHandle, "AT+GSN");
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
- {
- for(i = 0;i < (SIMCOM_INFO_SIZE-1);i ++)
- {
- if((pData[2+i] == '\r') || (pData[2+i] == '\n') || (pData[2+i] == '\0')) break;
- pInfo->IMEI[i] = pData[2+i];
- }
- pInfo->IMEI[i] = 0;
- break;
- }
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
-
- return TRUE;
- }
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_COPS(SIMCOM_HANDLE *pHandle, char pCOPS_Buff[SIMCOM_INFO_SIZE])
- * 功能 : 获取运营商名称
- * 参数 : pHandle:句柄;pCOPS_Buff:运营商名称
- * 返回 : FALSE:失败;TRUE:成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2014-07-29
- * 最后修改时间 : 2018-03-24
- * 说明 : SIMCOM_INFO_SIZE 限制最大长度
- *************************************************************************************************************************/
- bool SIMCOM_COPS(SIMCOM_HANDLE *pHandle, char pCOPS_Buff[SIMCOM_INFO_SIZE])
- {
- u32 i,cnt;
- u8 retry = 5; //重试次数
- char *p;
- u8 *pData;
-
- //清空缓冲区
- pCOPS_Buff[0] = 0;
-
- switch(pHandle->SimcomModeType) //不同的芯片存在不一样的初始化
- {
- case SIMCOM_SIM2000: //SIM2000需要多次读取,等待的时间比较长
- {
- retry = 28;
- }break;
- default:break;
- }
-
- //获取运营商
- do
- {
- SIMCOM_SendAT(pHandle, "AT+COPS?"); //显示模块当前注册的网络运营商
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 150)) //等待响应,超时300MS
- {
- p = strstr((const char*)pData, "\"");
- if(p != NULL)
- {
- p ++;
- for(i = 0;i < (SIMCOM_INFO_SIZE-1);i ++)
- {
- if((p[i] == '\r') || (p[i] == '\n') || (p[i] == '\0') || (p[i] == '\"')) break;
- pCOPS_Buff[i] = p[i];
- }
- pCOPS_Buff[i] = 0;
- return TRUE;
- }
- }
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //延时1秒
- retry --;
- }while(retry);
-
-
- return FALSE; //超时//错误
- }
-
-
-
- /*************************************************************************************************************************
- * 函数 : SIMCOM_NETMODE_TYPE SIM7XXX_GetNetworkMode(SIMCOM_HANDLE *pHandle)
- * 功能 : 获取SIM7XXX系列模块网络制式
- * 参数 : pHandle:句柄
- * 返回 : SIMCOM_NETMODE_TYPE
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2016-12-29
- * 最后修改时间 : 2018-03-24
- * 说明 : 用于从SIM7600模块网络制式
- 必须在网络注册成功后进行获取,正常返回
- +CNSMOD: 0,15
- 用于SIM7000系列获取网制式
- *************************************************************************************************************************/
- SIMCOM_NETMODE_TYPE SIM7XXX_GetNetworkMode(SIMCOM_HANDLE *pHandle)
- {
- u32 cnt;
- u8 retry = 3;
- char *p;
- int temp;
- u8 *pData;
-
- //获取型号
- do
- {
- SIMCOM_SendAT(pHandle, "AT+CNSMOD?");
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
- {
- p = strstr((char *)pData, "+CNSMOD: 0,");
- if(p==NULL) p = strstr((char *)pData, "+CNSMOD: 1,");
- p += strlen("+CNSMOD: 0,");
- temp = atoi(p);
- if(temp > 16) continue;
- else return (SIMCOM_NETMODE_TYPE)temp;
- }
-
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- return SIMCOM_NETMODE_NULL;
- }
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_HardwarePowerUP(SIMCOM_HANDLE *pHandle, bool isTest)
- * 功能 : SIMCOM模块硬件开机
- * 参数 : pHandle:句柄;isTest:是否检测开机是否成功,通过STATUS脚变为高电平可以检测是否开机成功
- * 返回 : 开机是否成功
- * 依赖 : 无
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-29
- * 最后修改时间 : 2018-03-24
- * 说明 : 用于SIM900模块开机,拉低PWR
- 2016-12-07:修改动态监测是否上电成功,增加SIM7600CE兼容
- *************************************************************************************************************************/
- bool SIMCOM_HardwarePowerUP(SIMCOM_HANDLE *pHandle, bool isTest)
- {
- u8 i,j;
-
- pHandle->pSetDTR_Pin(SIMCOM_L_LEVEL); //DTR=0,退出低功耗模式
- pHandle->s_isInitStatus = FALSE; //模块没有初始化,需要重新初始化
- if(isTest) //需要检测是否开机成功
- {
- if(pHandle->pGetSTATUS_Pin() == SIMCOM_H_LEVEL) //开机脚已经是高电平了
- {
- return TRUE;
- }
- for(i = 0;i < 2;i ++)
- {
- pHandle->pSetPWRKEY_Pin(SIMCOM_L_LEVEL); //拉低1200ms开机
- pHandle->pDelayMS(1200);
- pHandle->pSetPWRKEY_Pin(SIMCOM_H_LEVEL); //恢复高电平
- for(j = 0;j < 6;j ++)
- {
- pHandle->pDelayMS(1000);
- if(pHandle->pGetSTATUS_Pin() == SIMCOM_H_LEVEL) //开机脚已经是高电平了
- {
- return TRUE;
- }
- }
- }
-
- return FALSE;
- }
- else //无需检测是否开机成功
- {
- pHandle->pSetPWRKEY_Pin(SIMCOM_L_LEVEL); //拉低1200ms开机
- pHandle->pDelayMS(1200);
- pHandle->pSetPWRKEY_Pin(SIMCOM_H_LEVEL); //恢复高电平
- pHandle->pDelayMS(3000);; //延时3S等待开机完毕
-
- return TRUE;
- }
- }
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_HardwarePowerDOWN(SIMCOM_HANDLE *pHandle, bool isTest)
- * 功能 : SIMCOM模块硬件关机
- * 参数 : pHandle:句柄;isTest:是否检测开机是否成功,通过STATUS脚变为高电平可以检测是否关机成功
- * 返回 : 关机是否成功
- * 依赖 : 无
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-29
- * 最后修改时间 : 2018-03-24
- * 说明 : 用于SIM900模块关机机,拉低PWR大于1S小于5S
- 2016-12-07:优化关机,兼容SIM7600
- 一定要先获取模块型号,不同模块关机时间不一样
- *************************************************************************************************************************/
- bool SIMCOM_HardwarePowerDOWN(SIMCOM_HANDLE *pHandle, bool isTest)
- {
- u8 i,j;
-
- pHandle->s_isInitStatus = FALSE; //模块没有初始化,需要重新初始化
- if(isTest) //需要检测是否开机成功
- {
- if(pHandle->pGetSTATUS_Pin() == SIMCOM_L_LEVEL) //开机脚已经是低电平了
- {
- return TRUE;
- }
- for(i = 0;i < 2;i ++)
- {
- pHandle->pSetPWRKEY_Pin(SIMCOM_L_LEVEL); //拉低1200ms关机
- switch(pHandle->SimcomModeType)
- {
- case SIMCOM_SIM7600:
- {
- pHandle->pDelayMS(3000); //SIM7600关机至少2.5S
- }break;
- default:
- {
- pHandle->pDelayMS(1000);
- }break;
- }
-
- pHandle->pDelayMS(200);
- pHandle->pSetPWRKEY_Pin(SIMCOM_H_LEVEL); //恢复高电平
- for(j = 0;j < 5;j ++)
- {
- pHandle->pDelayMS(3000); //延时3S等待关机完毕
- if(pHandle->pGetSTATUS_Pin() == SIMCOM_L_LEVEL) //开机脚已经是低电平了
- {
- return TRUE;
- }
- }
- }
-
- return FALSE;
- }
- else //无需检测是否开机成功
- {
- pHandle->pSetPWRKEY_Pin(SIMCOM_L_LEVEL); //拉低1200ms关机
- pHandle->pDelayMS(1200);
- pHandle->pSetPWRKEY_Pin(SIMCOM_H_LEVEL); //恢复高电平
- pHandle->pDelayMS(3000);; //延时3S等待关机完毕
-
- return TRUE;
- }
- }
-
-
- /*************************************************************************************************************************
- * 函数 : SIMCOM_MODE_TYPE SIMCOM_GetMode(SIMCOM_HANDLE *pHandle)
- * 功能 : 获取SIMCOM模块的型号
- * 参数 : pHandle:句柄
- * 返回 : 型号,见SIMCOM_MODE_TYPE
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2015-09-12
- * 最后修改时间 : 2015-09-12
- * 说明 : 用于识别型号,对应初始化
- 2016-12-07:修改指令为AT+CGMM,兼容SIM7600,(旧指令:AT+GOI)
- *************************************************************************************************************************/
- SIMCOM_MODE_TYPE SIMCOM_GetMode(SIMCOM_HANDLE *pHandle)
- {
- u32 cnt;
- u8 retry = SIMCOM_DEFAULT_RETRY+1;
- u8 *pData;
-
- //获取型号
- do
- {
- SIMCOM_SendAT(pHandle, "AT+CGMM");
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 200)) //等待响应,超时200MS
- {
- if(strstr((char *)pData, "SIM900") != NULL) return SIMCOM_SIM900;
- else if(strstr((char *)pData, "SIM800") != NULL) return SIMCOM_SIM800;
- else if(strstr((char *)pData, "SIM2000") != NULL) return SIMCOM_SIM2000;
- else if(strstr((char *)pData, "SIM7600") != NULL) return SIMCOM_SIM7600;
- else if(strstr((char *)pData, "SIMCOM_SIM868") != NULL) return SIMCOM_SIM868;
- else if(strstr((char *)pData, "SIMCOM_SIM7000C") != NULL) return SIMCOM_SIM7000C;
- else if(strstr((char *)pData, "LYNQ_L700") != NULL) return LYNQ_L700;
- else
- {
- uart_printf("未知通信模块:%s\r\n",pData);
- return SIMCOM_INVALID;
- }
- }
-
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- return SIMCOM_INVALID;
- }
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_GetServeNumber(PHONE_NUMBER *pServeNumber)
- * 功能 : 获取短信服务中心号码(会去掉前面的86,限制长度15位,不能用于SIM7000,SIM2000以及电信卡)
- * 参数 : pServeNumber:电话号码存储缓冲区指针
- * 返回 : FALSE:通信失败;TRUE:通信成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-20
- * 最后修改时间 : 2013-10-20
- * 说明 : 获取SIM卡内部的短信服务中心号码,一般在办理SIM卡的时候已经进行了设置.
- 如果没有预置短信中心号码需要使用手机进行设置
- 2014-07-12:只要返回OK则认为成功,因为有可能没有设置短信中心号码
- 2016-01-26:自动选择是否跳过+86
- *************************************************************************************************************************/
- bool SIMCOM_GetServeNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16])
- {
- u8 i,n;
- u32 cnt;
- char *p,*p1;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- u8 *pData;
-
- do
- {
- //+CSCA: "+8613800270500",145
- SIMCOM_SendAT(pHandle, "AT+CSCA?"); //发送"AT+CSCA",获取短信服务中心号码
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 30, 600)) //等待响应,超时600MS
- {
- p = strstr((const char*)pData, "+CSCA:"); //搜索字符"+CSCA:"
- if(p != NULL) //搜索成功
- {
- p = strstr(p+1, "+"); //搜索"+"
- if(p != NULL)
- {
- p1 = strstr(p+1, "\""); //搜索"\""
- if(p1 != NULL)
- {
- if(p[0] == '+') //如果是+开头,则跳过加号
- {
- p+=3; //跳过+86
- }
- else if(p[0]=='8' && p[1] == '6') //跳过86
- {
- p+=2;
- }
- n = p1 - p; //计算电话号码长度
- if(n > 15) n = 15; //限制号码长度为15字节
- for(i = 0;i < n;i ++)
- {
- pPhoneNumber[i] = p[i]; //复制电话号码
- }
- pPhoneNumber[i] = '\0'; //添加结束符
-
- SIMCOM_GSM_debug("短信中心号码:%s\r\n",pPhoneNumber);
-
- return TRUE;
- }
- }
- }
- else
- {
- pPhoneNumber[0] = '\0';
- SIMCOM_GSM_debug("短信中心号码:为空,没有设置\r\n");
-
- return TRUE;
- }
- }
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- return FALSE;
- }
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_GetPhoneNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16])
- * 功能 : 获取本机号码(会去掉前面的86,限制长度15位,不能用于SIM7000,SIM2000以及电信卡)
- * 参数 : pHandle:句柄;pPhoneNumber:号码缓冲区
- * 返回 : FALSE:通信失败;TRUE:通信成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-20
- * 最后修改时间 : 2018-03-24
- * 说明 : 通常会预存本机号码到SIM卡,也可能没有(不能用于SIM7000,SIM2000C,不能用于电信卡)
- 2014-07-12:只要返回OK则认为成功,因为有可能没有设置电话号码
- 2016-01-26:修改字节超时,否则某些卡会出现超时,没有收到OK
- 自动选择是否跳过+86
- *************************************************************************************************************************/
- bool SIMCOM_GetPhoneNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16])
- {
- u8 n;
- u8 i;
- u32 cnt;
- char *p,*p1;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- u8 *pData;
-
-
- do
- {
- //+CNUM: "","15871750634",129,7,4
- SIMCOM_SendAT(pHandle, "AT+CNUM"); //发送"AT++CNUM",获取号码
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 30, 600)) //等待响应,超时600MS
- {
- p = strstr((const char*)pData, "+CNUM:"); //搜索字符"+CNUM:"
- if(p != NULL) //搜索成功
- {
- p = strstr(p+1, "\",\""); //搜索"," //开始
- if(p != NULL)
- {
- p1 = strstr(p+3, "\","); //搜索",//结束
- if(p1 != NULL)
- {
- p+=3; //跳过","
- if(p[0] == '+') //如果是+开头,则跳过加号
- {
- p+=3; //跳过+86
- }
- else if(p[0]=='8' && p[1] == '6') //跳过86
- {
- p+=2;
- }
-
- n = p1 - p; //计算电话号码长度
- if(n > 15) n = 15; //限制号码长度为15字节
- for(i = 0;i < n;i ++)
- {
- pPhoneNumber[i] = p[i]; //复制电话号码
- }
- pPhoneNumber[i] = '\0'; //添加结束符
- SIMCOM_GSM_debug("本机号码:%s\r\n",pPhoneNumber);
-
- return TRUE;
- }
- }
- }
- else
- {
- pPhoneNumber[0] = '\0';
-
- SIMCOM_GSM_debug("本机号码:为空,没有设置\r\n");
- return TRUE;
- }
- }
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- return FALSE;
- }
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_GetBookNumber(SIMCOM_HANDLE *pHandle, u8 index, char pPhoneNumber[16])
- * 功能 : 从电话簿获取一个电话号码(不能用于SIM7000)
- * 参数 : pHandle:句柄;index:电话号码所有,1-255;CenterPhone:电话号码存储缓冲区指针
- * 返回 : FALSE:通信失败;TRUE:通信成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-20
- * 最后修改时间 : 2016-06-15
- * 说明 : 用于从电话簿读取一个电话号码,常用语电信卡SIM2000C模块存储本机号码到第一个索引
- *************************************************************************************************************************/
- bool SIMCOM_GetBookNumber(SIMCOM_HANDLE *pHandle, u8 index, char pPhoneNumber[16])
- {
- u8 i,n;
- u32 cnt;
- char *p,*p1;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- u8 *pData;
- char buff[32];
-
- if(index < 1) return FALSE; //索引从1开始
- do
- {
- //+CPBR: 1,"152778787878",129,"Phone"
- sprintf(buff,"AT+CPBR=%d",index);
- SIMCOM_SendAT(pHandle, buff); //发送"AT+CPBR=1",获取号码
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 30, 600)) //等待响应,超时600MS
- {
- p = strstr((const char*)pData, "+CPBR:"); //搜索字符"+CPBR:"
- if(p != NULL) //搜索成功
- {
- p = strstr(p+1, ",\""); //搜索," //开始
- if(p != NULL)
- {
- p1 = strstr(p+2, "\","); //搜索",//结束
- if(p1 != NULL)
- {
- p+=2; //跳过,"
- if(p[0] == '+') //如果是+开头,则跳过加号
- {
- p+=3; //跳过+86
- }
- else if(p[0]=='8' && p[1] == '6') //跳过86
- {
- p+=2;
- }
-
- n = p1 - p; //计算电话号码长度
- if(n > 15) n = 15; //限制号码长度为15字节
- for(i = 0;i < n;i ++)
- {
- pPhoneNumber[i] = p[i]; //复制电话号码
- }
- pPhoneNumber[i] = '\0'; //添加结束符
-
- SIMCOM_GSM_debug("号码:%s\r\n",pPhoneNumber);
- return TRUE;
- }
- }
- }
- else
- {
- pPhoneNumber[0] = '\0';
- SIMCOM_GSM_debug("号码:为空\r\n");
-
- return TRUE;
- }
- }
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- return FALSE;
- }
-
-
- /*************************************************************************************************************************
- * 函数 : int SIMCOM_GetSignal(SIMCOM_HANDLE *pHandle)
- * 功能 : 获取信号强度
- * 参数 : pHandle:句柄
- * 返回 : <0:获取失败;0-31:信号强度;
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2013-10-21
- * 最后修改时间 : 2013-10-21
- * 说明 : 无
- *************************************************************************************************************************/
- int SIMCOM_GetSignal(SIMCOM_HANDLE *pHandle)
- {
- u8 temp;
- u32 cnt;
- char *p;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- u8 *pData;
-
- do
- {
- //+CSQ: 27,0
- //+CSQ: 5,0
- //+CSQ: 16,99
- SIMCOM_SendAT(pHandle,"AT+CSQ"); //发送"AT++CSQ",获取号码
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 400)) //等待响应,超时400MS
- {
- p = strstr((const char*)pData, "+CSQ:"); //搜索字符"+CSQ:"
- if(p != NULL) //搜索成功
- {
- if(p[7] != ',' && p[8] != ',') p[8] = '\0';
- temp = atoi(&p[6]);
-
- return temp;
- }
- break;
- }
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- return -1;
- }
-
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_GetCIMI(SIMCOM_HANDLE *pHandle, char pCIMI[16])
- * 功能 : 获取SIM卡CIMI号码(SIM卡唯一id,必须存在)
- * 参数 : pHandle:句柄;pCIMI:CIMI缓冲区,长15字节
- * 返回 : FALSE:通信失败;TRUE:通信成功
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2017-11-16
- * 最后修改时间 : 2018-03-24
- * 说明 : 用于获取卡唯一CIMI编号,防止某些卡无法读取本机号码,这个与卡号一一对应
- *************************************************************************************************************************/
- bool SIMCOM_GetCIMI(SIMCOM_HANDLE *pHandle, char pCIMI[16])
- {
- u32 cnt;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- u8 *pData;
-
- do
- {
- //460041037206894
- SIMCOM_SendAT(pHandle, "AT+CIMI"); //发送"AT+CIMI"
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 20, 200)) //等待响应,超时200MS
- {
- if(pData[0]!='\r' || pData[1]!='\n') continue;
- memcpy(pCIMI, &pData[2], 15); //跳过前面\r\n
- pCIMI[15] = 0; //添加结束符
-
- SIMCOM_GSM_debug("获取CIMI成功:%s\r\n", pCIMI);
- return TRUE;
- }
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- return FALSE;
- }
-
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIM7000C_GetNB_APN(SIMCOM_HANDLE *pHandle, char pAPN[17])
- * 功能 : 获取SIM7000C NBIOT 接入点
- * 参数 : pHandle:句柄;pAPN:接入点缓冲区
- * 返回 : TRUE:成功;FALSE:失败
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2018-01-16
- * 最后修改时间 : 2018-01-16
- * 说明 : 必须是NBIOT模式才能使用
- *************************************************************************************************************************/
- bool SIM7000C_GetNB_APN(SIMCOM_HANDLE *pHandle, char pAPN[17])
- {
- u32 cnt;
- char *p;
- u8 retry = SIMCOM_DEFAULT_RETRY; //重试次数
- u8 *pData;
- u8 i;
-
- do
- {
- //+CGNAPN: 1,"ctnb"
- SIMCOM_SendAT(pHandle, "AT+CGNAPN"); //发送AT指令
- pHandle->pClearRxData(); //清除接收计数器
- if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 2000)) //等待响应,超时2000MS
- {
- p = strstr((const char*)pData, "+CGNAPN: 1,\""); //搜索字符+CGNAPN: 1,"
- if(p != NULL) //搜索成功
- {
- p += strlen("+CGNAPN: 1,\"");
- for(i = 0;i < 17;i ++)
- {
- if(p[i] == '\"') //结束符号位 ”
- {
- pAPN[i] = 0;
- if(i == 0) break; //太短了
- return TRUE;
- }
- pAPN[i] = p[i];
- }
- }
- }
-
- SIMCOM_Ready(pHandle); //等待就绪
- pHandle->pDelayMS(1000); //失败延时1秒后重试
- retry --;
- }while(retry);
-
- return FALSE;
- }
-
//SIMCOM_GSM.h
- /*************************************************************************************************************
- * 文件名: SIMCOM_GSM.h
- * 功能: SIMCOM GSM相关接口
- * 作者: cp1300@139.com
- * 创建时间: 2015-02-15
- * 最后修改时间: 2018-03-23
- * 详细:
- *************************************************************************************************************/
- #ifndef _SIMCOM_GSM_H_
- #define _SIMCOM_GSM_H_
- #include "system.h"
- #include "simcom.h"
-
- bool SIMCOM_NetworkConfig(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, NETWORK_CONFIG_TYPE *pConfig); //SIMCOM网络配置
- SIM_CARD_STATUS SIMCOM_GetCPIN(SIMCOM_HANDLE *pHandle); //获取SIM卡状态
- SIMCOM_NETSTATUS SIM900_GetGSMNetworkStatus(SIMCOM_HANDLE *pHandle); //获取GSM网络注册状态
- SIMCOM_NETSTATUS SIMCOM_GetDataNetworkStatus(SIMCOM_HANDLE *pHandle); //获取数据网络注册状态
- bool SIMCOM_ModuleInit(SIMCOM_HANDLE *pHandle); //初始化SIMCOM模块基本配置(不允许失败)
- bool SIMCOM_GetModuleInfo(SIMCOM_HANDLE *pHandle, SIMCOM_INFO *pInfo); //获取模块的相关信息
- bool SIMCOM_COPS(SIMCOM_HANDLE *pHandle, char pCOPS_Buff[SIMCOM_INFO_SIZE]); //获取运营商名称
- SIMCOM_NETMODE_TYPE SIM7XXX_GetNetworkMode(SIMCOM_HANDLE *pHandle); //获取SIM7XXX系列模块网络制式
- bool SIMCOM_HardwarePowerUP(SIMCOM_HANDLE *pHandle, bool isTest); //SIMCOM模块硬件开机
- bool SIMCOM_HardwarePowerDOWN(SIMCOM_HANDLE *pHandle, bool isTest); //SIMCOM模块硬件关机
- SIMCOM_MODE_TYPE SIMCOM_GetMode(SIMCOM_HANDLE *pHandle); //获取SIMCOM模块的型号
- int SIMCOM_GetSignal(SIMCOM_HANDLE *pHandle); //获取信号强度
- bool SIMCOM_GetBookNumber(SIMCOM_HANDLE *pHandle, u8 index, char pPhoneNumber[16]); //从电话簿获取一个电话号码(不能用于SIM7000)
- bool SIMCOM_GetPhoneNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16]); //获取本机号码(会去掉前面的86,限制长度15位,不能用于SIM7000,SIM2000以及电信卡)
- bool SIMCOM_GetServeNumber(SIMCOM_HANDLE *pHandle, char pPhoneNumber[16]); //获取短信服务中心号码(会去掉前面的86,限制长度15位,不能用于SIM7000,SIM2000以及电信卡)
- bool SIMCOM_GetCIMI(SIMCOM_HANDLE *pHandle, char pCIMI[16]); //获取SIM卡CIMI号码(SIM卡唯一id,必须存在)
- bool SIM7000C_GetNB_APN(SIMCOM_HANDLE *pHandle, char pAPN[17]); //获取SIM7000C NBIOT 接入点
-
- #endif /*_SIMCOM_GSM_H_*/
//SIMCOM_USER.c
- /*************************************************************************************************************
- * 文件名: SIMCOM_USER.c
- * 功能: SIMCOM用户层函数
- * 作者: cp1300@139.com
- * 创建时间: 2015-02-15
- * 最后修改时间: 2018-03-23
- * 详细:
- *************************************************************************************************************/
- #include "system.h"
- #include "usart.h"
- #include "string.h"
- #include "ucos_ii.h"
- #include "SIMCOM_USER.h"
- #include "SIMCOM_GSM.h"
- #include "SIMCOM_GPRS.h"
- #include "SIMCOM_AT.h"
- #include "SIMCOM.h"
-
- bool g_SIMC0M_USER_Debug = TRUE; //应用层指令调试状态
-
- //调试开关
- #define SIMCOM_USER_DBUG 1
- #if SIMCOM_USER_DBUG
- #include "system.h"
- #define SIMCOM_USER_debug(format,...) {if(g_SIMC0M_USER_Debug){uart_printf(format,##__VA_ARGS__);}}
- #else
- #define SIMCOM_USER_debug(format,...) /\
- /
- #endif //SIMCOM_USER_DBUG
-
- const char *const SIMCOM_NETWORK_NAME[18] = {"未注册","GSM","GPRS","EGPRS (EDGE)","WCDMA","HSDPA only(WCDMA)","HSUPA only(WCDMA)","HSPA (HSDPA and HSUPA, WCDMA)",
- "LTE","TDS-CDMA","TDS-HSDPA only","TDS-HSUPA only","TDS- HSPA (HSDPA and HSUPA)","CDMA","EVDO","HYBRID (CDMA and EVDO)","1XLTE(CDMA and LTE)","未知,错误"};
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_Init(SIMCOM_HANDLE *pHandle,
- bool (* pSendData)(u8 *pDataBuff, u16 DataLen),
- int (* pReadData)(u8 **pDataBuff, u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelay),
- void (*pClearRxData)(void),
- void (*pSetDTR_Pin)(u8 Level),
- void (*pSetPWRKEY_Pin)(u8 Level),
- u8 (*pGetSTATUS_Pin)(void),
- u8 (*pGetDCD_Pin)(void),
- void (*pDelayMS)(u32 ms),
- void (*pIWDG_Feed)(void)
- * 功能 : 初始化SIMCOM句柄接口
- * 参数 : pSl651_Handle:句柄;
- pSendCallBack:发送回调函数(pDataBuff:发送数据缓冲区,DataLen:发送数据长度)
- pReadCallBack:接收数据回调函数,会等待直到数据被写入到接收缓冲区(pDataBuff:接收数据缓冲区,ByteTimeOut:等待的字节超时时间,单位ms,TimeOut:数据包超时时间,单位ms)
- pClearRxData:清除接收缓冲区函数,用于清除接收数据缓冲区数据
- pSetDTR_Pin:DTR引脚电平控制-用于控制sleep模式或者退出透传模式
- pSetPWRKEY_Pin:PWRKEY开机引脚电平控制-用于开机
- pGetSTATUS_Pin:获取STATUS引脚电平-用于指示模块上电状态
- pGetDCD_Pin:获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
- pDelayMS:系统延时函数
- pIWDG_Feed:清除系统看门狗(可以为空)
- * 返回 : 无
- * 依赖 : TRUE:成功,FALSE:失败
- * 作者 : cp1300@139.com
- * 时间 : 2018-03-24
- * 最后修改时间 : 2018-03-24
- * 说明 : 除pIWDG_Feed接口可以为空,其余接口均不能为空,否则程序会崩溃
- *************************************************************************************************************************/
- bool SIMCOM_Init(SIMCOM_HANDLE *pHandle,
- bool (* pSendData)(u8 *pDataBuff, u16 DataLen), //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
- int (* pReadData)(u8 **pDataBuff, u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelay), //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
- void (*pClearRxData)(void), //清除接收缓冲区函数,用于清除接收数据缓冲区数据
- void (*pSetDTR_Pin)(u8 Level), //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
- void (*pSetPWRKEY_Pin)(u8 Level), //PWRKEY开机引脚电平控制-用于开机
- u8 (*pGetSTATUS_Pin)(void), //获取STATUS引脚电平-用于指示模块上电状态
- u8 (*pGetDCD_Pin)(void), //获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
- void (*pDelayMS)(u32 ms), //系统延时函数
- void (*pIWDG_Feed)(void) //清除系统看门狗(可以为空)
- )
- {
- if(pHandle == NULL)
- {
- DEBUG("无效的句柄!\r\n");
- return FALSE;
- }
- //所需变量
- pHandle->SimcomModeType = SIMCOM_INVALID; //模块型号
- pHandle->TelecomCarr[0] = 0; //运营商名称
- memset(&pHandle->SIMCOM_Info, 0, sizeof(SIMCOM_INFO)); //SIMCOM通信模块相关信息结构体
- memset(&pHandle->NetworkConfig, 0, sizeof(NETWORK_CONFIG_TYPE)); //网络模式设置
- pHandle->NetworkMode = SIMCOM_NETMODE_NULL; //当前网络制式
-
-
- //底层通信接口
- pHandle->pSendData = pSendData; //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
- pHandle->pReadData = pReadData; //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
- pHandle->pClearRxData = pClearRxData; //清除接收缓冲区函数,用于清除接收数据缓冲区数据
- pHandle->pSetDTR_Pin = pSetDTR_Pin; //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
- pHandle->pSetPWRKEY_Pin = pSetPWRKEY_Pin; //PWRKEY开机引脚电平控制-用于开机
- pHandle->pGetSTATUS_Pin = pGetSTATUS_Pin; //获取STATUS引脚电平-用于指示模块上电状态
- pHandle->pGetDCD_Pin = pGetDCD_Pin; //获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
- //系统接口
- pHandle->pDelayMS = pDelayMS; //系统延时函数
- pHandle->pIWDG_Feed = pIWDG_Feed; //清除系统看门狗(可以为空)
- //内部状态定义
- pHandle->s_isInitStatus = FALSE; //用于记录模块初始化状态,复位或上电后变为无效
- //检查是否有接口为空
- if(pHandle->pSendData==NULL || pHandle->pReadData==NULL || pHandle->pClearRxData==NULL || pHandle->pSetDTR_Pin==NULL || pHandle->pSetPWRKEY_Pin==NULL ||
- pHandle->pGetSTATUS_Pin==NULL || pHandle->pGetDCD_Pin==NULL || pHandle->pDelayMS==NULL)
- {
- DEBUG("错误,有回调接口为空!\r\n");
- return FALSE;
- }
-
- return TRUE;
- }
-
-
-
- /*************************************************************************************************************************
- * 函数 : void SIMCOM_PrintfModel(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, const char **pModeInof)
- * 功能 : 显示并打印模块型号
- * 参数 : pHandle:句柄;ModeType:模块型号;pModeInof:返回模块型号信息(不需要可以为空)
- * 返回 : 无
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2017-10-17
- * 最后修改时间 : 2018-03-24
- * 说明 :
- *************************************************************************************************************************/
- void SIMCOM_PrintfModel(SIMCOM_HANDLE *pHandle, SIMCOM_MODE_TYPE ModeType, const char **pModeInof)
- {
- switch(ModeType)
- {
- case SIMCOM_SIM900 : //默认为SIM900
- {
- if(pModeInof!=NULL) *pModeInof = "SIM900系列";//通信模块型号
- uart_printf("[DTU]通信模块为SIM900\r\n");
- }break;
- case SIMCOM_SIM800 : //SIM800
- {
- if(pModeInof!=NULL) *pModeInof = "SIM800系列"; //通信模块型号
- uart_printf("[DTU]通信模块为SIM800\r\n");
- }break;
- case SIMCOM_SIM2000 : //SIM2000
- {
-
- if(pModeInof!=NULL) *pModeInof = "SIM2000系列"; //通信模块型号
- uart_printf("[DTU]通信模块为SIM2000\r\n");
- }break;
- case SIMCOM_SIM7600 : //SIM7600
- {
- if(pModeInof!=NULL) *pModeInof = "SIM7600系列"; //通信模块型号
- uart_printf("[DTU]通信模块为SIM7600\r\n");
- }break;
- case SIMCOM_SIM868: //SIM868
- {
- if(pModeInof!=NULL) *pModeInof = "SIM868系列"; //通信模块型号
- uart_printf("[DTU]通信模块为SIM868模块\r\n");
- }break;
- case SIMCOM_SIM7000C: //SIM7000C
- {
- if(pModeInof!=NULL) *pModeInof = "SIM7000C系列"; //通信模块型号
- uart_printf("[DTU]通信模块为SIM7000C\r\n");
- }break;
- case LYNQ_L700: //LYNQ_L700
- {
- if(pModeInof!=NULL) *pModeInof = "L700系列"; //通信模块型号
- uart_printf("[DTU]通信模块为L700模块\r\n");
- }break;
- case SIMCOM_INVALID : //无效则默认
- {
- if(pModeInof!=NULL) *pModeInof = "未知"; //通信模块型号
- uart_printf("[DTU]通信模块未知!\r\n");
- }break;
- }
- }
-
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : SIMCOM_USER_ERROR SIMCOM_RegisNetwork(SIMCOM_HANDLE *pHandle, u16 Retry, u16 NetworkDelay,const char **pModeInof)
- * 功能 : SIMCOM模块上电初始化并注册网络
- * 参数 : pHandle:句柄;Retry:初始化重试次数>0;NetworkDelay:注册网络延时时间,单位S;pModeInof:返回模块型号信息(不需要可以为空)
- * 返回 : SIMCOM_USER_ERROR
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2014-08-18
- * 最后修改时间 : 2018-03-24
- * 说明 : 用于通信模块上电并初始化操作
- *************************************************************************************************************************/
- SIMCOM_USER_ERROR SIMCOM_RegisNetwork(SIMCOM_HANDLE *pHandle, u16 Retry, u16 NetworkDelay,const char **pModeInof)
- {
- SIMCOM_NETSTATUS NetStatus;
- SIMCOM_MODE_TYPE ModeType = SIMCOM_INVALID; //初始化模块型号无效
- SIMCOM_NETMODE_TYPE NetworkMode = SIMCOM_NETMODE_NULL; //初始化为未知模式
- SIMCOM_USER_ERROR Error = SIMCOM_NULL_ERROR; //初始化状态
-
- u16 pcnt,cnt;
- u8 NotCnt,SeaCnt,TurCnt,UnkCnt,ErrCnt;
- bool isCart = FALSE;
- u8 SIM_NotReadyCnt = 0; //SIM卡未准备就绪计数器
-
- Retry += 1; //重试次数至少1次
- //模块上电
- for(pcnt = 0;pcnt < Retry;pcnt ++) //上电循环
- {
- SIM_NotReadyCnt = 0; //SIM卡未准备就绪计数器复位
- if(pHandle->pIWDG_Feed!=NULL) pHandle->pIWDG_Feed(); //喂狗
-
- if(pHandle->pGetSTATUS_Pin()==SIMCOM_L_LEVEL) //模块没有上电
- {
- pHandle->s_isInitStatus = FALSE; //模块没有初始化
- SIMCOM_USER_debug("[SIMCOM]:模块没有上电!\r\n");
- if(SIMCOM_HardwarePowerUP(pHandle, TRUE) == TRUE) //上电
- {
- SIMCOM_USER_debug("[SIMCOM]:开机成功!\r\n");
- if(SIMCOM_TestAT(pHandle, 50) != TRUE) //发送AT测试命令
- {
- if(pModeInof!=NULL) *pModeInof = "模块未知";
- SIMCOM_USER_debug("[SIMCOM]:通信错误,串口错误!\r\n");
- }
- }
- else
- {
- if(pModeInof!=NULL) *pModeInof = "模块未知";
- SIMCOM_USER_debug("[SIMCOM]:开机失败!\r\n");
- Error = SIMCOM_POWER_UP_ERROR; //开机失败
- }
-
- }
-
- //上电完毕后初始化模块
- if(pHandle->pGetSTATUS_Pin() == SIMCOM_H_LEVEL)
- {
- //模块初始化网络
- if(NetworkDelay == 0) NetworkDelay = 0xffff; //为0,一直等待
- NotCnt=SeaCnt=TurCnt=UnkCnt=ErrCnt=0; //初始化注册状态计数器为0
-
- //获取模块型号
- if(ModeType == SIMCOM_INVALID)
- {
- SIMCOM_SetParametersReturnBool(pHandle, "ATE 0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭AT回显模式失败!\r\n");
- pHandle->pDelayMS(500);
- ModeType = SIMCOM_GetMode(pHandle); //获取模块型号
- SIMCOM_PrintfModel(pHandle, ModeType, pModeInof); //打印显示通信模块型号
- }
- //型号获取成功了,更新信息
- if(ModeType!=SIMCOM_INVALID)
- {
- pHandle->SimcomModeType = ModeType; //上电初始化设置通信模块型号
- }
-
- //根据模块类型进行初始化,如果是SIM7000C,需要选择工作在GSM模式还是NBIOT模式
- if(SIMCOM_NetworkConfig(pHandle, ModeType, &pHandle->NetworkConfig)==FALSE)
- {
- uart_printf("[DTU]初始化通信模块网络模式失败了!\r\n");
- }
-
- //初始化获取网络信息
- for(cnt = 0;cnt < NetworkDelay;cnt ++)
- {
- if(pHandle->pGetSTATUS_Pin()==SIMCOM_L_LEVEL)
- {
- Error = SIMCOM_POWER_UP_ERROR; //异常断电
- uart_printf("[DTU]异常断电了,请检查供电是否稳定!\r\n");
- break; //模块没有上电,初始化
- }
-
- if(ModeType == SIMCOM_INVALID)
- {
- SIMCOM_SetParametersReturnBool(pHandle, "ATE 0", SIMCOM_DEFAULT_RETRY, 110, "\r\n关闭AT回显模式失败!\r\n");
- pHandle->pDelayMS(500);
- ModeType = SIMCOM_GetMode(pHandle); //获取模块型号
- pHandle->SimcomModeType = ModeType; //上电初始化设置通信模块型号
- SIMCOM_PrintfModel(pHandle, ModeType, pModeInof); //打印显示通信模块型号
- }
-
- if(isCart == FALSE) //卡未检测到,则一直重新检测
- {
- if(SIMCOM_GetCPIN(pHandle)==SIM_READY)
- {
- isCart = TRUE; //卡检测成功
- uart_printf("\r\nSIM卡准备就绪!\r\n");
- }
- else
- {
- uart_printf("\r\nSIM卡未准备就绪!\r\n");
- Error = SIMCOM_SIM_NOT_REALYE; //卡未就绪
- }
- }
-
-
- //2018-01-18 增加SIM7000C NB模式网络注册状态获取支持
- if((ModeType == SIMCOM_SIM7000C) && (pHandle->NetworkConfig.NB_EnableMode==1)) //如果是SIM7000C,并且开启了NB模式
- {
- NetStatus = SIMCOM_GetDataNetworkStatus(pHandle); //获取数据网络网络注册状态
- }
- else
- {
- NetStatus = SIM900_GetGSMNetworkStatus(pHandle); //获取GSM网络注册状态
- }
-
- SIMCOM_USER_debug("[DTU]网络注册状态%d!\r\n",NetStatus);
- //一直出现网络未注册以及注册拒绝,重启,有些卡会先出现拒绝,然后出现注册成功
- switch(NetStatus)
- {
- case SIMCOM_NET_NOT :
- {
- NotCnt++;
- //2017-09-09 增加如果连续15次未检测到卡,并且未注册,则直接退出,返回未插卡
- if(SIMCOM_GetCPIN(pHandle)==SIM_NOT_READY)
- {
- Error = SIMCOM_SIM_NOT_REALYE; //卡未就绪
- SIM_NotReadyCnt ++; //SIM卡未准备就绪计数器增加
- }
- else
- {
- SIM_NotReadyCnt = 0; //SIM卡未就绪计数器复位
- }
- }break; //未注册
- case SIMCOM_NET_ROA : //已经注册,但是漫游
- case SIMCOM_NET_YES : //已经注册
- {
- SIM_NotReadyCnt = 0; //SIM卡未就绪计数器复位
- if(pHandle->s_isInitStatus == FALSE)//模块没有初始化
- {
- if(SIMCOM_ModuleInit(pHandle) == FALSE) //上电后初始化模块基本配置
- {
- SIMCOM_USER_debug("[DTU]初始化失败!\r\n");
- if(isCart==TRUE) Error = SIMCOM_INIT_ERROR; //卡初始化成功了,才返回初始化错误
- goto reset;
- }
- }
-
- //获取模块信息
- if( SIMCOM_GetModuleInfo(pHandle, &pHandle->SIMCOM_Info) == TRUE) //获取模块的相关信息
- {
- SIMCOM_USER_debug("\r\n制造商:%s\r\n",pHandle->SIMCOM_Info.Manu);
- SIMCOM_USER_debug("模块型号:%s\r\n",pHandle->SIMCOM_Info.Model);
- SIMCOM_USER_debug("软件版本:%s\r\n",pHandle->SIMCOM_Info.Ver);
- SIMCOM_USER_debug("模块序列号:%s\r\n",pHandle->SIMCOM_Info.IMEI);
- }
- else
- {
- SIMCOM_USER_debug("\r\n获取模块信息失败!\r\n");
- }
- //获取运营商信息
- if(SIMCOM_COPS(pHandle, pHandle->TelecomCarr) == TRUE) //获取运营商名称
- {
- SIMCOM_USER_debug("运营商信息:%s\r\n", pHandle->TelecomCarr);
- }
- else
- {
- SIMCOM_USER_debug("获取运营商信息失败!\r\n");
- }
-
- //如果是SIM7600 SIM7000C模块,则需要获取网络制式
- switch(ModeType)
- {
- case SIMCOM_SIM7600:
- case SIMCOM_SIM7000C:
- {
- NetworkMode = SIM7XXX_GetNetworkMode(pHandle); //获取SIM7XXX系列模块网络制式
- pHandle->NetworkMode = NetworkMode; //记录全局网络制式,必须在获取短信中心号码之前进行获取,因为电信卡无短信中心号码用于初始化
- if(NetworkMode > 16)
- {
- SIMCOM_USER_debug("网络制式:获取失败\r\n");
- }
- else
- {
- SIMCOM_USER_debug("网络制式:%s\r\n",SIMCOM_NETWORK_NAME[NetworkMode]);
- }
- }break;
- default: //2G
- {
- pHandle->NetworkMode = SIMCOM_NETMODE_GSM; //其它2G模块默认GSM网络
- }break;
- }
-
- Error = SIMCOM_INIT_OK; //初始化成功
- return Error; //已经注册并初始化了
- }
- case SIMCOM_NET_SEA : SeaCnt++;break; //未注册,正在搜索
- case SIMCOM_NET_TUR : TurCnt++;break; //注册被拒绝
- case SIMCOM_NET_UNK : UnkCnt++;break; //未知
- default : ErrCnt++;break; //错误
- }
-
- if((TurCnt > 60) || (UnkCnt > 20) || (ErrCnt > 20)) //注册被拒绝,或者错误
- {
- if(isCart==TRUE) Error = SIMCOM_REG_ERROR; //卡初始化成功了,才返回初注册失败
- SIMCOM_USER_debug("[DTU]模块重启!\r\n");
- if(SIMCOM_HardwarePowerDOWN(pHandle, TRUE) == FALSE)
- {
- SIMCOM_USER_debug("[DTU]:关机失败!\r\n");
- }
- break;
- }
-
- //SIM卡未就绪次数过多
- if(SIM_NotReadyCnt > 16)
- {
-
- uart_printf("[DTU]:多次检测到卡未就绪!模块重启!\r\n");
- if(SIMCOM_HardwarePowerDOWN(pHandle, TRUE) == FALSE)
- {
- SIMCOM_USER_debug("[DTU]:关机失败!\r\n");
- }
- break;
- }
-
- //延时
- pHandle->pDelayMS(800);
- if(pHandle->pIWDG_Feed!=NULL) pHandle->pIWDG_Feed(); //喂狗
-
- }
- //网络注册失败或模块初始化失败
-
- reset:
- if(SIMCOM_HardwarePowerDOWN(pHandle, TRUE) == TRUE) //关闭电源
- {
- uart_printf("[DTU]:网络初始化失败,模块关机成功!\r\n");
- }
- else
- {
- uart_printf("[DTU]:网络初始化失败,模块关机失败!\r\n");
- }
- }
- else
- {
- Error = SIMCOM_POWER_UP_ERROR; //开机失败
- }
- }
-
- //显示错误信息
- switch(Error)
- {
- case SIMCOM_INIT_OK : //初始化成功
- {
- uart_printf("[DTU]:模块上电或初始成功!\r\n");
- }break;
- case SIMCOM_POWER_UP_ERROR : //上电错误
- {
- uart_printf("[DTU]:模块上电错误!\r\n");
- }break;
- case SIMCOM_REG_ERROR : //注册出错(超时)
- {
- uart_printf("[DTU]:模块注册网络出错(超时)!\r\n");
- }break;
- case SIMCOM_INIT_ERROR : //初始化配置错误
- {
- uart_printf("[DTU]:模块初始化配置出错!\r\n");
- }break;
- case SIMCOM_SIM_NOT_REALYE : //SIM卡未就绪导致上电失败
- {
- uart_printf("[DTU]:模块SIM卡未就绪!\r\n");
- }break;
- default:
- {
- uart_printf("[DTU]:未知的错误!\r\n");
- }break;
- }
-
-
- return Error;
- }
-
-
-
-
-
- /*************************************************************************************************************************
- * 函数 : bool SIMCOM_PhoneMessageNumberInitialize(SIMCOM_HANDLE *pHandle, u8 retry)
- * 功能 : SIMCOM 初始化获取短信中心号码以及本机号码,信号强度,CIMI(结果存放在句柄pHandle中)
- * 参数 : pHandle:句柄;Retry:初始化重试次数>0
- * 返回 : TRUE成功,FALSE:失败
- * 依赖 : 底层
- * 作者 : cp1300@139.com
- * 时间 : 2014-08-18
- * 最后修改时间 : 2018-03-24
- * 说明 : 用于网络初始化之后进行初始化获取相关信息,需要提前初始化网络模块型号以及网络制式
- 短信中心号码存放在:pHandle->ServiceCenterPhoneNumber;
- 电话号码存放在:pHandle->LocalPhoneNumber;
- 信号强度存放在:pHandle->Singal;
- SIM卡CIMI号码存放在pHandle->SIM_CIMI;
- 2016-06-15:SIM2000C使用电信SIM卡时,过快读取本机号码会失败,增加延时,确保读取成功
- 2016-11-16:增加获取短信中心号码延时
- 2017-12-05:NBIO 模块不读取电话号码
- *************************************************************************************************************************/
- bool SIMCOM_PhoneMessageNumberInitialize(SIMCOM_HANDLE *pHandle, u8 retry)
- {
- u8 i; //重试计数器
- int Singal;
- bool status;
- bool isReadServerNumber = TRUE; //是否需要获取短信中心号码,电信卡无需获取
-
- //测试AT指令
- SIMCOM_Ready(pHandle);
- if(SIMCOM_TestAT(pHandle, 20) != TRUE)
- {
-
- return FALSE;
- }
-
-
- retry += 1;
- //获取短信中心号码
- if(pHandle->SimcomModeType == SIMCOM_SIM2000) //电信模块无需获取短信中心号码
- {
- isReadServerNumber = FALSE;
- }
- else if(pHandle->SimcomModeType == LYNQ_L700) //L700 NBIOT 无需获取短信中心号码
- {
- isReadServerNumber = FALSE;
- }
- else if(pHandle->SimcomModeType==SIMCOM_SIM7000C) //SIM7000C
- {
- isReadServerNumber = FALSE; //sim7000不支持
- }
- else if(pHandle->SimcomModeType==SIMCOM_SIM7600) //SIM7600
- {
- switch(pHandle->NetworkMode) //查看网络制式,如果是CDMA(电信卡)则不需要获取短信中心号码
- {
- case SIMCOM_NETMODE_CDMA ://CDMA
- case SIMCOM_NETMODE_EVDO ://EVDO
- case SIMCOM_NETMODE_HYBRID ://HYBRID (CDMA and EVDO)
- case SIMCOM_NETMODE_1XLTE ://1XLTE(CDMA and LTE)
- {
- isReadServerNumber = FALSE;
- }break;
- }
- }
-
- if(isReadServerNumber) //需要获取短信中心号码
- {
- for(i = 0;i < retry;i ++)
- {
- if(SIMCOM_GetServeNumber(pHandle, pHandle->ServiceCenterPhoneNumber) == TRUE) //获取短信服务中心号码成功
- {
- if(pHandle->ServiceCenterPhoneNumber[0] == 0)
- {
- SIMCOM_USER_debug("短信中心号码为空\r\n");
- }
- else
- {
- SIMCOM_USER_debug("短信中心号码:%s\r\n",pHandle->ServiceCenterPhoneNumber);
- }
- break;
- }
- else
- {
- SIMCOM_WaitSleep(pHandle, 100);
- SIMCOM_Ready(pHandle);
- pHandle->pDelayMS(1000);
- }
- }
- if(i==retry) return FALSE;
- }
- else
- {
- pHandle->pDelayMS(2000); //等待2s钟
- strcpy(pHandle->ServiceCenterPhoneNumber, "13800818500"); //短信中心号码-固定值,防止为空
- SIMCOM_USER_debug("[缺省]短信中心号码:%s\r\n",pHandle->ServiceCenterPhoneNumber);
- }
-
- //获取信号强度
- for(i = 0;i < retry;i ++)
- {
- Singal = SIMCOM_GetSignal(pHandle); //获取信号强度
- if((Singal > 0) && (Singal!=99))
- {
- pHandle->Singal = (u8)Singal;
- SIMCOM_USER_debug("信号强度 <%02d>!\r\n" ,Singal);
- break;
- }
- else
- {
- pHandle->Singal = 0; //没有读取到,延时2秒
- pHandle->pDelayMS(2000); //等待2s钟
- }
- SIMCOM_WaitSleep(pHandle, 100);
- SIMCOM_Ready(pHandle);
- pHandle->pDelayMS(1000); //等待1s钟
- }
-
- //获取本机号码
- for(i = 0;i < retry;i ++)
- {
- if(pHandle->NetworkMode == LYNQ_L700) //L700 NBIOT 无法获取
- {
- pHandle->pDelayMS(1000); //等待1s钟
- pHandle->LocalPhoneNumber[0] = 0;
-
- return TRUE;
- }
- else if(pHandle->NetworkMode == SIMCOM_SIM7000C) //SIM7000C 无法获取
- {
- pHandle->pDelayMS(1000); //等待1s钟
- pHandle->LocalPhoneNumber[0] = 0;
-
- return TRUE;
- }
- else if(pHandle->SimcomModeType==SIMCOM_SIM7600) //SIM7600,SIM7000C
- {
- switch(pHandle->NetworkMode) //查看网络制式,如果是CDMA(电信卡)则不需要获取短信中心号码
- {
- case SIMCOM_NETMODE_CDMA ://CDMA
- case SIMCOM_NETMODE_EVDO ://EVDO
- case SIMCOM_NETMODE_HYBRID ://HYBRID (CDMA and EVDO)
- case SIMCOM_NETMODE_1XLTE ://1XLTE(CDMA and LTE)
- {
- status = SIMCOM_GetBookNumber(pHandle, 1, pHandle->LocalPhoneNumber); //从电话簿中读取一个电话号码
- }break;
- default: //其他制式可以读取
- {
- status = SIMCOM_GetPhoneNumber(pHandle, pHandle->LocalPhoneNumber); //读取本机号码
- }break;
- }
- }
- else if(pHandle->SimcomModeType == SIMCOM_SIM2000) //SIM2000
- {
- status = SIMCOM_GetBookNumber(pHandle, 1, pHandle->LocalPhoneNumber); //从电话簿中读取一个电话号码
- }
-
- else //其它模块
- {
- status = SIMCOM_GetPhoneNumber(pHandle, pHandle->LocalPhoneNumber); //读取本机号码
- }
-
-
- if(status== TRUE) //获取本机号码成功
- {
- pHandle->LocalPhoneNumber[15] = 0;
- if(pHandle->LocalPhoneNumber[0] == 0)
- {
- SIMCOM_USER_debug("本机号码为空\r\n");
- }
- else
- {
- SIMCOM_USER_debug("本机号码:%s\r\n",pHandle->LocalPhoneNumber);
- }
- break;
- }
- else
- {
- SIMCOM_WaitSleep(pHandle, 100);
- SIMCOM_Ready(pHandle);
- pHandle->pDelayMS(2000); //等待2s钟
- }
- }
- if(i==retry) return FALSE;
-
-
- //获取SIM卡CIMI号码
- for(i = 0;i < retry;i ++)
- {
- //获取SIM卡CIMI号码(SIM卡唯一id,必须存在)
- if(SIMCOM_GetCIMI(pHandle, pHandle->SIM_CIMI) == TRUE) break;
-
- SIMCOM_WaitSleep(pHandle, 100);
- SIMCOM_Ready(pHandle);
- pHandle->pDelayMS(1000); //等待1s钟
- }
- if(i==retry) return FALSE;
-
-
- return TRUE;
- }
//SIMCOM_USER.h
- /*************************************************************************************************************
- * 文件名: SIMCOM_USER.h
- * 功能: SIMCOM用户层函数
- * 作者: cp1300@139.com
- * 创建时间: 2015-02-15
- * 最后修改时间: 2018-03-23
- * 详细:
- *************************************************************************************************************/
- #ifndef _SIMCOM_SUER_H_
- #define _SIMCOM_SUER_H_
- #include "system.h"
- #include "simcom.h"
-
- //SIMCOM 初始化错误
- typedef enum
- {
- SIMCOM_INIT_OK = 0, //初始化成功
-
- SIMCOM_POWER_UP_ERROR = 1, //上电错误
- SIMCOM_REG_ERROR = 2, //注册出错(超时)
- SIMCOM_INIT_ERROR = 3, //初始化配置错误
- SIMCOM_SIM_NOT_REALYE = 4, //SIM卡未就绪导致上电失败
- SIMCOM_NULL_ERROR = 255 //状态无效
- }SIMCOM_USER_ERROR;
-
-
- //API
- //初始化SIMCOM句柄接口
- bool SIMCOM_Init(SIMCOM_HANDLE *pHandle,
- bool (* pSendData)(u8 *pDataBuff, u16 DataLen), //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
- int (* pReadData)(u8 **pDataBuff, u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelay), //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
- void (*pClearRxData)(void), //清除接收缓冲区函数,用于清除接收数据缓冲区数据
- void (*pSetDTR_Pin)(u8 Level), //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
- void (*pSetPWRKEY_Pin)(u8 Level), //PWRKEY开机引脚电平控制-用于开机
- u8 (*pGetSTATUS_Pin)(void), //获取STATUS引脚电平-用于指示模块上电状态
- u8 (*pGetDCD_Pin)(void), //获取DCD引脚电平-高电平AT指令模式,低电平为透传模式
- void (*pDelayMS)(u32 ms), //系统延时函数
- void (*pIWDG_Feed)(void) //清除系统看门狗(可以为空)
- );
-
- SIMCOM_USER_ERROR SIMCOM_RegisNetwork(SIMCOM_HANDLE *pHandle, u16 Retry, u16 NetworkDelay,const char **pModeInof);//SIMCOM模块上电初始化并注册网络
- bool SIMCOM_PhoneMessageNumberInitialize(SIMCOM_HANDLE *pHandle, u8 retry); //SIMCOM 初始化获取短信中心号码以及本机号码,信号强度,CIMI(结果存放在句柄pHandle中)
-
-
-
- #endif /*_SIMCOM_SUER_H_*/
//底层相关接口,自己根据自己的平台进行开发的接口
- //发送数据接口
- static bool GPRS_UART_SendData(u8 DataBuff[], u16 DataLen)
- {
- UARTx_SendData(SIMCOM_UART_CH, DataBuff, DataLen);
-
- return TRUE;
- }
-
-
-
- //接收数据接口
- static int GPRS_UART_ReadData(u8 **pDataBuff,u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelayMs)
- {
- u32 cnt = 0;
- u16 TempTime;
-
- if(ByteTimeOutMs < 1) ByteTimeOutMs = 1; //字节超时时间,2个帧之间的间隔最小时间
- TimeOutMs /= ByteTimeOutMs;
- TimeOutMs += 1;
- TempTime = TimeOutMs;
- while(TimeOutMs --)
- {
- cnt = UARTx_GetRxCnt(SIMCOM_UART_CH);
- OSTimeDlyHMSM(0,0,0,ByteTimeOutMs);;
- if((cnt > 0) && (cnt == UARTx_GetRxCnt(SIMCOM_UART_CH)))
- {
- if(pReceiveDelayMs!=NULL) //需要返回延时
- {
- *pReceiveDelayMs = (TempTime-TimeOutMs)*ByteTimeOutMs;
- }
- *pDataBuff = g_SIMCOM_Buff; //接收缓冲区
-
- return cnt;
- }
- #if SYS_WDG_EN_
- IWDG_Feed(); //喂狗
- #endif
- }
-
- return 0;
- }
-
-
- //清除接收缓冲区
- static void GPRS_UART_ClearData(void)
- {
- UARTx_ClearRxCnt(SIMCOM_UART_CH); //清除串口缓冲区
- }
- /
- //SIM900/SIM800通信支持
- //GSM模块相关定义
- #define SIMCOM_UART_CH UART_CH3 //串口3
- #define SIMCOM_UART_BAUD 115200 //波特率
- #define SIMCOM_UART_BUFF_SIZE (1024*4) //接收缓冲区大小
-
- //相关控制引脚
- __inline void SIMCOM_SetDTR(u8 Level) {(PGout(4)=Level);} //DTR
- __inline void SIMCOM_SetPWRKEY(u8 Level) {(PGout(3)=Level);} //PWRKEY
- __inline u8 SIMCOM_GetSTATUS(void) {return PGin(5)?1:0;} //STATUS
- __inline u8 SIMCOM_GetDCD(void) {return PDin(11)?1:0;} //DCD-上拉输入,高电平AT指令模式,低电平为透传模式
-
- //引脚初始化
- __inline void SIMCOM_IO_Init(void)
- {
- SYS_DeviceClockEnable(DEV_GPIOD, TRUE); //使能GPIOD时钟
- SYS_DeviceClockEnable(DEV_GPIOG, TRUE); //使能GPIOG时钟
- SYS_GPIOx_Init(GPIOG, BIT3|BIT4, OUT_PP, SPEED_2M); //推挽输出
- SYS_GPIOx_OneInit(GPIOD, 11, IN_IPU, IN_NONE); //DCD 上拉输入
- SYS_GPIOx_OneInit(GPIOG, 5, IN_IPD, IN_NONE); //STATUS 下拉输入
- }
另外还有一个看门狗清除的回调函数
- //喂独立看门狗
- __inline void IWDG_Feed(void) {IWDG->KR=0XAAAA;}
//实现了以上的接口就可以调用了
//下面是应用层调用,使用了ucos的一个任务
- SIMCOM_HANDLE g_SIMCOM_Handle; //SIMCOM通信模块句柄
- u8 g_SIMCOM_Buff[SIMCOM_UART_BUFF_SIZE+1]; //串口接收缓冲区
-
-
-
- static bool GPRS_UART_SendData(u8 DataBuff[], u16 DataLen); //发送数据接口
- static int GPRS_UART_ReadData(u8 **pDataBuff,u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelayMs); //接收数据接口
- static void GPRS_UART_ClearData(void); //清除接收缓冲区
-
-
- //GPRS通信任务
- void GPRS_Task(void *pdata)
- {
- const char *pModeInof;
-
- UARTx_Init(SIMCOM_UART_CH, SIMCOM_UART_BAUD, ENABLE); //初始化串口
- UARTx_SetRxBuff(SIMCOM_UART_CH, g_SIMCOM_Buff, SIMCOM_UART_BUFF_SIZE); //设置串口接收缓冲区
- SIMCOM_IO_Init(); //SIMCOM相关IO初始化
- OSTimeDlyHMSM(0,0,0,20);
-
- //初始化SIMCOM句柄接口
- SIMCOM_Init(&g_SIMCOM_Handle,
- GPRS_UART_SendData, //发送数据接口,如果发送失败,返回FALSE,成功返回TRUE;
- GPRS_UART_ReadData, //接收数据接口,返回数据长度,如果失败返回<=0,成功,返回数据长度
- GPRS_UART_ClearData, //清除接收缓冲区函数,用于清除接收数据缓冲区数据
- SIMCOM_SetDTR, //DTR引脚电平控制-用于控制sleep模式或者退出透传模式
- SIMCOM_SetPWRKEY, //PWRKEY开机引脚电平控制-用于开机
- SIMCOM_GetSTATUS, //获取STATUS引脚电平-用于指示模块上电状态
- SIMCOM_GetDCD, //DCD-上拉输入,高电平AT指令模式,低电平为透传模式
- SYS_DelayMS, //系统延时函数
- IWDG_Feed //清除系统看门狗(可以为空)
- );
-
- while(1)
- {
- SIMCOM_RegisNetwork(&g_SIMCOM_Handle, 6, 60, &pModeInof);//SIMCOM模块上电初始化并注册网络
- //SIMCOM 初始化获取短信中心号码以及本机号码,信号强度,CIMI(结果存放在句柄pHandle中)
- if(SIMCOM_PhoneMessageNumberInitialize(&g_SIMCOM_Handle, 3) == FALSE)
- {
- uart_printf("\r\n警告:初始化获取相关信息失败!\r\n");
- }
-
-
- OSTimeDlyHMSM(0,5,0,20);
- }
- }
//以上代码实现了通信模块的初始化,开机,联网,读取本机号码,中心站号码,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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。