admin管理员组

文章数量:1558963

前言

首先,我们需要梳理一下我们整个流程的思路:我们是通过单片机(STM32)的串口发送AT指令给wifi模块进行模块初始化;紧接着,手机TCP助手连接AP发送消息,利用串口接收wifi模块返回的响应信息,对响应的信息进行判断,做出正确的反应。
整个流程大致可以归纳为以上的那么一段话,接下来我们就根据具体代码来仔细讲解,代码不复杂,我写代码都是怎么简单怎么来,所以相信大家都可以看的懂。

代码讲解

串口初始化

用的是串口2收发信息,硬件上将串口2的TX,RX跟模组的RX,TX连接,下面贴上代码:

	u8 USART2_RX_BUF[USART2_REC_LEN];  //定义接收缓存数组(串口接受的数据存储在数组里)
	u16 USART2_RX_STA=0; 
	int flag=0;  //串口接收标志位
	
	void W600_USART_init(void)
	{
	GPIO_InitTypeDef GPIO_InitStrue;     //结构体定义
	USART_InitTypeDef USART_InitStrue;
	NVIC_InitTypeDef NVIC_InitStrue;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);  //使能串口2,GPIOA时钟 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
	//GPIOA初始化
	GPIO_InitStrue.GPIO_Pin = GPIO_Pin_2;          //USART2_TX	    PA.2
    GPIO_InitStrue.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStrue.GPIO_Mode = GPIO_Mode_AF_PP;	   //复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStrue);             //初始化PA2
     
    GPIO_InitStrue.GPIO_Pin = GPIO_Pin_3;             //USART2_RX	  PA.3
    GPIO_InitStrue.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStrue);                //初始化PA3
	
	//USART初始化
	USART_InitStrue.USART_BaudRate = 115200;//波特率
	USART_InitStrue.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStrue.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStrue.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStrue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	USART_Init(USART2, &USART_InitStrue); //初始化串口
	
	NVIC_InitStrue.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStrue.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStrue.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStrue);	//根据指定的参数初始化VIC寄存器
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断
	
	USART_Cmd(USART2,ENABLE);   //使能串口
	}

	//*************************串口2中断服务函数*********************************//
	void USART2_IRQHandler(void)                	//串口2中断服务程序
	{
	if(USART_GetITStatus(USART2, USART_IT_RXNE)!=RESET)  
		{  
			 flag=1;
		   USART2_RX_BUF[USART2_RX_STA++]=USART_ReceiveData(USART2);
		}	
	}  

上面这段代码没什么特别的,就是串口的初始化,重点看一下中断服务函数,我们的信息接收是在中断中进行的,原本用的是正点原子的,但是却一直收不到数据,弄了很久才发现问题在于原子定义的协议,协议规定了接收到回车换行代表数据接收完成,但恰恰我用的wifi模块返回的信息是回车换行开头的…,所以我修改成没有任何协议,只要接收到数据就统统存储到前面定义的数组中。

WiFi模块初始化

