使用SIMCOM模块的一些总结

    最近在使用SIMCOM的通信模块,GSM模块SIM800以及NB-IOT模块SIM7020c,遇到一些小的问题,在这里做一个记录。

底层参考了https://blog.csdn.net/cp1300/article/details/79686460

两个模块封装可以兼容,模块上电初始化并注册网络大部分底层程序一致,从模块上电到PS业务附着成功SIM800较SIM7020c时间要长,SIM800有透传模式,SIM7020c没有透传模式,虽然手册上说明两种模块都可以进行TCP/IP连接,但是在使用时发现SIM7020c不能建立TCP连接,原因未知。

部分不能兼容的AT指令:

SIM800:  AT+CREG?   //获取网络注册状态

                 AT+CIPMODE=1    //开启透传模式

SIM7020c:AT+CGREG?  //获取网络注册状态

在SIM800进入透传模式后大部分AT指令会被认为是数据被传输,但是仍可以进行如下设置进行UDP服务器连接:

AT+CSTT=\"CMNET\"    //设置为APN为CMNET

AT+CIICR                      //建立无线链路

AT+CIFSR                    //获得本地IP地址   (实际使用时,在建立UDP连接时,如果省略这步操作会失败)

/*************************************************************************************************************************
* 函数				:	uint8_t SIMCOM_UDP_ServerCnt(SIMCOM_HANDLE *pHandle)
* 功能				:	连接UDP服务器函数
* 参数				:	
* 返回				:	连接建立状态
* 依赖				:	无
* 作者				:	
* 时间				:	2018-12-23
* 最后修改时间 		: 	2018-12-23
* 说明				: 	
*************************************************************************************************************************/
int RSSI_sim=0;
uint8_t SIMCOM_UDP_ServerCnt(SIMCOM_HANDLE *pHandle)
{
//	int Singal=0;
	uint8_t retry;
//配置服务器IP地址 格式:	"AT+CIPSTART=\"UDP\",\"47.104.137.129\",\"20030\""
	const char *Server = "AT+CIPSTART=\"UDP\",\"47.104.137.129\",\"20030\"";	//IP登录服务器
	retry = SIMCOM_DEFAULT_RETRY;
	while(retry)
	{
		if(SIM800_GetGPRSAdhereStatus(pHandle)!=1) 
			{
			}
		else break;
		pHandle->pDelayMS(1000);				//延时1秒
		retry --;		
	}
	if(retry==0)
	{
		printf("\r\nGPRS附着失败\r\n");
		return 0;		
	}
	RSSI_sim = SIMCOM_GetSignal(pHandle);				//获取信号强度
	pHandle->Singal = (uint8_t)RSSI_sim;
	#if SIMCOM_USER_DBUG
	printf("信号强度 <%02d>!\r\n" ,RSSI_sim);
	#endif
	if(SIMCOM_SetParametersReturnbool(pHandle, "AT+CSTT=\"CMNET\"", 1, 510, "\r\n设置为CMNET失败\r\n") == 0)return 0;
	if(SIMCOM_SetParametersReturnbool(pHandle, "AT+CIICR", 1, 510, "\r\n 建立无线链路失败\r\n") == 0)return 0;
	LED2_OFF();
	SIMCOM_SetParametersReturnbool(pHandle, "AT+CIFSR", 0, 510, "\r\n");
	if(SIMCOM_SetParametersReturnbool(pHandle,(char*)Server, 1, 310, "\r\n建立UDP连接失败\r\n") == 0)return 0;
//	LED2_ON();
  return 1;
}

在透传模式下可以直接通过串口发送数据:

/*************************************************************************************************************************
* 函数				:	uint8_t SIMCOM_GSM_Transparent_Send(SIMCOM_HANDLE *pHandle,uint8_t *databuf,uint16_t datalen)
* 功能				:	发送数据
* 参数				:	pHandle:SIMCOM句柄;datalen最长512
* 返回				:	连接建立状态
* 依赖				:	无
* 作者				:	
* 时间				:	2018-12-23
* 最后修改时间 : 2018-12-23
* 说明				: 	
*************************************************************************************************************************/
uint8_t SIMCOM_GSM_Transparent_Send(SIMCOM_HANDLE *pHandle,uint8_t *databuf,uint16_t datalen)
{
	pHandle->pSendData((uint8_t *)databuf, datalen);
	pHandle->pClearRxData();					//清除接收计数器	
	HAL_UART_Receive_IT(&SIMCOM_UART_CH,(uint8_t *)g_SIMCOM,1);
}

对于SIM7020c,由于不支持透传模式,需要先建立UDP socket再发送和接收UDP数据

