十二、【高级篇】WIFI模块-ESP8266


WiFi:芯片是ESP8266(32bit的单片机芯片),2.4GHz的无线射频模块,内部集成了TCP/UDP的协议栈
需要通过串口为ESP8266发送AT指令:AT指令集、AT指令使用示例

ESP8266模块是通过串口接口进行交互数据,连接STM32F103R8T6 USART2

AT指令集

在这里插入图片描述
在这里插入图片描述

AT指令使用示例

在这里插入图片描述

ESP8266单连接:

在这里插入图片描述
在这里插入图片描述

ESP8266透传

在这里插入图片描述

ESP8266驱动代码:

#ifndef __ESP8266_H
#define __ESP8266_H
/*
ESP8266模块是WIFI无线通讯模块,该模块是串口接口
连接到了我们开发板上的USART2
*/
#include "stm32f10x_conf.h"//包含该头文件所有的外设头文件均已包含

typedef void (*wifi_recv_handler)(char *buf, int len);//通过typedef定义函数指针类型

extern void set_wifi_recv_handler(wifi_recv_handler h);//设置wifi接收到数据的回调函数
extern void esp8266_init(void);//初始化的函数(初始化串口)
extern void esp8266_link_wifi(char *ssid, char *passwd);//连接路由(需要路由的名称和路由的密码)
extern void esp8266_connect(char *ip, char *port);//连接TCP server
extern void esp8266_disconnect(void);//断开TCP连接
extern void esp8266_send(char *msg, char *len);//发送数据
extern void dataHandler(unsigned char c);//处理接收到的数据

#endif
#include "esp8266.h"
#include "usart2.h"
#include "delay.h"
#include "stdio.h"
#include "stdlib.h"

#define O_F	1//O的状态
#define K_F	2//K的状态
static int flag = O_F;
static int ok_flag = 0;
static int len = 0;//保存数据长度的整数

//"+IPD,13:1234567890ABC"
#define ADD_S 	0//+的状态
#define I_S			1//I的状态
#define P_S			2//P的状态
#define D_S			3//D的状态
#define H_S			4//,的状态
#define LEN_S		5//长度的状态
#define DATA_S	6//数据的状态
static int data_flag = ADD_S;//默认是+的状态
wifi_recv_handler wifi_handler = NULL;

void set_wifi_recv_handler(wifi_recv_handler h)//设置wifi接收到数据的回调函数
{
    
    
	wifi_handler = h;
}

void dataHandler(unsigned char c)//处理接收到的数据
{
    
    
	static char len_buf[5];//接收到数据的字节数
	static int i = 0;//循环变量
	static char data_buf[512];//存储接收到的数据
	
	switch(data_flag)
	{
    
    
		case ADD_S :
			if(c == '+')
				data_flag = I_S;
			break;
		case I_S :
			if(c == 'I')
				data_flag = P_S;
			else
				data_flag = ADD_S;
			break;
		case P_S :
			if(c == 'P')
				data_flag = D_S;
			else
				data_flag = ADD_S;
			break;
		case D_S :
			if(c == 'D')
				data_flag = H_S;
			else
				data_flag = ADD_S;
			break;
		case H_S :
			if(c == ',')
				data_flag = LEN_S;
			else
				data_flag = ADD_S;
			break;
		case LEN_S ://+IPD,13:1234567890ABC
			if(c == ':')
			{
    
    
				len_buf[i] = '\0';
				len = atoi(len_buf);
				data_flag = DATA_S;
				i = 0;
				break;
				}
			else
				len_buf[i] = c;
				i++;
			break;
		case DATA_S:
			data_buf[i] = c;
			i++;
			if(i == len)
			{
    
    
				i = 0;
				data_flag = ADD_S;
				if(wifi_handler)
					wifi_handler(data_buf, len);
				break;
			}
			break;
	}
	
	if(c == '>')
		ok_flag = 1;
	
	if(ok_flag == 0)
	{
    
    
		switch(flag)
		{
    
    
			case O_F : 
				if(c == 'O')
					flag = K_F;
				break;
			case K_F : 
				if(c == 'K')
				{
    
    
					flag = O_F;
					ok_flag = 1;
				}
					else
						flag = O_F;
					break;
		}
	}
}

