STM32cubeMX【Hal库】实现wifi无线通讯【利用ESP8266模块】——入门篇(实现点灯)

stm32串口+AT指令控制ESP8266

1.基本原理&知识点

1.1运行原理:

单片机通过串口usart向esp8266发送AT指令,上报信息。

其他设备上报的信息通过云,传送到单片机端的esp8266。

单片机通过串口usart接收esp8266所得到的云端信息。

1.2esp8266 at 指令

在这里插入图片描述

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

【对于穿透的理解】

顾名思义,开启穿透就是不用管wifi协议怎么实现的~
我们只用专注于在A设备和B设备间使用串口收发数据,
就好像A和B直接用导线相连~ 就好像穿透了~

+++可推出穿透模式

【ESP8266的一般使用顺序】
这里的“一般”指的是:ESP8266连接当前环境的热点,与服务器建立TCP连接,传输数据。

AT+CWMODE=1:设置工作模式(STA模式)
AT+RST:模块重启(生效工作模式)
AT+CWJAP=“111”,“11111111”:连接当前环境的WIFI热点(热点名,密码)
AT+CIPMUX=0:设置单路连接模式
AT+CIPSTART=“TCP”,“xxx.xxx.xxx.xxx”,xxxx:建立TCP连接
AT+CIPMODE=1:开启透传模式
AT+CIPSEND:透传模式下,传输数据
+++:退出透传模式

1.3mqtt协议

普通的socket连接对服务器的消耗太大,所以出现了类似MQTT这种轻量级、低消耗的协议来维护长连接。维护长连接需要采用心跳机制…

这篇博客写的比较简练——感谢博主.

2.云平台部分【阿里云】

我之前博客的连接.

tips:点灯的产品流转规则~没必要用json格式,二进制就行。
所谓的产品流转规则就是数据的流转规则,而数据又依托存放在topic中。
故:产品流转规则就是设计A设备使用的topic数据传送到B设备使用的topic.

3.上位机部分【安卓app】

我之前的android studio 开发app博客专题合集——mqtt.jar包.
在这里插入图片描述

4.下位机部分【stm32+AT指令】

库移植操作:
在这里插入图片描述

4.1mqtt协议库

在这里插入图片描述
这个库有6个函数,作用如函数名所示

4.2esp8266at指令库

在这里插入图片描述
这个库有12个函数,对at指令做了封装,直接调用相应函数(不用死记at指令)

4.3main.c

4.3.1 宏定义
在这里插入图片描述
4.3.2 main函数
在这里插入图片描述在这里插入图片描述

4.3.3 自定义函数

USART1接收中断代码

/****** USART1接收中断代码  *****/

// ES8266驱动串口接收中断处理函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART1)	// 判断是由哪个串口触发的中断
	{
		//将接收到的数据放入接收usart1接收数组
		usart1_rxbuf[usart1_rxcounter] = usart1_rxone[0];
		usart1_rxcounter++;	//接收数量+1
		
		//重新使能串口1接收中断
		
		/**【易错~~接受回调函数中别忘再次使能】*/
		HAL_UART_Receive_IT(&huart1,usart1_rxone,1);		
	}
}

进入错误模式代码

/************  进入错误模式代码  ************/

//进入错误模式等待手动重启
void Enter_ErrorMode(uint8_t mode)
{
	HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_SET);
	while(1)
	{
		switch(mode){
			case 0:user_main_error("ESP8266初始化失败!\r\n");break;
			case 1:user_main_error("ESP8266连接热点失败!\r\n");break;
			case 2:user_main_error("ESP8266连接阿里云服务器失败!\r\n");break;
			case 3:user_main_error("ESP8266阿里云MQTT登陆失败!\r\n");break;
			case 4:user_main_error("ESP8266阿里云MQTT订阅主题失败!\r\n");break;
			default:user_main_info("Nothing\r\n");break;
		}
		user_main_info("请重启开发板");
		//HAL_GPIO_TogglePin(LED_R_GPIO_Port,LED_R_Pin);
		HAL_Delay(200);
	}
}

初始化函数

/*************  STM32 MQTT业务代码  **********/

//MQTT初始化函数
void ES8266_MQTT_Init(void)
{
	uint8_t status=0;

	//初始化|检查esp8266好坏
	if(ESP8266_Init())
	{
		user_main_info("ESP8266初始化成功!\r\n");
		status++;
	}
	else Enter_ErrorMode(0);

	//连接手机热点|家庭wifi
	if(status==1)
	{
		if(ESP8266_ConnectAP(WIFI_NAME,WIFI_PASSWD))
		{
			user_main_info("ESP8266连接热点成功!\r\n");
			status++;
		}
		else Enter_ErrorMode(1);
	}
	
	//连接阿里云IOT服务器
	if(status==2)
	{
		if(ESP8266_ConnectServer("TCP",MQTT_BROKERADDRESS,1883)!=0)
		{
			user_main_info("ESP8266连接阿里云服务器成功!\r\n");
			status++;
		}
		else Enter_ErrorMode(2);
	}
	
	//登陆MQTT
	if(status==3)
	{
		if(MQTT_Connect(MQTT_CLIENTID, MQTT_USARNAME, MQTT_PASSWD) != 0)
		{
			user_main_info("ESP8266阿里云MQTT登陆成功!\r\n");
			status++;
		}
		else Enter_ErrorMode(3);
	}

	//订阅主题
	if(status==4)
	{
		if(MQTT_SubscribeTopic(MQTT_SUBSCRIBE_TOPIC,0,1) != 0)
		{
			user_main_info("ESP8266阿里云MQTT订阅主题成功!\r\n");
		}
		else Enter_ErrorMode(4);
	}
}

