stm32远程点灯
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,\"MQTT客户端id\",\"用户名\",\"密码\",0,0,\"\"\r\n"
#define ESP8266_MQTT_CONN "AT+MQTTCONN=0,\"broker.emqx.io\",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的远程开和关。