M26模块TCP透传数据流程笔记

M26 TCP透传

  • TCP连接流程
    • 初始化
    • 连接到服务器,我现在是域名连接
    • 发送数据

TCP连接流程

第一次使用 M26 ,很生疏,从手册入手开始一步一步的走,做透传,幸好是中文手册,看着不费劲,这里用的是AT指令开发,坐下流程笔记,以后用的着的时候看,这里做一些功能上的封装,框架可以直接用,具体怎么实现根据实际情况,用的是STM32F1系列的单片机通过串口向M26发送数据透传到服务器。

初始化

在TCP连接之前需要一些初始化,例如:AT测试指令,设置反显和初始化PDP上下文。

封装的发送指令函数M26_SendCmd其实就是向串口发送数据和延时一段时间等待串口接受M26返回后比较相应返回成功报文。第一个参数是AT指令,第二个参数是期待返回值,第三个参数是等待模块返回超时时间

  1. 初始化基本配置
unsigned char m25_conf_base()
{
		while(M26_SendCmd("AT\r\n","OK",500))//测试指令
	{
		Clear_Buffer2(); 
	}
	delay_ms(500);
	Clear_Buffer2(); 
	
	while(M26_SendCmd("ATE0\r\n","OK",500))//设置回显   ATE1设置回显  ATE0设置不回显  2019-3-22
	{
		Clear_Buffer2(); 
	}
	delay_ms(500);
	Clear_Buffer2(); 
	
	while(M26_SendCmd("AT+CSQ\r\n","OK",500))//获取信号强度
	{
		Clear_Buffer2(); 
	}
	
	while(M26_SendCmd("AT+QREFUSECS=1,1\r\n","OK",500))//拒接来电和短信
	{
		Clear_Buffer2(); 
	}
	delay_ms(500);
	Clear_Buffer2();
	
	return 1;
}

2.初始化APN配置

unsigned char m26_conf_APN()
{
	
	while(M26_SendCmd("AT+QIFGCNT=0\r\n","OK",500)) //设置为前台
	{
		Clear_Buffer2(); 
	}
	delay_ms(500);
	Clear_Buffer2();
	
	while(M26_SendCmd("AT+QICSGP=1,\042CMNET\042\r\n","OK",500)) //设置接入点
	{
		Clear_Buffer2(); 
	}
	delay_ms(500);
	Clear_Buffer2();
	return 1;
}
  1. 初始化SIM状态查询:如果SIM状态不成功需要模块重启重新初始化
unsigned char m26_conf_SIM()
{
	int i;
	unsigned char res = 0;
	for(i = 0; i < 20; i++)
	{

		//10S内未找到SIM需要重启模块
		if(M26_SendCmd("AT+CPIN?\r\n","+CPIN: READY",500))//SIM卡解密
		{
			res = 0;
			Clear_Buffer2(); 
		}
		else
		{
				res = 1;
				break;
		}	
	}
	delay_ms(500);
	Clear_Buffer2();
	
	M26_SendCmd("AT+QINISTAT\r\n","OK",500);
	delay_ms(500);
	Clear_Buffer2();
	return res;
}
  1. GSM网络判断:如果不成功也要重启模块然后重新配置
unsigned char m26_conf_GSM()
{
		unsigned char res = 0;
	int i = 0;
	//30s未找到网络则需要重启
	for(i = 0; i < 60; i++)
	{
		if(M26_SendCmd("AT+CREG?\r\n","+CREG: 0,1",500))//确定找网成功
		{
			res = 0;
			Clear_Buffer2();
		}
		else
		{
			res = 1;
			break;
		}
	}
	delay_ms(500);
	Clear_Buffer2(); 
	return res;
}
  1. GPRS网络判断:查询失败也要强制执行下一步流程
unsigned char m26_conf_GPRS()
{
		
	//30失败则强制执行下一步
	int i = 0;
	for(i = 0; i < 60; i++)
	{
		if(M26_SendCmd("AT+CGREG?\r\n","+CGREG: 0,1",500))//GPRS网络注册状态
		{
			Clear_Buffer2(); 
		}
		else
		{
			break;
		}
	}
	delay_ms(500);
	Clear_Buffer2(); 
	return 1;
}
  1. PDP上下文的配置:这里面的流程必须打包顺序执行,如果有错误,必须关闭场景后重新配置,如果关闭失败就要重启模块后重新配置
unsigned char m26_conf_PDP()
{
	unsigned char res = 0;
	int i;
	int j;
	for(i = 0; i < 10; i++)
	{
		if(M26_SendCmd("AT+QIREGAPP\r\n","OK",500) == 0) //启动应用 
		{
			delay_ms(500);
			Clear_Buffer2();
			for(j = 0; j < 3; j++)
			{
				if(M26_SendCmd("AT+QIACT\r\n","OK",500) == 0)//开启PDP场景
				{
					M26_SendCmd("AT+QILOCIP\r\n","ERROR",500);//获取IP地址
					res = 1;
					break;
				}
				else
				{
					res = 0;
					Clear_Buffer2();
				}
			}
			return res;
		}
		else
		{
			res = 0;
			Clear_Buffer2();
		}		
	}

	return res;
}
  1. 其他配置
