stm32学习笔记-通过串口3使用wifi模块连接新大陆云平台

一、使用USB转TTL模块测试连接云平台。

AT指令代码:

连接新大陆云平台
AT						//检测wifi模块是否一安装
AT+CWMODE=1					//STA模式
AT+CWJAP="pengchun","p2952870"			//连接wifi热点
AT+CIPSTART="TCP","120.77.58.34",8700			//建立TCP连接
AT+CIPSEND=84					//发送数据包长度,自己根据数据包更改长度
{"t":1,"device":"pzlbban","key":"34903414c53e412985abea331ed13c50","ver":"v0.0.0.0"}//握手连接报文
AT+CIPSEND=51					
{"t":3,"datatype":1,"datas":{"lock":1},"msgid":123}		//传感器数据上传
AT+CIPSEND=7					
"$#AT#"						//心跳包

窗口助手观察现象
在这里插入图片描述

握手连接响应
+IPD,19:{"status":0,"t":2}
上传传感数据响应
+IPD,31:{"msgid":123,"status":0,"t":4}

二、stm32配置串口1,串口3,并进行简单测试。

串口1用来把串口3接收到的数据打印到PC机的串口助手上。
串口3与ATK_ESP8266WIFI模块交互,用来发送AT指令,接收WIFI模块的响应信息。
配置如下:

Tool.h (usart.c配置使用到这里的 MY_NVIC_Init() 函数)

#ifndef TOOL_H
#define TOOL_H
#include "stm32f10x.h"
#define GPIOA_ODR (GPIOA_BASE+0x0C)
#define GPIOA_IDR (GPIOA_BASE+0x08)
#define GPIOB_ODR (GPIOB_BASE+0x0C)
#define GPIOB_IDR (GPIOB_BASE+0x08)
#define GPIOC_ODR (GPIOC_BASE+0x0C)
#define GPIOC_IDR (GPIOC_BASE+0x08)
#define GPIOD_ODR (GPIOD_BASE+0x0C)
#define GPIOD_IDR (GPIOD_BASE+0x08)
#define GPIOE_ODR (GPIOE_BASE+0x0C)
#define GPIOE_IDR (GPIOE_BASE+0x08)

#define BitBand(Addr,bitNum) *((volatile unsigned long *)((Addr&0xf0000000)+0x2000000+((Addr&0xfffff)<<5)+(bitNum<<2)))
	
#define PAout(n) BitBand(GPIOA_ODR,n)
#define PAin(n)  BitBand(GPIOA_IDR,n)
#define PBout(n) BitBand(GPIOB_ODR,n)
#define PBin(n)  BitBand(GPIOB_IDR,n)
#define PCout(n) BitBand(GPIOC_ODR,n)
#define PCin(n)  BitBand(GPIOC_IDR,n)
#define PDout(n) BitBand(GPIOD_ODR,n)
#define PDin(n)  BitBand(GPIOD_IDR,n)
#define PEout(n) BitBand(GPIOE_ODR,n)
#define PEin(n)  BitBand(GPIOE_IDR,n)

#define led1 PBout(5)
#define led2 PEout(5)

void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_Subpriority,u8 NVIC_Channel,u32 NVIC_Group);
#endif

usart.h

#ifndef USART1_H
#define USART1_H
#include "stm32f10x.h"
#include "stdarg.h"
#include <stdio.h>
#include <string.h>
#include "Tool.h"

#define EN_USART1_RX						0	//串口接收使能。
#define EN_USART3_RX						1	//串口接收使能。

#define USART1_REC_LEN 500
#define USART3_REC_LEN 500
#define USART3_SEND_LEN 500

#ifdef EN_USART1_RX	//如果使能了接收中断
extern u16 USART1_RX_STA;//USART1状态标志变量。
extern u8 USART1_RX_BUF[USART1_REC_LEN];
#endif

#ifdef EN_USART3_RX	//如果使能了接收中断
extern u16 USART3_RX_STA;
extern u8 USART3_RX_BUF[USART3_REC_LEN];
extern u8 USART3_TX_BUF[USART3_SEND_LEN];
#endif
void usart1_init(u32 baundRate);