单片机状态上报——————依据项目修改

/*******  单片机状态上报  *************/

//单片机状态上报
void STM32DHT11_StatusReport(void)
{
	//获取温湿度信息
	uint8_t temperature;
	uint8_t humidity;
	uint8_t get_times;
	
	// 获取温湿度信息并用串口打印,获取十次,直到成功跳出
	for(get_times=0;get_times<10;get_times++)
	{
		if(!dht11Read(&temperature, &humidity))//Read DHT11 Value
		{
			user_main_info("temperature=%d,humidity=%d \n",temperature,humidity);
			break;
		}
	}
	
	//上报一次数据
	uint8_t led_r_status = HAL_GPIO_ReadPin(LED_R_GPIO_Port,LED_R_Pin) ? 0:1;
	uint8_t led_g_status = HAL_GPIO_ReadPin(LED_G_GPIO_Port,LED_G_Pin) ? 0:1;
	uint8_t led_b_status = HAL_GPIO_ReadPin(LED_B_GPIO_Port,LED_B_Pin) ? 0:1;
	sprintf(mqtt_message,
	"{\"method\":\"thing.service.property.set\",\"id\":\"181454577\",\"params\":{\
		\"DHT11_Temperature\":%.1f,\
		\"DHT11_Humidity\":%.1f,\
		\"Switch_LEDR\":%d,\
		\"Switch_LEDG\":%d,\
		\"Switch_LEDB\":%d\
	},\"version\":\"1.0.0\"}",
	(float)temperature,
	(float)humidity,
	led_r_status,
	led_g_status,
	led_b_status
	);                        //阿里云数据上报格式~

	MQTT_PublishData(MQTT_PUBLISH_TOPIC,mqtt_message,0);   //
}

字符串处理函数*2

/***********  自定义函数~方便处理str    *******/

char temp_str[30];    // 临时子串

/**从母串中获取与子串长度相等的临时子串*/

void ReadStrUnit(char * str,char *temp_str,int idx,int len)  // 从母串中获取与子串长度相等的临时子串
{
    int index;
    for(index = 0; index < len; index++)
    {
        temp_str[index] = str[idx+index];
    }
    temp_str[index] = '\0';
}

/** 返回子串第一个字符在母串中的位置*/
/** 返回值大于>0 找到了
    返回值小于<0 没找到
*/
int GetSubStrPos(char *str1,char *str2)// 返回子串第一个字符在母串中的位置
{
    int idx = 0;
    int len1 = strlen(str1);
    int len2 = strlen(str2);

    if( len1 < len2)
    {
        //printf("error 1 \n"); // 子串比母串长
        return -1;
    }

    while(1)
    {
        ReadStrUnit(str1,temp_str,idx,len2);    // 不断获取的从 母串的 idx 位置处更新临时子串
        if(strcmp(str2,temp_str)==0)break;      // 若临时子串和子串一致,结束循环
        idx++;                                  // 改变从母串中取临时子串的位置
        if(idx>=len1)return -1;                 // 若 idx 已经超出母串长度,说明母串不包含该子串
    }

    return idx;    // 返回子串第一个字符在母串中的位置
}

处理MQTT下发的消息 ————依据项目修改

data[i]-=‘0’ ASCII转化成数值
data[i]+=‘0’ 数值转化成ASCII

/**** 处理MQTT下发的消息  *********/
/**
data[i]-='0'   ASCII转化成数值
data[i]+='0'   数值转化成ASCII
*/        
				  
//处理MQTT下发的消息
void deal_MQTT_message(uint8_t* buf,uint16_t len)
{
	uint8_t data[512];
	memset(usart1_rxbuf,0,sizeof(usart1_rxbuf));      //清空接收缓冲  
	usart1_rxcounter=0;
	
	//查找关键字
	int i = GetSubStrPos((char*)data,"LEDR");
	if( i>0 )
	{
		uint8_t ledr_status = data[i+6]-'0';      //【ASCII转化成数值的常用方法】
		if(ledr_status)
			HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_RESET);
		else
			HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_SET);
	}
	
}

4.4usart.c

如果想再加个串口2与电脑通信——重写fputc方便调试

#include "stdio.h"

int fputc(int ch,FILE *f)
{
    uint8_t temp[1]={ch};
    HAL_UART_Transmit(&huart2,temp,1,2);
	return 0;
}
  • 44
    点赞
  • 343
    收藏
    觉得还不错? 一键收藏
  • 48
    评论
评论 48
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值