SIM800/SIM900/SIM7000/SIM7600底層操作接口_句柄方式完全分離通信底層


使用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)-&gt;
SIMCOM_SIM7600CE
 
OK
 
OK 返回成功!
[DTU]通信模塊為SIM7600
 
SIMCOM(22B)-&gt;
+CPIN: READY
 
OK
 
OK 返回成功!
 
SIM卡准備就緒!
 
SIMCOM(20B)-&gt;
+CREG: 0,1
 
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
[DTU]網絡注冊狀態1!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(22B)-&gt;
+CPIN: READY
 
OK
 
OK 返回成功!
 
SIM卡准備就緒!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(35B)-&gt;
OK
 
SIMCOM INCORPORATED
 
OK
 
OK 返回成功!
 
SIMCOM(26B)-&gt;
SIMCOM_SIM7600CE
 
OK
 
OK 返回成功!
 
SIMCOM(34B)-&gt;
+GMR: LE11B02SIM7600CE-A
 
OK
 
OK 返回成功!
 
SIMCOM(25B)-&gt;
861477030032237
 
OK
 
OK 返回成功!
 
制造商:OK
模塊型號:SIMCOM_SIM7600CE
軟件版本:LE11B02SIM7600CE-A
模塊序列號:861477030032237
 
SIMCOM(42B)-&gt;
+COPS: 0,0,"CHINA MOBILE CMCC",7
 
OK
 
OK 返回成功!
運營商信息:CHINA MOBILE CMCC
 
SIMCOM(22B)-&gt;
+CNSMOD: 0,8
 
OK
 
OK 返回成功!
網絡制式:LTE
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(6B)-&gt;
OK
 
OK 返回成功!
 
SIMCOM(37B)-&gt;
+CSCA: "+8613800100569",145
 
OK
 
OK 返回成功!
短信中心號碼:13800100569
短信中心號碼:13800100569
 
SIMCOM(21B)-&gt;
+CSQ: 20,99
 
OK
 
OK 返回成功!
信號強度 &lt;20&gt;!
 
SIMCOM(41B)-&gt;
+CNUM: "","1064838905852",129
 
 
OK
 
OK 返回成功!
本機號碼:1064838905852
本機號碼:1064838905852
 
SIMCOM(25B)-&gt;
460040389005852
 
OK
 
OK 返回成功!
獲取CIMI成功:460040389005852

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM