本文以Clion作为编译器,STM32F407作为芯片,通过串口以AT指令与ESP8266-01S进行通信,让其连接到腾讯云物联网平台。
一、ESP8266-01S
ESP8266-01S原本固件是不支持MQTT的,因此需要在安信可官网去下载MQTT透传AT固件。AT固件汇总
再通过固件烧录工具将适用于ESP8266-01S的MQTT固件下载进其中。将ESP8266-01S进行上电测试,输入AT指令,有返回OK,说明此时ESP8266-01S是用的。
二、STM32CubeMx的配置
1.时钟树
2.RCC、SYS、Project Name…(略)
3.USART1、USART6
USART1选择异步通信方式,其余默认
USART6选择异步通信方式,打开更新中断,设置DMA,其余默认
4设置引脚
USART6_Rx默认PC7改为PG14
USART6_Tx默认PC6改为PG9
将PE2、PE3设置为GPIO输出
STM32 |
ESP8266 |
3.3V |
VCC |
GND |
GND |
PE2 |
EN |
PE3 |
RST |
Rx |
PG14 |
Tx |
PG9 |
5 设置TIM8定时器
三、STM32程序
1. usart.c
/* USER CODE BEGIN 1 */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE {
HAL_UART_Transmit(&huart1, (uint8_t *) &ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 1 */
usart.h 文件中加入:
#include "stdio.h"
2.stm32f4xx_it.c
#define BUFFER_SIZE 1024
uint8_t rx_len;
uint8_t recv_end_flag;
uint8_t usart6_rxbuf[1024];
void USART6_IRQHandler(void) {
/* USER CODE BEGIN USART6_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
recv_end_flag = 0;
tmp_flag = __HAL_UART_GET_FLAG(&huart6, UART_FLAG_IDLE);
if ((tmp_flag != 0)) {
__HAL_UART_CLEAR_IDLEFLAG(&huart6);
HAL_UART_DMAStop(&huart6);
temp = hdma_usart6_rx.Instance->NDTR;
rx_len = BUFFER_SIZE - temp;
recv_end_flag = 1;
uint8_t i;
for (i = 0; i < 250; i++)
{
esp_rxbuf[i] = usart6_rxbuf[i];
}
printf("\r\n◇:%s \r\n", usart6_rxbuf);
memset(&usart6_rxbuf, 0, sizeof(usart6_rxbuf));
HAL_UART_Receive_DMA(&huart6, usart6_rxbuf, BUFFER_SIZE);
}
/* USER CODE END USART6_IRQn 0 */
HAL_UART_IRQHandler(&huart6);
/* USER CODE BEGIN USART6_IRQn 1 */
/* USER CODE END USART6_IRQn 1 */
}
}
3.创建ESP8266.c.h文件
ESP8266.c
#include "Esp8266.h"
#include "stdio.h"
#include "usart.h"
#include "string.h"
#include "Time.h"
uint8_t send_device_buf[1024];
uint8_t esp_rxbuf[1024]; //ESP数据接收缓冲区
uint8_t esp_wxbuf[1024]; //ESP数据发送缓冲区
EspCode Esp_One;
extern float Temperature, Distance;
unsigned int mqttPacketLen = 0;
float Temperature = 9, Distance = 8;
void ESP_Connect_Server() {
ESP_Init();
ESP8266_Connect_Wifi(Esp_One.WIFI_NAME, Esp_One.WIFI_PASSWORD);
ESP_Mqtt_Connection(Esp_One.ClientID, Esp_One.UserName, Esp_One.PassWord);
ESP_CONNECT_SERVER(Esp_One.ServerIP, Esp_One.Port);
ESP_Mqtt_Subscribe(Esp_One.Topic);
ESP_Send_Data(Esp_One.TopicPost);
}
void ESP_Init() {
ESP_RST_Pin_SetH;
ESP_CH_PD_Pin_SetH;
Esp_One.WIFI_NAME = "要连接的WIFI名";
Esp_One.WIFI_PASSWORD = "要连接的WIFI密码";
Esp_One.ServerIP = "U9849JAYEY.iotcloud.tencentdevices.com";
Esp_One.Port = "1883";
Esp_One.ClientID = "客户端ID";
Esp_One.UserName = "用户名";
Esp_One.PassWord = "用户密码";
Esp_One.Topic = "$thing/down/property/客户端ID/项目名";
Esp_One.TopicPost = "$thing/up/property/客户端ID/项目名";
printf("ESP_Init_Success\r\n");
}
uint8_t ESP8266_Connect_Wifi(char *WIFI_NAME, char *WIFI_PASSWORD) {
int Ti = 1;
memset(esp_rxbuf, 0, sizeof(esp_rxbuf));
memset(&send_device_buf, 0, sizeof(send_device_buf));
sprintf((char *) send_device_buf, "AT+CWMODE=3\r\n");//设置为STA和AP模式
HAL_UART_Transmit(ESP_UART, send_device_buf, strlen((const char *) send_device_buf), 100);
HAL_Delay(1000);
memset(&send_device_buf, 0, sizeof(send_device_buf));
sprintf((char *) send_device_buf, "AT+CWJAP=\"%s\",\"%s\"\r\n", WIFI_NAME, WIFI_PASSWORD);
HAL_UART_Transmit(ESP_UART, send_device_buf, strlen((const char *) send_device_buf), 100); //输入路由ssid和密码
HAL_Delay(1000);
Set_TimeC_value(60);
while (Ti) {
if (Time_C == 0) {
Ti = 0;
}
if (strstr((const char *) esp_rxbuf, "FAIL") != NULL ||
strstr((const char *) esp_rxbuf, "ERROR") != NULL) //如果检索到关键词
{
HAL_Delay(1000);
memset(&send_device_buf, 0, sizeof(send_device_buf));
sprintf((char *) send_device_buf, "AT+CWJAP=\"%s\",\"%s\"\r\n", WIFI_NAME, WIFI_PASSWORD);
HAL_UART_Transmit(ESP_UART, send_device_buf, strlen((const char *) send_device_buf), 100); //输入路由ssid和密码
}
if (strstr((const char *) esp_rxbuf, "WIFI GOT IP") != NULL) //如果检索到关键词
{
printf("WIFI_Connect_Succeeded\r\n");
break;
}
}
}
uint8_t ESP_Mqtt_Connection(char *ClientID, char *UserName, char *PassWord) {
int Ti = 1;
memset(esp_rxbuf, 0, sizeof(esp_rxbuf));
Set_TimeC_value(30);
while (Ti) {
if (Time_C == 0) {
Ti = 0;
}
HAL_Delay(1000);
if (strstr((const char *) esp_rxbuf, "OK") != NULL) //如果检索到关键词
{
return 0;
} else {
memset(send_device_buf, 0, 200);
sprintf((char *) send_device_buf,
"AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n", ClientID, UserName, PassWord);
HAL_UART_Transmit(ESP_UART, send_device_buf, strlen((const char *) send_device_buf), 1000);
}
}
return 1;
}
uint8_t ESP_CONNECT_SERVER(uint8_t *ServerIP, uint8_t *Port) {
int Ti = 1;
memset(esp_rxbuf, 0, sizeof(esp_rxbuf));
Set_TimeC_value(30);
while (Ti) {
if (Time_C == 0) {
Ti = 0;
}
HAL_Delay(1000);
if (strstr((const char *) esp_rxbuf, "OK") != NULL) //如果检索到关键词
{
return 0;
} else {
memset(send_device_buf, 0, sizeof(send_device_buf));
sprintf((char *) send_device_buf, "AT+MQTTCONN=0,\"%s\",%s,1\r\n", ServerIP, Port);
HAL_UART_Transmit(ESP_UART, send_device_buf, strlen((const char *) send_device_buf), 1000);
}
}
return 1;
}
uint8_t ESP_Mqtt_Subscribe(char *Topic) {//订阅
int Ti = 1;
memset(esp_rxbuf, 0, sizeof(esp_rxbuf));
Set_TimeC_value(3);
while (Ti) {
if (Time_C == 0) {
Ti = 0;
}
HAL_Delay(1000);
if (strstr((const char *) esp_rxbuf, "OK") !=
NULL) //如果检索到关键词
{
return 0;
} else {
memset(send_device_buf, 0, sizeof(send_device_buf));
sprintf((char *) send_device_buf, "AT+MQTTSUB=0,\"%s\",0\r\n", Topic);
HAL_UART_Transmit(ESP_UART, send_device_buf, strlen((const char *) send_device_buf), 1000);
}
}
return 1;
}
uint8_t ESP_Send_Data(char *TopicPost) {
int Ti = 1;
memset(esp_rxbuf, 0, sizeof(esp_rxbuf));
Set_TimeC_value(10);
while (Ti) {
if (Time_C == 0) {
Ti = 0;
}
HAL_Delay(1000);
if (strstr((const char *) esp_rxbuf, "{\"method\":\"report_reply\",\"code\":0,\"status\":\"success\"}") !=
NULL) //如果检索到关键词
{
return 0;
} else {
memset(send_device_buf, 0, sizeof(send_device_buf));
sprintf((char *) send_device_buf,
"AT+MQTTPUB=0,\"%s\",\"{\\\"method\\\":\\\"report\\\"\\,\\\"params\\\":{\\\"Temperature\\\":%.2f\\,\\\"Distance\\\":%.2f}}\",0,0\r\n",
TopicPost, Temperature, Distance);
HAL_UART_Transmit(ESP_UART, send_device_buf, strlen((const char *) send_device_buf), 1000);
}
}
return 1;
}
uint8_t ESP_DisConnect() {
int Ti = 1;
memset(esp_rxbuf, 0, sizeof(esp_rxbuf));
Set_TimeC_value(10);
while (Ti) {
if (Time_C == 0) {
Ti = 0;
}
HAL_Delay(1000);
if (strstr((const char *) esp_rxbuf, "OK") !=
NULL) //如果检索到关键词
{
return 0;
} else {
memset(send_device_buf, 0, sizeof(send_device_buf));
sprintf((char *) send_device_buf,
"AT+MQTTCLEAN=0\r\n");
HAL_UART_Transmit(ESP_UART, send_device_buf, strlen((const char *) send_device_buf), 1000);
}
}
return 1;
}
ESP8266.h
#ifndef __ESP8266_H__
#define __ESP8266_H__
#include "main.h"
#define ESP_RST_Pin_SetH HAL_GPIO_WritePin(GPIOE,GPIO_PIN_3,GPIO_PIN_SET)
#define ESP_RST_Pin_SetL HAL_GPIO_WritePin(GPIOE,GPIO_PIN_3,GPIO_PIN_RESET)
#define ESP_CH_PD_Pin_SetH HAL_GPIO_WritePin(GPIOE,GPIO_PIN_2,GPIO_PIN_SET)
#define ESP_CH_PD_Pin_SetL HAL_GPIO_WritePin(GPIOE,GPIO_PIN_2,GPIO_PIN_RESET)
extern uint8_t send_device_buf[1024];
extern uint8_t esp_rxbuf[1024]; //ESP数据接收缓冲区
extern uint8_t esp_wxbuf[1024]; //ESP数据发送缓冲区
#define ESP_UART &huart6
typedef struct _EspCode {
char *WIFI_NAME;
char *WIFI_PASSWORD;
uint8_t *ServerIP;
uint8_t *Port;
char *UserName;
char *PassWord;
char *ClientID;
char *Topic;
char *TopicPost;
} EspCode;
extern EspCode Esp_One;
void ESP_Init(void);
uint8_t ESP8266_Connect_Wifi(char *WIFI_NAME, char *WIFI_PASSWORD);
uint8_t ESP_CONNECT_SERVER(uint8_t *ServerIP, uint8_t *Port);
uint8_t ESP_Mqtt_Connection(char *ClientID, char *UserName, char *PassWord);
void ESP_Connect_Server();
uint8_t ESP_Mqtt_Subscribe(char *Topic);
uint8_t ESP_Send_Data(char *TopicPost);
#endif
4.创建Time.c/.h文件
Time.c
#include "Time.h"
#include "tim.h"
int Time_C = 0;
void Set_TimeC_value(int value) {
Time_C = value;
HAL_TIM_Base_Start_IT(&htim8);
if (Time_C == 0) {
HAL_TIM_Base_Stop_IT(&htim8);
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器回调函数,用于计算速度
{
if (htim->Instance == TIM8) {
Time_C--;
if (Time_C <= 0) {
Time_C = 0;
}
}
}
Time.h
#ifndef F407_BLANCE_CAR_TIME_H
#define F407_BLANCE_CAR_TIME_H
#include "main.h"
extern int Time_C;
void Set_TimeC_value(int value);
#endif
5.main.c
#define BUFFER_SIZE 1024
extern uint8_t usart6_rxbuf[1024];
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_USART6_UART_Init();
MX_TIM8_Init();
/* USER CODE BEGIN 2 */
__HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);//使能IDLE线检测中断
HAL_UART_Receive_DMA(&huart6, usart6_rxbuf, BUFFER_SIZE);
HAL_TIM_Base_Stop_IT(&htim8);
ESP_Connect_Server();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
四、结果
上下行数据皆成功
总结
使用ESP8266-01S的MQTT固件连接腾讯云物联网平台,简单数据上下行的应用。