stm32远程点灯

发布时间 2023-04-15 23:06:40作者: 浅晓寒

Stm32+ESP8266-01S远程控制LED

接线:

stm32f103c8t6 esp8266-01s
PA2(Usart_TX) RX
PA3(Usart_RX) TX
3.3v 3.3v
GND GND
PC14(可以不接) RST

直接上代码:

esp8266.c

//单片机头文件
#include "stm32f10x.h"

//网络设备驱动
#include "esp8266.h"

//硬件驱动
#include "Delay.h"
#include "usart.h"

//C库
#include <string.h>
#include <stdio.h>

#define ESP8266_WIFI_INFO		"AT+CWJAP=\"wifi名称\",\"密码\"\r\n"
#define ESP8266_MQTT_USERCFG	"AT+MQTTUSERCFG=0,1,\"ESP32\",\"espressif\",\"1234567890\",0,0,\"\"\r\n"
#define ESP8266_MQTT_CONN		"AT+MQTTCONN=0,\"3.228.54.173\",1883,0\r\n"
#define ESP8266_MQTT_SUB1		"AT+MQTTSUB=0,\"主题名\",1\r\n"
#define ESP8266_MQTT_SUB2		"AT+MQTTSUB=0,\"主题名\",1\r\n"

unsigned char esp8266_buf[128];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;
unsigned char LED_Status = 0;

//清空缓存
void ESP8266_Clear(void)
{

	memset(esp8266_buf, 0, sizeof(esp8266_buf));
	esp8266_cnt = 0;

}

//==========================================================
//	函数名称:	ESP8266_WaitRecive
//
//	函数功能:	等待接收完成
//
//	入口参数:	无
//
//	返回参数:	REV_OK-接收完成		REV_WAIT-接收超时未完成
//
//	说明:		循环调用检测是否接收完成
//==========================================================
char ESP8266_WaitRecive(void)
{

	if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕
	{
		esp8266_cnt = 0;							//清0接收计数
			
		return REV_OK;								//返回接收完成标志
	}
		
	esp8266_cntPre = esp8266_cnt;					//置为相同
	
	return REV_WAIT;								//返回接收未完成标志

}

//==========================================================
//	函数名称:	ESP8266_SendCmd
//
//	函数功能:	发送命令
//
//	入口参数:	cmd:命令
//				res:需要检查的返回指令
//
//	返回参数:	0-成功	1-失败
//
//	说明:		
//==========================================================
unsigned char ESP8266_SendCmd(char *cmd, char *res)
{
	
	unsigned char timeOut = 200;

	Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
	
	while(timeOut--)
	{
		if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据
		{
			if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词
			{
				ESP8266_Clear();									//清空缓存
				
				return 0;
			}
		}
		
		delay_ms(10);
	}
	
	return 1;

}

//开关灯
unsigned char GET_SUB(unsigned short timeOut)
{
	do
	{
		if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据
		{
			UsartPrintf(USART_DEBUG, "GET_SUB...\r\n");				//打印到串口助手,用于调试
			UsartPrintf(USART_DEBUG, (char*)esp8266_buf);
			if(strstr((const char *)esp8266_buf, "on") != NULL)		//如果"\"led\":off"是子串,则开灯
			{
				ESP8266_Clear();									//清空缓存
				LED_Status = 1;
				return LED_Status;
			}
			if(strstr((const char *)esp8266_buf, "off") != NULL)		//如果"\"led\":off"是子串,则关灯
			{
				ESP8266_Clear();									//清空缓存
				LED_Status = 0;
				return LED_Status;
			}
		}
		delay_ms(10);
	}while(timeOut--);
	return LED_Status;
}

//主题发布,0:发送成功,1:失败
unsigned char ESP_PUB(char *cmd)
{
	char status = ESP8266_SendCmd(cmd, "SUBRECV");
	delay_ms(200);
    return status;
}


//==========================================================
//	函数名称:	ESP8266_Init
//
//	函数功能:	初始化ESP8266
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_Init(void)
{
	
	GPIO_InitTypeDef GPIO_Initure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

	//ESP8266复位引脚
	GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Initure.GPIO_Pin = GPIO_Pin_14;					//GPIOC14-复位
	GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_Initure);
	
	GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_RESET);
	delay_ms(250);
	GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_SET);
	delay_ms(500);
	
	ESP8266_Clear();
	
	UsartPrintf(USART_DEBUG, "1. RST\r\n");		//向串口1输出信息,串口1通过USB-TTL连接到PC
	while(ESP8266_SendCmd("AT+RST\r\n", "OK"))	//向esp8266发送指令
		delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "2. CWMODE\r\n");
	while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))
		delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\r\n");
	while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))
		delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "4. CWJAP\r\n");
	while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
		delay_ms(500);
	
	//用户信息配置
	UsartPrintf(USART_DEBUG, "5. AT+MQTTUSERCFG\r\n");
	while(ESP8266_SendCmd(ESP8266_MQTT_USERCFG, "OK"))
		delay_ms(500);
	
	//连接MQTT服务器
	UsartPrintf(USART_DEBUG, "6. AT+MQTTCONN\r\n");
	while(ESP8266_SendCmd(ESP8266_MQTT_CONN, "MQTTCONNECTED"))
		delay_ms(500);
	
	//订阅主题1
	UsartPrintf(USART_DEBUG, "7. AT+MQTTSUB1\r\n");
	while(ESP8266_SendCmd(ESP8266_MQTT_SUB1, "OK"))
		delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "8. ESP8266 Init OK\r\n");

}

//==========================================================
//	函数名称:	USART2_IRQHandler
//
//	函数功能:	串口2收发中断
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void USART2_IRQHandler(void)
{

	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收到数据时触发中断
	{
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆
		esp8266_buf[esp8266_cnt++] = USART2->DR;
		
		USART_ClearFlag(USART2, USART_FLAG_RXNE);
	}

}

esp8266.h

#ifndef _ESP8266_H_
#define _ESP8266_H_

#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志

void ESP8266_Init(void);
void ESP8266_Clear(void);
void ESP8266_SendData(unsigned char *data, unsigned short len);
unsigned char ESP_PUB(char *cmd);
unsigned char GET_SUB(unsigned short timeOut);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.H"
#include "LED.h"
#include <stdio.h>
#include "Delay.h"
#include "usart.h"
#include "esp8266.h"
#include "DHT11.h"
#include "Timer.h"
#include <string.h>

char ts[50];
int Temperature;
int Shidu;
uint8_t Lock;
uint8_t Switch2;
extern char RECS[250];
extern char Data[5];	//DHT11数据串
extern unsigned char esp8266_buf[128];
extern unsigned char temp1;
extern unsigned char temp2;
extern unsigned char humi1;
extern unsigned char humi2;

uint16_t cnt;

void Hardware_Init(void)
{
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断控制器分组设置
	LED_Init();
	ESP8266_Init();
	Usart1_Init(115200);							//串口1,打印信息用
	Usart2_Init(115200);							//串口2,驱动ESP8266用
	UsartPrintf(USART_DEBUG, " Hardware init OK\r\n");
}

int main(void)
{
	Hardware_Init();	
	while(1)
	{
		if(GET_SUB(0))
			LED1_ON();
		else
			LED1_OFF();
	}
}


使用APP连接MQTT服务器,和单片机订阅同一个topic后,向MQTT服务器发送一个json格式的字符串{"led":"on"}或者{"led":"off"},当APP向上传主题时,esp-01s接收到数据,通过串口通信向stm32的串口发送消息实现led的远程开和关。