SIM800/SIM900/SIM7000/SIM7600底层操作接口_句柄方式完全分离通信底层
Posted jiangzhaowei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 底层定义 * 作者: [email protected] * 创建时间: 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指令接口 * 作者: [email protected] * 创建时间: 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指令(会添加结束符 ),不会等待响应 * 参数 : pHandle:SIMCOM句柄;pStr:指令字符串 * 返回 : 接口发送状态 * 依赖 : 无 * 作者 : [email protected] * 时间 : 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 *)" ", 2); //发送结束符 } /************************************************************************************************************************* * 函数 : bool SIMCOM_TestAT(SIMCOM_HANDLE *pHandle, u32 retry) * 功能 : SIMCOM AT 命令通信测试 * 参数 : pHandle:SIMCOM句柄;retry:重试次数 * 返回 : FALSE:通信失败;TRUE:通信成功 * 依赖 : 底层 * 作者 : [email protected] * 时间 : 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:超时 * 依赖 : 无 * 作者 : [email protected] * 时间 : 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("模块进入空闲模式失败! "); pHandle->pClearRxData(); //清除接收计数器 return FALSE; } pHandle->pDelayMS(100); //延时100ms SIMCOM_debug("模块进入空闲模式成功! "); 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 * 依赖 : 无 * 作者 : [email protected] * 时间 : 2018-03-24 * 最后修改时间 : 2018-03-24 * 说明 : 本函数会在接收缓冲区字符串结束添加‘ ‘ 本函数不能清除缓冲区 *************************************************************************************************************************/ 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] = ‘