说是模块的初始化,实际上模块没有什么要初始化的,硬件连接上去就可以收发数据,我们在这里做的就是编写单片机发送AT指令给模块配置AP模式的函数,直接贴代码:

	//*******************预定义字符串*****************************//
	char w600_rst[]="AT+RST\r\n"; //复位指令
	char w600_at[]="AT\r\n"; //握手连接指令
	char w600_cwmode1[]="AT+CWMODE=1\r\n"; //设置w600工作模式为STA 
	char w600_cwmode2[]="AT+CWMODE=2\r\n"; //设置w600工作模式为AP 
	char w600_cwjap[]="AT+CWJAP=\"USER_1A383A\",\"00000000\"\r\n"; //设置要加入的AP参数 
	char w600_cwsap[]="AT+CWSAP=\"lxz\",\"lxz333333\",5,3\r\n"; //设置要创建的AP参数
	char w600_cipmux[]="AT+CIPMUX=1\r\n"; //使能多链接 
	char w600_cipserver[]="AT+CIPSERVER=1,6000\r\n"; //创建服务器
	char w600_return[]="OK\r\n";

	//*******************字符串发送函数*****************************//
	void USART_SendString(USART_TypeDef* USARTx,char *str)
	{
		while(*str!='\0')
		{ 
		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC )==RESET);	
		USART_SendData(USARTx,*str);
		str++;
		}
	}

	//*************************数组清空函数**************************//
	void Data_Clear(void)
	{
		int i;
		for(i=0;i<600;i++)
		{
		USART2_RX_BUF[i]=0;
		}	
	}

	//*************************返回信息比较函数************************//
	 Data_Compare(void)
	{
	int i;
	int strx=0;
		for(i=0;i<600;i++)
	{
		if((USART2_RX_BUF[i]=='O')&&(USART2_RX_BUF[i+1]=='K'))
	{
	  strx=1;
	}
	
	return strx;
	}
	u8 Data_Compare1(void)
	{
	int i;
	int strx=0;
		for(i=0;i<600;i++)
	{
		if((USART2_RX_BUF[i]=='S')&&(USART2_RX_BUF[i+1]=='T'))
	{
	  strx=1;
	}
	}
	return strx;
	}
	u8 Data_Compare2(void)
	{
	int i;
	int strx=0;
		for(i=0;i<600;i++)
	{
		if((USART2_RX_BUF[i]=='O')&&(USART2_RX_BUF[i+1]=='N'))
	{
	  strx=1;
	}
	}
	return strx;
	}

	//***************************W600初始化**************************//
	void W600_wifi_init(void)
	{ 
	USART_SendString(USART2, w600_at);
	while(1){
	if(Data_Compare()==1) break;		     
	}
	Data_Clear();
	WLED1=1;
	delay_ms(500);
	USART_SendString(USART2, w600_cwmode2);
	while(1){
	if(Data_Compare()==1) break;	
	}
	Data_Clear();
	WLED1=0;
	delay_ms(500);
	USART_SendString(USART2, w600_cwsap);
	while(1){
	if(Data_Compare()==1) break;	
	}
	Data_Clear();
	WLED1=1;
	delay_ms(500);
	USART_SendString(USART2, w600_cipmux);
	while(1){
	if(Data_Compare()==1) break;	
	}
	Data_Clear();
	WLED1=0;
	delay_ms(500);
	USART_SendString(USART2, w600_cipserver);
	while(1){
	if(Data_Compare()==1) break;		
	}
	Data_Clear();
	WLED1=1;
	}  

上面这段代码有几个函数我们讲解一下,首先是数组清空函数void Data_Clear(void),这个函数的作用是清空每一次我们接收的内容,为了下一次接收新的数据做准备,避免出错;还有一个就是返回信息比较函数Data_Compare(void),因为我们每一次发送AT指令,模块都会返回响应信息,我们需要判断是否接收到正确的信息来确定是否发送新的AT指令;最后一个就是系列指令发送的函数了void W600_wifi_init(void),这个函数我们通过系列指令来配置AP模式,使能多链接以及确定端口号…每发送一个指令,判断一次返回信息,这里还用LED亮灭来辅助观察,相信大家看代码是可以看的懂的。

主函数

下面我们看看主函数

	int main(void)
	{		
	int i;
	delay_init();	    	 //延时函数初始化	  
	NVIC_Configuration(); 	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(9600);	 //串口初始化为9600
	KEY_Init(); 
	LED_Init();
	W600_USART_init();
	W600_wifi_init();
	while(1)
	{
	if(Data_Compare1()==1) break;		
	}
	Data_Clear();
	while(1)
	{
	if(Data_Compare2()==1) break;		
	}
	Data_Clear();
	flag =0;
	
	 while(1)
	 {
		 if(flag == 1){
			 flag =0;
			 for(i=0;i<600;i++){
				 if(USART2_RX_BUF[i]=='1'  && USART2_RX_BUF[i+1]==':')
       {
				 switch(USART2_RX_BUF[i+2])
					 {
                case 'O': WLED2=1;
                          break;		 
                case 'F': WLED2=0;
                          break;
								default:  break;      							 
			  	 }
	 }
	 }
	 }
	 }
	}  

这里头还用到了两个返回信息比较函数,因为我们手机连上热点和连接上对应端口,模块都会分别返回信息到串口,这里也要判断一下;最后我们再次讲解一下我们的串口中断服务函数,里头定义了每次接收到数据,标志位置1,前面我们不讲是因为我们没用到这个标志位,当我们手机TCP调试助手连接上模块后,我们的准备工作就算是做完了,这时将标志位置0,接下来就是等待发送亮灭等的信息了,这里我们定义循环接收信息,当发送亮灭等信号后串口接收到新的数据(也就是当标志位被置1),我们判断是要亮还是灭,然后做出正确响应。(亮时O,灭时F,这些都是我们自己可以定义修改的)。
好了,代码这样就讲解完了,大家实践试试吧,本片完结!!!

本文标签: 用手单片机指令发信息助手