void usart3_init(u32 baundRate);
void u3_printf(char* fmt,...);
void USART3_Clear_RxBuf(void);
#endif

usart.c

#include "usart.h"



/*****************************************************************************************
* Function Name : fputc
* Descrption    : 重定向这个C库(stdio) printf函数 文件流->串口USART1
* Input					: ch ,*f
* Output				: None
* Return				: None 
*****************************************************************************************/
int fputc(int ch,FILE *f)
{
	//将ch送给USART1
	USART_SendData(USART1,ch);
	//等待发送完毕
 	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
	//返回ch
	return ch;
}


void usart1_init(u32 baundRate)
{	
	GPIO_InitTypeDef GPIO_InitStructure; 
	USART_InitTypeDef usartst;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);	//使能USART1,GPIOA时钟
	
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
	
	
	usartst.USART_BaudRate = baundRate;
	usartst.USART_WordLength = USART_WordLength_8b;
	usartst.USART_StopBits = USART_StopBits_1;
	usartst.USART_Parity = USART_Parity_No;
	usartst.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usartst.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
	USART_Init(USART1,&usartst);
	USART_Cmd(USART1,ENABLE);
	
#ifdef EN_USART1_RX	//如果使能了接收中断
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
	MY_NVIC_Init(3, 2, USART1_IRQn, NVIC_PriorityGroup_2);	//中断分组2
	
#endif	
}



void usart3_init(u32 baundRate)
{	
	USART_InitTypeDef usartst;
	GPIO_InitTypeDef GPIO_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能USART3,GPIOA时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//注意usart3再apb1
	
	//USART3_TX   GPIOB.10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.10
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.11  
	
	
	USART_DeInit(USART3);  //复位串口3
	usartst.USART_BaudRate = baundRate;
	usartst.USART_WordLength = USART_WordLength_8b;
	usartst.USART_StopBits = USART_StopBits_1;
	usartst.USART_Parity = USART_Parity_No;
	usartst.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usartst.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
	USART_Init(USART3,&usartst);
	USART_Cmd(USART3,ENABLE);
	
#ifdef EN_USART3_RX	//如果使能了接收中断
	
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
	
	MY_NVIC_Init(2, 3, USART3_IRQn, NVIC_PriorityGroup_2);	//中断分组2
	
#endif

}


//串口3,printf 函数
//确保一次发送数据不超过USART3_MAX_SEND_LEN字节
void u3_printf(char* fmt,...)  
{  
	u16 i,j; 
	va_list ap; 
	va_start(ap,fmt);
	vsprintf((char*)USART3_TX_BUF,fmt,ap);
	va_end(ap);
	i=strlen((const char*)USART3_TX_BUF);		//此次发送数据的长度
	for(j=0;j<i;j++)							//循环发送数据
	{
	  while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕   
		USART_SendData(USART3,USART3_TX_BUF[j]); 
	} 
}



u16 USART1_RX_STA = 0;
u8 USART1_RX_BUF[USART1_REC_LEN];
//USART1中断服务程序
void USART1_IRQHandler(void)
{
	u8 Res;
	//USART1中断服务程序只有一个,得判断是串口的什么中断
	//指令判断是否是接收中断
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a 作为结尾,即 按下回车键 结尾)
	{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART1_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART1_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART1_RX_STA=0;//接收错误,重新开始
				else USART1_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART1_RX_STA|=0x4000;
				else
					{
					USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ;
					USART1_RX_STA++;
					if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
  } 
}


u16 USART3_RX_STA = 0;
u8 USART3_RX_BUF[USART3_REC_LEN];
u8 USART3_TX_BUF[USART3_SEND_LEN];
void USART3_Clear_RxBuf(void)
{
	memset(USART3_RX_BUF,0x00,USART3_REC_LEN);
}
//USART3中断服务程序
void USART3_IRQHandler(void)
{
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收到数据
	{

		USART3_RX_BUF[USART3_RX_STA] = USART_ReceiveData(USART3);	//读取接收到的数据
		USART3_RX_STA++;
		if(USART3_RX_STA>USART3_REC_LEN)//缓存区溢出
		{USART3_RX_STA = 0x0000;}	   		 		 
	}	
}