void esp8266_init(void)//初始化的函数(初始化串口)
{
    
    
	usart_2_init();
}

void esp8266_link_wifi(char *ssid, char *passwd)//连接路由(需要路由的名称和路由的密码)
{
    
    
	//AT+RST\r\n 重启无线模块
	usart_2_send_data("AT+RST\r\n");
	delay_ms(2000);//重启之后延时两秒
	
	//AT+CWMODE=1\r\n 选择wifi模式
	ok_flag = 0;
	usart_2_send_data("AT+CWMODE=1\r\n");//选择模式
	while(ok_flag == 0);//等待esp8266的OK
	
	//AT+CWJAP="SSID","password"\r\n 连接路由
	ok_flag = 0;
	usart_2_send_data("AT+CWJAP=");
	usart_2_send_byte('"');
	usart_2_send_data(ssid);
	usart_2_send_byte('"');
	usart_2_send_byte(',');
	usart_2_send_byte('"');
	usart_2_send_data(passwd);
	usart_2_send_byte('"');
	usart_2_send_data("\r\n");
	while(ok_flag == 0);
	
	//AT+CIFSR\r\n 查询分配到的IP地址(必须要查一下,否则无法建立连接)
	usart_2_send_data("AT+CIFSR\r\n");
}

void esp8266_connect(char *ip, char *port)//连接TCP server
{
    
    
	//AT+CIPSTART="TCP","192.168.3.116",8080\r\n 建立TCP连接
	ok_flag = 0;
	usart_2_send_data("AT+CIPSTART=");
	usart_2_send_byte('"');
	usart_2_send_data("TCP");
	usart_2_send_byte('"');
	usart_2_send_byte(',');
	usart_2_send_byte('"');
	usart_2_send_data(ip);
	usart_2_send_byte('"');
	usart_2_send_byte(',');
	usart_2_send_data(port);
	usart_2_send_data("\r\n");
	while(ok_flag == 0);
}

void esp8266_disconnect(void)//断开TCP连接
{
    
    
	//AT+CIPCLOSE\r\n 断开TCP连接
	usart_2_send_data("AT+CIPCLOSE\r\n");
	//注意:有可能回复有可能不回复,所以不检测closed ok
}

void esp8266_send(char *msg, char *len)//发送数据
{
    
    
	//AT+CIPSEND=4\r\n 发送数据
	ok_flag = 0;
	usart_2_send_data("AT+CIPSEND=");
	usart_2_send_data(len);
	usart_2_send_data("\r\n");
	while(ok_flag == 0);//等待 OK
	
	ok_flag = 0;
	while(ok_flag == 0);//等待 >
	
	ok_flag = 0;
	usart_2_send_data(msg);
	while(ok_flag == 0);//等待 SEND OK
}
#include "led.h"//包含LED灯的头文件
#include "buzzer.h"//包含BUZZER的头文件
#include "button.h"//包含BUTTON的头文件
#include "delay.h"//包含DELAY的头文件
#include "eint.h"//包含EINT的头文件
#include "iwdg.h"//包含IWDG的头文件
#include "dht.h"//包含DHT的头文件
#include "ldt.h"//包含LDT的头文件
#include "usart1.h"//包含USART1的头文件
#include "stdio.h"//包含标准输入输出的头文件
#include "eeprom.h"//包含EEPROM的头文件
#include "oled.h"//包含OLED的头文件
#include "sht.h"//包含SHT30的头文件
#include "adj_res.h"//包含高精度可调电阻的头文件
#include "rtc.h"//包含RTC的头文件
#include "esp8266.h"//包含ESP8266的头文件
#include "string.h"//包含字符串解析的头文件