unsigned char m26_conf_other()
{
	while(M26_SendCmd("ATV1\r\n","OK",500)) //设置回复的是OK 
	{
		Clear_Buffer2(); 
	}
	delay_ms(500);
	Clear_Buffer2();
	
	while(M26_SendCmd("AT+QIDNSIP=0\r\n","OK",500)) //设置使用IP连接 0IP 1域名
	{
		Clear_Buffer2(); 
	}
	delay_ms(500);
	Clear_Buffer2();	
	

	while(M26_SendCmd("AT+QIMODE?\r\n","OK",500)) //查询是否是透传模式
	{
		Clear_Buffer2(); 
	}
	delay_ms(500);
	Clear_Buffer2();	

}

如果需要关闭PDP场景,需要发送AT指令关闭

unsigned char m26_close_PDP()
{	
	int i;
	for(i = 0; i < 10; i++)
	{
			if(M26_SendCmd("AT+QIDEACT\r\n","ERROR",1000))
				return 1;
	}
	return 0;
}

如果需要关机,M26关机比较简单只要发送AT指令即可

void m26_powerDown()
{
		while(M26_SendCmd("AT+QPOWD=1\r\n","NORMAL POWER DOWN",500)) 
		{
			Clear_Buffer2(); 
		}
		delay_ms(500);
		Clear_Buffer2();
}
  1. 初始化函数总流程,参数s是为了方便初始化失败后跳跃没必要的初始化步骤
void m26_init_new(int s)
{
	//m26_poweron();
	int i = s;
	while(1)
	{
		switch(s)
		{
			case 0://判断是否开机,未开机开机
				m26_poweron();
			case 1://基础配置和APN配置
				m25_conf_base();
				m26_conf_APN();
			case 2://查询SIM卡级初始化状态
				if(m26_conf_SIM() == 0)
				{
					m26_powerDown();
					i = 0;
					continue;
				}
			case 3://GSM网络判断
				if(m26_conf_GSM() == 0)
				{
					m26_powerDown();
					i = 0;
					continue;
				}
			case 4://GPRS网络判断
				m26_conf_GPRS();
			case 5://PDP场景配置
				if(m26_conf_PDP() == 0)
				{
					if(m26_close_PDP() == 1)
					{
						i = 2;
						continue;
					}
					else
					{
						m26_powerDown();
						i = 0;
						//m26_init_new(0);
						continue;
					}
				}
			default:
				break;
		}
		break;
	}	
}

连接到服务器,我现在是域名连接

unsigned char  m26_connect_new()
{
	while(M26_SendCmd("AT+QIOPEN=\042TCP\042,\042www.xxxx.com\042,\0421301\042\r\n","OK",500));
	while(1)
	{
		if(m26_CheckCmd("ALREADY CONNECT") == 0)
		{
			return 1;
		}
		else if(m26_CheckCmd("CONNECT OK") == 0)
		{
			return 1;
		}
		else if(m26_CheckCmd("CONNECT FAIL") == 0)
		{
			while(M26_SendCmd("AT+QISTAT\r\n","OK",500));
			return 0;
		}
	}
}

发送数据

1.发送指定长度的数据是推荐的,不推荐使用不指定长度

unsigned char m26_tcp_send_len(uint8_t * msg,int len)
{
	while(M26_SendCmd("AT+QISEND=?\r\n","OK",500));
	//Clear_Buffer2();
	char ATbuff[50] = "";
	memset(ATbuff,0,sizeof(ATbuff));
	sprintf(ATbuff,"AT+QISEND=%d\r\n",len);
	while(M26_SendCmd(ATbuff,"<",500))
	{
		//如果在服务器连接上瞬断后,发送发送指令悔返回ERROR
		if(m26_CheckCmd("ERROR") == 0)
		{
			return 0;
		}
	}
	Clear_Buffer2();
	Uart1_serial_send(USART2,msg);
	delay_ms(500);
	if(m26_CheckCmd("SEND OK") == 0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
  1. 发送成功后只是将数据发送的M26的协议栈中,不是真正的发送,这里需要检测真正的数据传输完成
int m26_send_stat()
{
	strx = NULL;	
	int length = -1;
	int i;
	//bixu duoqing jici 20190321
	Clear_Buffer2();
	Clear_Buffer2();
	for(i = 0; (i < 30) && (length != 0); i++)
	{
			while(M26_SendCmd("AT+QISACK\r\n","OK",500));
			strx=strstr((const char*)RI_Set2_Buffer,(const char*)"+QISACK");
			if(strx != NULL)
			{
				strx = strstr((const char*)RI_Set2_Buffer,(const char*)",");
				strx = strstr(strx+1,(const char*)",");
				//解析后的长度是字符串,这里是将字符串转换成整形,没有atoi,只能自己封装
				length = str2int(strx+2);
			}
			else
			{
				Clear_Buffer2();
				return -1;
			}
			
			Clear_Buffer2();
	}	
	return length;
}

这里是整个初始化,发送流程,具体发送AT指令和接受根据手里的单片机文档封装即可

你可能感兴趣的:(物理透传)