main.c

#include "stm32f10x.h"
#include "bsp_systick.h"
#include "led.h"
#include "exti.h"
#include "Tool.h"
#include "usart.h"


void Stm32_Clock_Init(void)
{
	/*----------使用外部RC晶振----------*/
	RCC_DeInit() ;
	//初始化为缺省值
	RCC_HSEConfig(RCC_HSE_ON); //使 能外部的高速时钟
	while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //等 待外部高速时钟使能就绪
	
	//Flash 2 wait state
	RCC_HCLKConfig (RCC_SYSCLK_Div1) ;
	//HCLK = SYSCLK
	RCC_PCLK2Config(RCC_HCLK_Div1) ;
	//PCLK2 =HCLK
	RCC_PCLK1Config(RCC_HCLK_Div2) ;
	//PCLK1 = HCLR/2
	RCC_PLLConfig (RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLLCLK = 8MHZ * 9 =72MHZ
	RCC_PLLCmd(ENABLE) ;
	//Enable PLLCLK
	while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLLCLK is ready
	RCC_SYSCLKConfig (RCC_SYSCLKSource_PLLCLK) ;
	//Select PLL as system clock
	while (RCC_GetSYSCLKSource () !=0x08) ;
	//wait till PLL is used as system clock source

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
}



u8 check_AT_Respose(u8 *string)
{
	printf("接收到模块响应数据为:\n%s\n",USART3_RX_BUF);
	if(strstr((const char*)USART3_RX_BUF,(const char*)string) != 0)
	{
		printf("接收到期待的响应 %s",string);
		USART3_RX_STA = 0;
		memset(USART3_RX_BUF,0x00,USART3_REC_LEN);
		return 1;
	}	
	else
	{
		printf("未接收到期待的响应 %s",string);
		USART3_RX_STA = 0;
		memset(USART3_RX_BUF,0x00,USART3_REC_LEN);
		return 0;
	}
}

/*****************************************************************************************
* Function Name : sentATCmd
* Descrption    : 使用串口3发送AT指令
* Input					: string 发送内容,lenth发送内容的长度
* Output				: None
* Return				: None 
*****************************************************************************************/
u8 sentATCmd(u8 *cmd,u8 times)
{
	u8 i;
	for(i=0;i<times;i++)
	{
		u3_printf("%s\r\n",cmd);
		printf("已发送指令:%s\n",cmd);
		SysTick_Delay_ms(1500);
		SysTick_Delay_ms(1500);
		if(check_AT_Respose("OK"))
			return 1;
		printf("发送指令响应错误,1.5s后重新发送指令:%sn",cmd);
		SysTick_Delay_ms(1500);
	}
	return 0;
	
}


void wifi_Test(void)
{
	u8 *instruction = "";
	instruction="AT";
	sentATCmd(instruction,3);
	SysTick_Delay_ms(1500);
	
	instruction="AT+GMR";
	sentATCmd(instruction,3);
	SysTick_Delay_ms(1500);
	
	instruction="AT+CWMODE=1";
	sentATCmd(instruction,3);
	SysTick_Delay_ms(1500);
	
	instruction="AT+CWJAP=\"pengchun\",\"p2952870\"";
	sentATCmd(instruction,3);
	SysTick_Delay_ms(1500);
	
	instruction="AT+CIFSR";
	sentATCmd(instruction,3);
	SysTick_Delay_ms(1500);
	
}
int main(void)
{
	//Stm32_Clock_Init();
	led_init();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	exti_init();
	usart1_init(9600);
	usart3_init(115200);
	
	led1 = 0;
	led2 = 0;
	printf("system start!\n");
	
	
	while(1)
	{
		wifi_Test();
	}
}

现象结果

可以观察到wifi模块响应的响应。
在这里插入图片描述
在此测试中发现连接wifi热点响应时间较慢,编程时应该给予更多的响应时间。

三、编写为wifi模块服务的文件。

遇到的问题:如何usart3接收到的数据时一次发送过来的数据?
解决:通过延时读RXBUF,把这段时间内发送过来的数据看作一次连续发送的数据。

esp_8622wifi.h

#ifndef ESP_8622WIFI_H
#define ESP_8622WIFI_H

#include "usart.h"
#include "stm32f10x.h"
#include "bsp_systick.h"
#include "string.h"
//WiFi连接
//云平台连接
//数据上传
//命令上传
#define DeviceID "AIPickUpClothes"//设备表标识
#define SecretKey "0a7a1d29d34748dca7dfe19543b16098"//密钥


u8 sentATCmd(u8 *cmd,u8 *ack,u8 times);
u8 sentData(u8 *data,u8 *ack,u8 times);
u8 connect_Wifi(void);
u8 connect_Cloud(void);
u8 ESP8266_sensorSend(u8 *sensorTag,u8 sensorValue,u8 tryTimes);
#endif

esp_8622wifi.c

#include "esp_8622wifi.h"

/*****************************************************************************************
* Function Name : check_AT_Respose
* Descrption    : 使用串口3发送AT指令
* Input					: string 期待的响应内容
* Output				: None
* Return				: None 
*****************************************************************************************/
u8 check_AT_Respose(u8 *string)
{
	printf("\n接收到模块响应数据为:\n%s",USART3_RX_BUF);
	if(strstr((const char*)USART3_RX_BUF,(const char*)string) != 0)
	{
		printf("\n接收到期待的响应 %s",string);
		USART3_RX_STA = 0;
		memset(USART3_RX_BUF,0x00,USART3_REC_LEN);
		return 1;
	}	
	else
	{
		printf("\n未接收到期待的响应 %s",string);
		USART3_RX_STA = 0;
		memset(USART3_RX_BUF,0x00,USART3_REC_LEN);
		return 0;
	}
}

/*****************************************************************************************
* Function Name : sentATCmd
* Descrption    : 使用串口3发送AT指令
* Input					: string 发送内容,ack期许的应答,times重试次数
* Output				: None
* Return				: None 
*****************************************************************************************/
u8 sentATCmd(u8 *cmd,u8 *ack,u8 times)
{
	u8 i;
	for(i=0;i<times;i++)
	{
		u3_printf("%s\r\n",cmd);
		printf("\n已发送指令:%s",cmd);
		SysTick_Delay_ms(1500);
		if(check_AT_Respose(ack))
			return 1;
		printf("\n发送指令响应错误,1.5s后重新发送指令:%s",cmd);
		SysTick_Delay_ms(1500);
	}
	return 0;
	
}


/*******************************************************************
*函数:u8 ESP8266_IpSend(u8 *data,u8 *ack,u8 lenth,u8 times)
*功能:发送数据函数
*输入:
	u8 *data, 发送的数据氨?
	u8 *ack,	期待的响应
	u8 sensor, 传感数值
	u8 tryTimes 若不成功尝试发送次数
*输出:
		return = 1 ,sucess
		return = 0 ,error
*特殊说明:
*******************************************************************/
u8 ESP8266_IpSend(u8 *data,u8 *ack,u8 lenth,u8 tryTimes)
{
	u8 i;
	u8 CIPSEND[USART3_SEND_LEN];
	memset(CIPSEND,0x00,USART3_SEND_LEN);
	sprintf((char *)CIPSEND,"AT+CIPSEND=%d",lenth);
	for(i=0;i<tryTimes;i++)
	{	
		u3_printf("%s\r\n",CIPSEND);
		SysTick_Delay_ms(100);
		if(check_AT_Respose("OK"))
		{
			u3_printf("%s",data);
			printf("\n已经发送数据报:%s",data);
			SysTick_Delay_ms(500);
			if(check_AT_Respose(ack))
				return 1;
			printf("\n数据响应错误,1.5s后重新发送指令:%s",data);
			SysTick_Delay_ms(1500);
		}
		else
		{
			printf("CIPSEND发生错误!");
		}
	}
	return 0;
}


/*******************************************************************
*函数:ESP8266_SendSensor
*功能:发送传感数据到服务器
*输入:
	u8 *SensorTag, 对象标签名称
	u8 sensor, 传感数值
	u8 tryTimes 若不成功尝试发送次数
*输出:
		return = 1 ,sucess
		return = 0 ,error
*特殊说明:
	函数流程:
		1、拼接json数据包
		2、发送数据包
		3、
*******************************************************************/
u8 ESP8266_sensorSend(u8 *sensorTag,u8 sensorValue,u8 tryTimes)
{
	u8 jsonTemp[USART3_SEND_LEN];
	memset(jsonTemp,0x00,USART3_SEND_LEN);
	sprintf((char*)jsonTemp,"{\"t\":3,\"datatype\":1,\"datas\":{\"%s\":%d},\"msgid\":001}",sensorTag,sensorValue);
	if(ESP8266_IpSend(jsonTemp,"\"status\":0",strlen((char*)jsonTemp),tryTimes))
		return 1;
	return 0;
}

/*******************************************************************
*函数:connect_Wifi
*功能:连接上wifi热点
*输入:None
*输出:
		return = 1 ,sucess
		return = 0 ,error
*特殊说明:
	函数流程:
		1、检测wifi模块
		2、设置为sta模式
		3、连接wifi热点
*******************************************************************/
u8 connect_Wifi(void)
{
	
	u8 *instruction="AT";
	if(sentATCmd(instruction,"OK",3))//检测wifi模块
	{
		SysTick_Delay_ms(1000);
		instruction="AT+CWMODE=1";
		if(sentATCmd(instruction,"OK",3))//设置为sta模式
		{
			SysTick_Delay_ms(1500);
			instruction="AT+CWJAP=\"pengchun\",\"p2952870\"";
			if(sentATCmd(instruction,"OK",5))//连接wifi热点
			{
				return 1;
			}
		}
	}
	return 0;
}

/*******************************************************************
*函数:connect_Cloud
*功能:连接上新大陆云平台
*输入:None
*输出:
		return = 1 ,sucess
		return = 0 ,error
*特殊说明:
	函数流程:
		1、检测wifi模块
		2、设置为sta模式
		3、连接wifi热点
*******************************************************************/
u8 connect_Cloud(void)
{
	u8 *instruction = "";
	instruction="AT+CIPSTART=\"TCP\",\"120.77.58.34\",8700";
	if(sentATCmd(instruction,"OK",3))
	{
		u8 IPDATA[200];
		memset(IPDATA,0x00,200);
		sprintf((char *)IPDATA,"{\"t\":1,\"device\":\"%s\",\"key\":\"%s\",\"ver\":\"v0.0.0.0\"}",DeviceID,SecretKey);
		if(ESP8266_IpSend(IPDATA,"{\"status\":0,\"t\":2}",strlen((char*)IPDATA),3))
		{
			printf("与云平台握手连接成功");
			return 1;
		}
	}
	return 0;
}

main.c

#include "stm32f10x.h"
#include "bsp_systick.h"
#include "led.h"
#include "exti.h"
#include "Tool.h"
#include "usart.h"
#include "esp_8622wifi.h"

u8 wifiConnected = 0;
u8 cloudConnected = 0;
int main(void)
{
	led_init();
	exti_init();
	usart1_init(9600);
	usart3_init(115200);
	
	led1 = 0;
	led2 = 0;
	printf("system start!\n");
	
	while(1)
	{
		if(wifiConnected == 0)
			if(connect_Wifi())
				wifiConnected=1;
		if((wifiConnected == 1) && (cloudConnected == 0))
			if(connect_Cloud())
				cloudConnected=1;
		
		SysTick_Delay_ms(1500);	
		ESP8266_sensorSend("temperature",30,3);
	}
}


现象结果

串口助手结果
在这里插入图片描述
查看云平台历史传感数据,云平台一直接收到temperature的传感数据。
在这里插入图片描述

  • 4
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值