void recv_handler(char *buf, int len)//buf里存储的是数据的内容 len里存的是数据的字节数
{
    
    
	if(strcmp(buf, "BUZZER_ON") == 0)
		buzzer_on();
	if(strcmp(buf, "BUZZER_OFF") == 0)
		buzzer_off();
}

int main(void)
{
    
    
	char dht_buf[5] = {
    
    0};//该数组用于存储DHT11采集到的数据
	int dht_value = 0;//该变量用于存储DHT11温湿度结合的数据
	int i = 500;//循环变量
	int adc_value = 0;//存储高精度可调电阻转换的数据
	u8 old_value = 97;//存储要保存的数据
	u8 new_value = 0;//存储读取出的数据
	double sht_data[2] = {
    
    0};//用于存储SHT30传感器采集到的数据
	struct time_st old_time = {
    
    2021, 11, 29, 1, 15, 0, 0};//要设置的时间
	struct time_st new_time;//保存获取到的时间
	
	led_init();//调用LED灯初始化的函数
	buzzer_init();//调用蜂鸣器初始化的函数
	button_init();//调用功能按键初始化的函数
	delay_init();//调用系统定时器初始化的函数
	eint_init();//调用按键中断初始化的函数
	dht_init();//调用DHT11初始化的函数
	ldt_init();//调用数码管初始化的函数
	usart_1_init();//调用USART1初始化的函数
	eeprom_init();//调用EEPROM初始化的函数
	OLED_Init();//调用OLED初始化的函数
	sht_init();//调用SHT30初始化的函数
	adj_res_init();//调用高精度可调电阻初始化的函数
	rtc_init(&old_time);//调用RTC初始化的函数
	esp8266_init();//调用ESP8266初始化的函数
	
	OLED_Clear();//清屏
	
	//OLED_ShowChar(0, 0, '%', 16);
	//OLED_ShowNum(0, 0, 9527, 4, 16);
	//OLED_ShowString(0, 0, "Hello World!", 16);
	//OLED_ShowCHinese(0, 0, 7);
	picture_1();
	
	sht_write_mode();//设置SHT30的采样频率
	
	led_on(0);
	esp8266_link_wifi("UPIOT", "easthome");//需要填写自己的手机热点(需要配置为2.4GHz的频段)
	delay_ms(2000);//延时2s
	led_off(0);
	
	led_on(1);
	esp8266_connect("192.168.248.41", "2222");//建立TCP连接
	delay_ms(2000);//延时2s
	led_off(1);
	
	//eeprom_byte_write(0xA0, 0x11, old_value);//写数据
	
	set_wifi_recv_handler(recv_handler);//设置回调函数
	
	while(1)
	{
    
    
		esp8266_send("Hello World", "11");
		adc_value = get_adj_res_value();//获取高精度可调电阻转换的数据
		get_time(&new_time);//把获取到的时间保存到new_time变量中
		get_dht_value(dht_buf);//获取DHT11传感器采集到的数据
		new_value = eeprom_rand_addr_read(0xA0, 0x11);//读取EEPROM的数据
		sht_read_mode();//发送采集SHT30数据的指令
		sht_read_data(sht_data);//获取SHT30采集的数据
		printf("%d-%d-%d %d %02d:%02d:%02d\n", new_time.Y, new_time.M, new_time.D, new_time.W, new_time.h, new_time.m, new_time.s);
		printf("DHT:%d-%d Eeprom:%d SHT:%.2f-%.2f ADC:%d\n", dht_buf[0], dht_buf[2], new_value, sht_data[0], sht_data[1], adc_value);
		dht_value = dht_buf[0] * 100 + dht_buf[2];//把湿度的整数以及温度的整数整合成一个4位数据
		while(i--)
			digit_show_data(dht_value);//通过数码管显示温湿度数据
		i = 500;
		led_on(0);
		delay_ms(500);
		led_off(0);
		delay_ms(500);
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_51627897/article/details/121910289