當(dāng)前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀]使用SIMCOM公司通信模塊已經(jīng)好幾年了,周末抽空把底層重新寫了,將底層的通信與應(yīng)用完全進(jìn)行了分離,便于移植。SIMCOM.h //定義了相關(guān)的結(jié)構(gòu)體與類型。SIMCOM_AT.c//定義了底層的AT

使用SIMCOM公司通信模塊已經(jīng)好幾年了,周末抽空把底層重新寫了,將底層的通信與應(yīng)用完全進(jìn)行了分離,便于移植。

SIMCOM.h //定義了相關(guān)的結(jié)構(gòu)體與類型。

SIMCOM_AT.c//定義了底層的AT接口

SIMCOM_GSM.c//需要的模塊GSM相關(guān)命令

SIMCOM_GPRS.c//上網(wǎng)相關(guān)-未移植

SIMCOM_SMS.c//短信收發(fā)相關(guān)-未移植

SIMCOM_USER.c//用戶最終接口

//需要自己實現(xiàn)數(shù)據(jù)收發(fā)相關(guān)接口,DCD,DTR,PWRKEY,STATUS相關(guān)IO接口,需要一個ms延時支持


//SIMCOM.h

/*************************************************************************************************************
 * 文件名:			SIMCOM.h
 * 功能:			SIMCOM 底層定義
 * 作者:			cp1300@139.com
 * 創(chuàng)建時間:		2015-02-15
 * 最后修改時間:	2018-03-23
 * 詳細(xì):			注意:底層通信接口使用的是回調(diào)函數(shù),但是必須提供系統(tǒng)延時函數(shù) void SYS_DelayMS(u32 ms);
*************************************************************************************************************/
#ifndef _SIMCOM_H_
#define _SIMCOM_H_
#include "system.h"


//SIMCOM通信模塊定義	
typedef enum
{
	SIMCOM_SIM900	=	0	,		//默認(rèn)為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	,	//無效則默認(rèn)
}SIMCOM_MODE_TYPE;	

//網(wǎng)絡(luò)注冊狀態(tài)
typedef enum
{
	SIMCOM_NET_NOT = 0,		//未注冊
	SIMCOM_NET_YES = 1,		//已經(jīng)注冊
	SIMCOM_NET_SEA = 2,		//未注冊,正在搜索
	SIMCOM_NET_TUR = 3,		//注冊被拒絕
	SIMCOM_NET_UNK = 4,		//未知
	SIMCOM_NET_ROA = 5,		//已經(jīng)注冊,但是漫游
	SIMCOM_NET_ERROR=0XFF	//錯誤
}SIMCOM_NETSTATUS;



//SIMCOM網(wǎng)絡(luò)制式
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卡就緒狀態(tài)
typedef enum
{
	SIM_READY			=	0,	//SIM卡就緒
	SIM_NOT_READY		=	1,	//SIM卡未就緒
	SIM_UNKNOWN			=	2	//SIM卡狀態(tài)未知
}SIM_CARD_STATUS;

//控制IO電平定義
#define SIMCOM_H_LEVEL		1	//高電平
#define SIMCOM_L_LEVEL		0	//低電平

//DCD狀態(tài)定義
#define DCD_DATA_MODE		0	//數(shù)據(jù)透傳模式
#define DCD_AT_MODE			1	//AT指令模式

//相關(guān)信息長度限制
#define SIMCOM_INFO_SIZE	24	//信息長度
#define SIMCOM_VER_SIZE		24	//軟件版本長度定義

//重試次數(shù),防止AT指令操作失敗
#define SIMCOM_DEFAULT_RETRY	2 


//SIMCOM模塊相關(guān)信息
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;