/*************************************************************************************************************************
* 函数				:	uint8_t SIMCOM_EstablishSocket(SIMCOM_HANDLE *pHandle)
* 功能				:	建立Socket
* 参数				:	pHandle:SIMCOM句柄;
* 返回				:	连接建立状态
* 依赖				:	无
* 作者				:	
* 时间				:	2018-12-23
* 最后修改时间 		: 	2018-12-23
* 说明				: 	
*************************************************************************************************************************/
uint8_t SIMCOM_NB_EstablishSocket(SIMCOM_HANDLE *pHandle)
{
//配置服务器IP地址 格式:"AT+CSOCON=0,20030,\"47.104.137.122\""
	const char *Server = "AT+CSOCON=0,20030,\"47.92.243.222\"";	//IP登录服务器
	
	uint8_t retry;
	retry = SIMCOM_DEFAULT_RETRY;		//重试次数
	RSSI_sim = SIMCOM_GetSignal(pHandle);				//获取信号强度
	pHandle->Singal = (uint8_t)RSSI_sim;
	#if SIMCOM_USER_DBUG
	printf("信号强度 <%02d>!\r\n" ,RSSI_sim);
	#endif
	SIMCOM_SetParametersReturnbool(pHandle, "AT+CSOCL=0", SIMCOM_DEFAULT_RETRY, 110, "\r\n删除socket失败!\r\n");
	while(retry)
	{
		//设置重试次数为2次,并且发送延时为120ms
		if(SIMCOM_SetParametersReturnbool(pHandle, "AT+CSOC=1,2,1", 0, 110, "\r\n创建socket失败!\r\n") == 0)  //重试次数为1
		{
		}
		else
		{			
			break;
		}
		pHandle->pDelayMS(1000);				//延时1秒
		retry --;
	}
	if(retry==0)
		return 0;
	retry = SIMCOM_DEFAULT_RETRY;
	while(retry)
	{		
		//设置重试次数为2次,并且发送延时为120ms
    if(SIMCOM_SetParametersReturnbool(pHandle, (char*)Server, 0, 110, "\r\n创建连接失败!\r\n") == 0)
		{
		}
    else			
		break;
		pHandle->pDelayMS(1000);				//延时1秒
		retry --;
	}	
	if(retry==0)
	return 0;
	else
	return 1;
}

通过已建立的socket发送数据需要将数据嵌入到AT指令进行发送,

/*************************************************************************************************************************
* 函数				:	uint8_t SIMCOM_Send(SIMCOM_HANDLE *pHandle,uint8_t *databuf,uint16_t datalen)
* 功能				:	发送数据
* 参数				:	pHandle:SIMCOM句柄;databuf待发送数据;datalen最长255
* 返回				:	连接建立状态
* 依赖				:	无
* 作者				:	
* 时间				:	2018-12-23
* 最后修改时间 		: 	2018-12-23
* 说明				: 	
*************************************************************************************************************************/
char Sdatabuff[512];
char Atbuff[560];

uint8_t SIMCOM_NB_Send(SIMCOM_HANDLE *pHandle,uint8_t *databuf,uint8_t datalen)
{
		uint32_t cnt;
		uint8_t retry;
		uint8_t *pData;
	  uint16_t i;
	  retry = 2;		//重试次数
		for(i=0;ipClearRxData();				//清除接收计数器
//	do
//	{			
		SIMCOM_SendAT(pHandle,Atbuff);			//发送AT命令
		pHandle->pClearRxData();				//清除接收计数器
		if(AT_RETURN_OK == SIMCOM_GetATResp(pHandle, &pData, &cnt, "OK", 5, 100))	//等待响应,超时10s
		{
			pHandle->pClearRxData();			//清除接收计数器

			HAL_UART_Receive_IT(&SIMCOM_UART_CH,(uint8_t *)g_SIMCOM,1);
			return 1;
		}		
//		SIMCOM_Ready(pHandle);					//等待就绪
//		pHandle->pDelayMS(1000);				//延时1秒
//		retry --;
//	}while(retry);
//	pHandle->pClearRxData();					//清除接收计数器	
	return 0;
}

 

需要注意的是发送数据后模块会立刻返回AT指令响应,如果在应用中采用中断的形式接收串口数据,那么会马上产生接收中断,这时如果服务器有应答数据或下发数据会再产生接收中断,在处理接收数据时需要注意。通过校验“+CSONMI”确认是下发的数据。下发数据是字符串形式,需进行转换。

unsigned char Rx_SIMCOM[256];
unsigned char Rx_SIMCOM_len;
uint8_t Rx_Simdata_check(void)
{
	uint16_t s_len;
	uint16_t hex_temp;
	uint8_t i,j;
	char *p;
	p = strstr(g_SIMCOM_Buff, "+CSONMI:");
	if(p != NULL)
  {
//		printf("%s",g_SIMCOM_Buff);
		for(i=0;i<4;i++)
		{
			if(p[11+i]==',')
			{
				p[11+i] = '\0';
				break;
			}				
		}
		Rx_SIMCOM_len=atoi(&p[11])/2;
		for(j=0;j

 

你可能感兴趣的:(学习心得)