二. 阿里云实战
需要完整代码的在评论区评论邮箱号,看到我都会发的
1.首先我们需要下载模块的AT固件和烧录软件。
百度搜索安可信ESP8266系列模组专题 | 安信可科技
找到如下资料下载
AT固件
烧录软件
2.进行AT指令的烧录
2.硬件链接
和串口连接一样,TX——RX,RX——TX
烧录时我们需要将I0_0口接地
烧录时需要选择
这里文件,选择DOUT,然后选择端口,当出现重新上电时,我们把电源口重新插拔一下,当出现成功时,我们点击start按钮。
出现如下信息时代表烧录成功。
3.打开串口软件。
打开软件前,我们将IO_0口拔掉,然后,重新上一下电。
发送AT指令提示OK时,代表成功了
发送AT+GMR获取版本信息
4.阿里云账号配置
打开阿里云平台
5.串口助手给esp8266指令连接
1.手机开热点
MQTT AT 命令集 - ESP32 - — ESP-AT 用户指南 latest 文档
2.发送如下指令
1.AT 返回 OK
2.AT+RST 复位
3.AT+RESTORE 恢复出厂设置
4.AT+CWMODE=1 设置模式
5.AT+CWJAP="WIFI名字","WIFI密码"
6.AT+CIPSNTPCFG=1,8,"ntp1.aliyun.com" 连接阿里云的网站
7.AT+MQTTUSERCFG=0,1,"NULL",'用户名",“密码”,0,0,""
所有指令可以写为:AT+MQTTUSERCFG=0,1,"NULL","ESP8266&i91j8i57ZEu","b469c005d3a654ffa27e7f56b18aff67dd39106b629e827288566a80bdca3912",0,0,""
8.AT+MQTTCLIENTID=0,"ClienId" 每个逗号前面都加\
AT+MQTTCLIENTID=0,"i91j8i57ZEu.ESP8266|securemode=2\,signmethod=hmacsha256\,timestamp=1677660883354|"
9.AT+MQTTCONN=0,"连接域名",1883,1
AT+MQTTCONN=0,"iot-06z00eies3ymcfm.mqtt.iothub.aliyuncs.com",1883,1
显示在线了
10.AT+MQTTSUB=0,"topoc",1 // 订阅改设备的名字
AT+MQTTSUB=0,"/i91j8i57ZEu/ESP8266/user/get",1
11.AT+MQTTPUB=0,"topic","AJson格式内容",1,0 // 发布 记得改名字
AT+MQTTPUB=0,"/i91j8i57ZEu/ESP8266/user/update","HELLO",1,0
查看消息
12.AT+MQTTCLEAN=0 //关闭云服务
例:
1.AT+RST
2.AT+RESTORE
3.AT+CWMODE=1
4.AT+CWJAP="www","12101210"
5.AT+CIPSNTPCFG=1,8,"ntp1.aliyun.com"
6.AT+MQTTUSERCFG=0,1,"NULL","ESP8266&i91j8i57ZEu","b469c005d3a654ffa27e7f56b18aff67dd39106b629e827288566a80bdca3912",0,0,""
7.AT+MQTTCLIENTID=0,"i91j8i57ZEu.ESP8266|securemode=2\,signmethod=hmacsha256\,timestamp=1677660883354|"
8.AT+MQTTCONN=0,"iot-06z00eies3ymcfm.mqtt.iothub.aliyuncs.com",1883,1
9.AT+MQTTSUB=0,"/i91j8i57ZEu/ESP8266/user/get",1
10.AT+MQTTPUB=0,"/i91j8i57ZEu/ESP8266/user/update","HELLO",1,0
11.AT+MQTTCLEAN=0 //关闭
6.阿里云给ESP8266发送消息
7.STM32给阿里云发送数据
1.STM32CUBEMX配置
先常规配置一下,直接上图
然后我们设置一个灯,我的开发板图图下
所以我的配置如下
串口我们设置2个,配置io口主要看自己板子的口,配置都是默认配置115200
然后我们生成工程,测试一下代码。
添加一下串口重定向功能
#include "stdio.h"
int fputc(int ch,FILE *f)
{ HAL_UART_Transmit (&huart1 ,(uint8_t *)&ch,1,HAL_MAX_DELAY );
return ch;
}
这样我们就可以用printf了
我们测试一下代码
灯和串口都有反应
2.代码编写
我们先用串口连接电脑,等我们调通了,在stm32串口连接ESP8266
接线如下图:
1.代码部分
/* USER CODE BEGIN 2 */
printf("AT+RST\r\n");
HAL_Delay(1000);
printf("AT+RESTORE\r\n");
HAL_Delay(1000);
printf("AT+CWMODE=1\r\n");
HAL_Delay(1000);
printf("AT+CWJAP=\"www\",\"12101210\"\r\n");
HAL_Delay(5000);
HAL_Delay(5000);
printf("AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\n"); //""前面要加'\'
HAL_Delay(1000);
printf("AT+MQTTUSERCFG=0,1,\"NULL\",\"ESP8266&i91j8i57ZEu\",\"b469c005d3a654ffa27e7f56b18aff67dd39106b629e827288566a80bdca3912\",0,0,\"\"\r\n");
HAL_Delay(1000);
printf("AT+MQTTCLIENTID=0,\"i91j8i57ZEu.ESP8266|securemode=2\\,signmethod=hmacsha256\\,timestamp=1677660883354|\"\r\n");
HAL_Delay(1000);
printf("AT+MQTTCONN=0,\"iot-06z00eies3ymcfm.mqtt.iothub.aliyuncs.com\",1883,1\r\n");
HAL_Delay(1000);
printf("AT+MQTTSUB=0,\"/i91j8i57ZEu/ESP8266/user/get\",1\r\n");
HAL_Delay(3000);
printf("AT+MQTTPUB=0,\"/i91j8i57ZEu/ESP8266/user/update\",\"ABC123\",1,0\r\n");
HAL_Delay(3000);
// printf("AT+MQTTCLEAN=0\r\n"); //关闭
// HAL_Delay(2000);
2.效果
成功
3.自动上传温度的数据。
dht11.c文件
/**
*****************************************************************************
* @file dht11.c
* @author
* @version V1.0.0
* @date 2023-02-27
* @brief 温湿度模块
*****************************************************************************
* @history
*
* 1. Date:2023-02-27
* Author:王猛
* Modification:创建文件
*
*****************************************************************************
*/
#include "dht11.h"
uint16_t temperature;
uint16_t humidity;
char temp,humi;
/***********************************************
函数名称:Delay_us
功 能:TIM3定时器实现us级延时
参 数:无
返 回:无
备 注:无
************************************************/
void Delay_us(uint16_t delay)
{
__HAL_TIM_DISABLE(&htim2);
__HAL_TIM_SET_COUNTER(&htim2,0);
__HAL_TIM_ENABLE(&htim2);
uint16_t curCnt=0;
while(1)
{
curCnt=__HAL_TIM_GET_COUNTER(&htim2);
if(curCnt>=delay)
break;
}
__HAL_TIM_DISABLE(&htim2);
}
/***********************************************
函数名称:Dht11_DATA_OUT,Dht11_DATA_IN
功 能:更改DHT11引脚方向
参 数:无
返 回:无
备 注:函数名称:Dht11_DATA_OUT-输出output,Dht11_DATA_IN-// 输入input
************************************************/
void Dht11_DATA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DHT11_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);
}
void Dht11_DATA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pin = DHT11_Pin;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);
}
/***********************************************
函数名称:DHT11_Rst
功 能:DHT11驱动,复位DHT11
参 数:无
返 回:无
备 注:无
************************************************/
void DHT11_Rst(void)
{
Dht11_DATA_OUT(); //设置为输出
DHT11_DQ_OUT_LOW; //拉低引脚
HAL_Delay(20); //延迟20ms
DHT11_DQ_OUT_HIGH; //拉高引脚
Delay_us(30); //延迟30us
}
/***********************************************
函数名称:DHT11_Check
功 能:DHT11驱动,复位DHT11
参 数:无
返 回:无
备 注:无
************************************************/
uint8_t DHT11_Check(void)
{
uint8_t retry=0;
Dht11_DATA_IN(); //设置为输入
while(GPIO_PIN_SET==DHT11_DQ_IN && retry<100)
{
retry++;
Delay_us(1);
}
if(retry>=100)
return 1;
else
retry=0;
while(GPIO_PIN_RESET==DHT11_DQ_IN && retry<100)
{
retry++;
Delay_us(1);
}
if(retry>=100)
return 1;
return 0;
}
/***********************************************
函数名称:DHT11_Read_Bit
功 能:DHT11读取一个位
参 数:无
返 回:1/0
备 注:无
************************************************/
uint8_t DHT11_Read_Bit(void)
{
uint8_t retry=0;
while(GPIO_PIN_SET==DHT11_DQ_IN && retry<100)
{
retry++;
Delay_us(1);
}
retry=0;
while(GPIO_PIN_RESET==DHT11_DQ_IN && retry<100)
{
retry++;
Delay_us(1);
}
Delay_us(40);
if(GPIO_PIN_SET==DHT11_DQ_IN)
return 1;
else
return 0;
}
/***********************************************
函数名称:DHT11_Read_Byte
功 能:从DHT11读取一个字节
参 数:无
返 回:读取到的字节数据(8位)
备 注:无
************************************************/
uint8_t DHT11_Read_Byte(void)
{
uint8_t dat=0;
for(uint8_t i=0;i<8;i++)
{
dat <<= 1;
dat |= DHT11_Read_Bit();
}
return dat;
}
uint8_t buf[5];
/***********************************************
函数名称:DHT11_Read_Data
功 能:从DHT11读取一次数据
参 数:humi:湿度值,temp:温度值
返 回:0代表正常,1代表读取失败
备 注:例:temp:0x1504=0x1504<<8=0x15=21(整数),0x1504&0xff=4(小数),即temp=21.4℃。湿度同理
************************************************/
uint8_t DHT11_Read_Data(uint16_t* temp,uint16_t* humi)
{
DHT11_Rst();
if(DHT11_Check() == 0)
{
for(uint8_t i=0;i<5;i++)
buf[i]=DHT11_Read_Byte();
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=(buf[0]<<8) + buf[1];
*temp=(buf[2]<<8) + buf[3];
}
}
else
return 1;
return 0;
}
dht11.h文件
/**
*****************************************************************************
* @file dht11.h
* @author
* @version V1.0.0
* @date 2023-02-27
* @brief 温湿度模块
*****************************************************************************
* @history
*
* 1. Date:2023-02-27
* Author:王猛
* Modification:创建文件
*
*****************************************************************************
*/
#ifndef __DHT11_H__
#define __DHT11_H__
#include "main.h"
#include "tim.h"
#include "gpio.h"
#include "stm32F4xx_hal.h"
#define DHT11_DQ_OUT_HIGH HAL_GPIO_WritePin(DHT11_GPIO_Port,DHT11_Pin,GPIO_PIN_SET)
#define DHT11_DQ_OUT_LOW HAL_GPIO_WritePin(DHT11_GPIO_Port,DHT11_Pin,GPIO_PIN_RESET)
#define DHT11_DQ_IN HAL_GPIO_ReadPin(DHT11_GPIO_Port,DHT11_Pin)
extern uint16_t temperature;
extern uint16_t humidity;
extern char temp,humi;
void Delay_us(uint16_t delay); //设置数据交互口为输出
void Dht11_DATA_IN(void); //通过TIM3定时器微秒级延时
void Dht11_DATA_OUT(void); //设置数据交互口为输入
void DHT11_Rst(void); //复位DHT11
uint8_t DHT11_Check(void); //DHT11状态反馈
uint8_t DHT11_Read_Bit(void); //读DHT11一位数据
uint8_t DHT11_Read_Byte(void); //读DHT11一字节数据
uint8_t DHT11_Read_Data(uint16_t* temp,uint16_t* humi); //DHT11数据显示
#endif
main.c文件
/* USER CODE BEGIN Includes */
#include "dht11.h"
/* USER CODE END Includes */
/* USER CODE BEGIN 2 */
DHT11_Rst();
while (1)
{
DHT11_Read_Data(&temperature,&humidity);
printf("AT+MQTTPUB=0,\"/i91j8i57ZEu/ESP8266/user/update\",\"temperature=%d.%d,humidity=%d.%d\",1,0\r\n",temperature>>8,temperature&0xff,humidity>>8,humidity&0xff);
HAL_Delay(3000);
实验现象:阿里云接收到stm32下发的命令。
8.阿里云给STM32发送数据
1.硬件连接
2.代码部分
既然是接收阿里云的消息,那么我们需要串口接收。
为了不定长接收,我们可以采用DMA的方式实现不定长接收
main.c中
/* USER CODE BEGIN PV */
uint8_t g_usart_rx_buf[USART_REC_LEN];
uint8_t DMA_FLAG=0;
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//开启串口空闲中断
HAL_UART_Receive_DMA(&huart1,g_usart_rx_buf,sizeof(g_usart_rx_buf));//接收
/* USER CODE END 2 */
whiel(1)
{
if(DMA_FLAG)
{
DMA_FLAG=0;
if(strstr((const char*)g_usart_rx_buf,"on"))
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
}
if(strstr((const char*)g_usart_rx_buf,"off"))
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
}
}
main.h中
/* USER CODE BEGIN ET */
#define USART_REC_LEN 600 /* 定义最大接收字节数 200 */
extern uint8_t g_usart_rx_buf[USART_REC_LEN]; /* 接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 */
extern uint8_t DMA_FLAG; // DMA串口发送
/* USER CODE END ET */
在it.c文件中添加如下代码
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET)//空闲中断,如果获取的不是0的话开启空闲中断
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除空闲中断
HAL_UART_DMAStop(&huart1);//停止DMA的接收,如果没有的话,会保存上一个的数据
uint8_t len=sizeof(g_usart_rx_buf)-__HAL_DMA_GET_COUNTER(huart1.hdmarx);// 实际接收的个数。len=总数-剩余部分的数据
HAL_UART_Receive_DMA(&huart1,g_usart_rx_buf,sizeof(g_usart_rx_buf));
DMA_FLAG=1;
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
开启串口中断后,我们接收到的数据保存到g_usart_rx_buf数组中,接着我们只需要处理一下数据就可以了。
1、strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。
2、找到所搜索的字符串,则该函数返回第一次匹配的字符串的地址;
3、如果未找到所搜索的字符串,则返回NULL。
3.实验结果
在阿里云发送on时,开灯。发送off时,关灯。
9.手机APP发送指令开灯。
esp8266_to_a