//網(wǎng)絡(luò)模式設(shè)置
typedef struct
{
	SIMCOM_MODE_TYPE	ModeType;					//模塊型號
	NBIOT_MODE_TYPE 	NB_Mode;					//NB模式
	s8 NB_EnableMode;								//NB模式使能模式,-1:無需設(shè)置;0:關(guān)閉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通信模塊相關(guān)信息結(jié)構(gòu)體
	NETWORK_CONFIG_TYPE NetworkConfig;				//網(wǎng)絡(luò)模式設(shè)置
	SIMCOM_NETMODE_TYPE NetworkMode;				//當(dāng)前網(wǎng)絡(luò)制式
	u8 Singal;										//網(wǎng)絡(luò)信號強(qiáng)度
	char LocalPhoneNumber[16];						//本機(jī)電話號碼
	char ServiceCenterPhoneNumber[16];				//短信中心電話號碼
	char SIM_CIMI[16];								//SIM卡唯一CIMI號碼
		
	//底層通信接口
	bool (* pSendData)(u8 *pDataBuff, u16 DataLen);											//發(fā)送數(shù)據(jù)接口,如果發(fā)送失敗,返回FALSE,成功返回TRUE;
	int (* pReadData)(u8 **pDataBuff, u8 ByteTimeOutMs, u16 TimeOutMs, u16 *pReceiveDelay);	//接收數(shù)據(jù)接口,返回數(shù)據(jù)長度,如果失敗返回<=0,成功,返回數(shù)據(jù)長度
	void (*pClearRxData)(void);																//清除接收緩沖區(qū)函數(shù),用于清除接收數(shù)據(jù)緩沖區(qū)數(shù)據(jù)
	void (*pSetDTR_Pin)(u8 Level);															//DTR引腳電平控制-用于控制sleep模式或者退出透傳模式
	void (*pSetPWRKEY_Pin)(u8 Level);														//PWRKEY開機(jī)引腳電平控制-用于開機(jī)
	u8 (*pGetSTATUS_Pin)(void);																//獲取STATUS引腳電平-用于指示模塊上電狀態(tài)
	u8 (*pGetDCD_Pin)(void);																//獲取DCD引腳電平-高電平AT指令模式,低電平為透傳模式
	//系統(tǒng)接口
	void (*pDelayMS)(u32 ms);																//系統(tǒng)延時函數(shù)
	void (*pIWDG_Feed)(void);																//清除系統(tǒng)看門狗(可以為空)
	//內(nèi)部狀態(tài)定義
	bool s_isInitStatus;																	//用于記錄模塊初始化狀態(tài),復(fù)位或上電后變?yōu)闊o效
}SIMCOM_HANDLE;



#endif /*_SIMCOM_H_*/

//SIMCOM_AT.c

/*************************************************************************************************************
 * 文件名:			SIMCOM_AT.c
 * 功能:			SIMCOM底層AT指令接口
 * 作者:			cp1300@139.com
 * 創(chuàng)建時間:		2015-02-15
 * 最后修改時間:	2018-03-23
 * 詳細(xì):			
*************************************************************************************************************/
#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指令調(diào)試狀態(tài)

//調(diào)試開關(guān)
#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


/*************************************************************************************************************************
* 函數(shù)				:	bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr)
* 功能				:	發(fā)送一個AT指令(會添加結(jié)束符rn),不會等待響應(yīng)
* 參數(shù)				:	pHandle:SIMCOM句柄;pStr:指令字符串
* 返回				:	接口發(fā)送狀態(tài)
* 依賴				:	無
* 作者				:	cp1300@139.com
* 時間				:	2018-03-23
* 最后修改時間 		: 	2018-03-23
* 說明				: 	用于底層AT指令發(fā)送
*************************************************************************************************************************/
bool SIMCOM_SendAT(SIMCOM_HANDLE *pHandle, char *pStr)
{
	pHandle->pSendData((u8 *)pStr, strlen(pStr));	//發(fā)送指令
	return pHandle->pSendData((u8 *)"rn", 2);		//發(fā)送結(jié)束符
}





/*************************************************************************************************************************
* 函數(shù)			:	bool SIMCOM_TestAT(SIMCOM_HANDLE *pHandle, u32 retry)
* 功能			:	SIMCOM AT 命令通信測試
* 參數(shù)			:	pHandle:SIMCOM句柄;retry:重試次數(shù)
* 返回			:	FALSE:通信失敗;TRUE:通信成功
* 依賴			:	底層
* 作者			:	cp1300@139.com
* 時間			:	2013-10-20
* 最后修改時間 : 	2018-03-23
* 說明			: 	每隔100ms向SIMCOM通信模塊發(fā)送一個"AT",等待響應(yīng)返回
*************************************************************************************************************************/
bool SIMCOM_TestAT(SIMCOM_HANDLE *pHandle, u32 retry)
{
	u32 cnt;
	u8 *pRxBuff;
	
	//檢測模塊存在
	do
	{
		SIMCOM_SendAT(pHandle, "AT");															//發(fā)送"AT",同步波特率,并且等待應(yīng)答
		pHandle->pClearRxData();																//清除計數(shù)器
		if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pRxBuff, &cnt, "OK", 10, 150))			//等待響應(yīng),超時150ms
		{
			pHandle->pDelayMS(100);
			return TRUE;
		}
		retry --;
	}while(retry);
	
	pHandle->pDelayMS(100);
	return FALSE;
}


/*************************************************************************************************************************
* 函數(shù)				:	bool SIMCOM_WaitSleep(SIMCOM_HANDLE *pHandle, u32 TimeOutMs)
* 功能				:	等待模塊空閑,并重新喚醒
* 參數(shù)				:	pHandle:句柄;TimeOut:等待超時,時間單位ms
* 返回				:	TRUE:成功;FALSE:超時
* 依賴				:	無
* 作者				:	cp1300@139.com
* 時間				:	2013-10-25
* 最后修改時間 		: 	2018-03-24
* 說明				: 	用于等待操作完成,防止快速操作造成模塊不響應(yīng)
*************************************************************************************************************************/
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);		//等待模塊空閑后進(jìn)入SLEEP模式
	
	//循環(huán)發(fā)送命令,直到命令超時了則認(rèn)為進(jìn)入了sleep模式
	for(i = 0;i < (TimeOutMs/100);i ++)
	{
		pHandle->pDelayMS(100);			//延時100ms
		SIMCOM_SendAT(pHandle, "AT");			//發(fā)送"AT",同步波特率,并且等待應(yīng)答
		pHandle->pClearRxData();				//清除接收計數(shù)器
		if(AT_RETURN_TIME_OUT == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 10, 100))	//等待響應(yīng),超時100ms
		{
			break;
		}
	}
	pHandle->pSetDTR_Pin(SIMCOM_L_LEVEL);		//喚醒
	
	if(i == (TimeOutMs/100)) 
	{
		SIMCOM_debug("模塊進(jìn)入空閑模式失敗!rn");
		pHandle->pClearRxData();				//清除接收計數(shù)器
		
		return FALSE;
	}
	pHandle->pDelayMS(100);				//延時100ms
	
	SIMCOM_debug("模塊進(jìn)入空閑模式成功!rn");
	SIMCOM_TestAT(pHandle, 10);
	pHandle->pClearRxData();				//清除接收計數(shù)器
	
	return TRUE;
}







/*************************************************************************************************************************
* 函數(shù)				:	SIMCOM_AT_ERROR SIMCOM_GetATResp(SIMCOM_HANDLE *pHandle, u8 **pRxBuff, u32 *pLen, const char *pKeyword, u8 ByteTimeOutMs, u16 TimeOutMs)
* 功能				:	獲取SIMCOM的AT指令響應(yīng)
* 參數(shù)				:	pHandle:句柄
						pRxBuff:接收緩沖區(qū)指針(輸出);pLen:接收到的數(shù)據(jù)大小(輸出),
						pKeyword:關(guān)鍵字,為字符串,比如"OK",如果在接收到的字符串中有OK字符,就返回成功,否則失敗(輸入)
						ByteTimeOutMs:字節(jié)超時時間,單位ms最大255ms
						TimeOutMs:等待超時時間,單位毫秒
* 返回				:	SIM900_ERROR
* 依賴				:	無
* 作者				:	cp1300@139.com
* 時間				:	2018-03-24
* 最后修改時間 		: 	2018-03-24
* 說明				: 	本函數(shù)會在接收緩沖區(qū)字符串結(jié)束添加'