ESP01S.h
#ifndef ESP01S_H
#define ESP01S_H
#include "stm32f10x.h"
#define ESP_BUFFER_SIZE 1024 // 接收缓冲区大小
#define USART2_BAUDRATE 115200 // 串口波特率
void ESP01S_Init(void);
void ESP01S_Send_ATCmd(char *cmd);
void ESP01S_Clear_DataBuffer(void);
unsigned char ESP01S_Get_RECDataFlag(void);
void ESP01S_Get_RECData(char result[ESP_BUFFER_SIZE]);
#endif
ESP01S.c
#include "ESP01S.h"
unsigned char RecTempByte; // 临时存储接收到的字节
unsigned char ESP_RECBuffer[ESP_BUFFER_SIZE]; // 接收缓冲区
int Buffer_Num = 0; // 接收缓冲区索引
/**
* 初始化USART2
* @note TXD=PA2, RXD=PA3, 波特率:115200
*/
void ESP01S_Init(void)
{
// 开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// GPIO初始化
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); // PA2配置为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure); // PA3配置为上拉输入
// USART2初始化
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = USART2_BAUDRATE;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART2, &USART_InitStructure);
// 配置中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
// 配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
// 使能USART2
USART_Cmd(USART2, ENABLE);
}
/**
* 发送单个字节
* @param Byte:要发送的字节
*/
void ESP01S_SendByte(unsigned char Byte)
{
USART_SendData(USART2, Byte);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); // 等待发送完成
}
/**
* 发送AT指令
* @param cmd:AT指令字符串
*/
void ESP01S_Send_ATCmd(char *cmd)
{
while (*cmd != '\0')
{
ESP01S_SendByte(*cmd++);
}
}
/**
* 清空接收缓冲区
*/
void ESP01S_Clear_DataBuffer(void)
{
Buffer_Num = 0;
}
/**
* 检查是否接收到数据
* @return 0:无数据,1:有数据
*/
unsigned char ESP01S_Get_RECDataFlag(void)
{
return Buffer_Num > 0 ? 1 : 0;
}
/**
* 获取接收数据
* @param result:存储接收数据的数组
*/
void ESP01S_Get_RECData(char result[ESP_BUFFER_SIZE])
{
int i;
for (i = 0; i < Buffer_Num && i < ESP_BUFFER_SIZE; i++)
{
result[i] = ESP_RECBuffer[i];
}
result[i] = '\0'; // 添加字符串结束符
ESP01S_Clear_DataBuffer(); // 清空缓冲区
}
/**
* USART2中断处理函数
*/
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
{
RecTempByte = USART_ReceiveData(USART2); // 读取接收到的数据
if (Buffer_Num < ESP_BUFFER_SIZE)
{
ESP_RECBuffer[Buffer_Num++] = RecTempByte; // 存储到缓冲区
}
else
{
// 缓冲区溢出保护
Buffer_Num = ESP_BUFFER_SIZE; // 防止溢出
}
USART_ClearITPendingBit(USART2, USART_IT_RXNE); // 清除中断标志位
}
}
说明
使用的是安可信的AT固件
ESP01S_AT_CMD.h
#ifndef ESP01S_ATCMD_H_
#define ESP01S_ATCMD_H_
#include "ESP01S.h"
#define ESP01S_TIMEOUT 5000 // 重启命令的超时时间(毫秒)
int ESP_AT_RST(void);
int ESP_AT_Get_WIFI_Name(char *wifiname);
int ESP_AT_Link_WIFI(char *wifiname, char *wifipwd);
int ESP_AT_Exit_WIFI(void);
int ESP_AT_Get_IP(char *cmd);
#endif
ESP01S_AT_CMD.c
#include "ESP01S_AT_CMD.h"
#include "Delay.h"
#include <stdio.h>
#include <string.h>
/**
* 重启 ESP01S 模块
*
* 发送 `AT+RST` 命令以重启模块,并检查返回的 `OK` 以确认重启成功。
*
* @return 1:重启成功,0:重启失败
*/
int ESP_AT_RST(void) {
unsigned char result = 0; // 初始化结果为失败
char response[ESP_BUFFER_SIZE]; // 用于存储模块返回的数据
// 清空接收缓冲区
ESP01S_Clear_DataBuffer();
// 发送重启命令
ESP01S_Send_ATCmd("AT+RST\r\n");
// 等待模块响应
Delay_s(1);
// 再次清空缓冲区,确保之前的响应被清空
ESP01S_Clear_DataBuffer();
// 发送测试命令以检查模块是否重启成功
ESP01S_Send_ATCmd("AT\r\n");
// 等待模块响应
Delay_ms(500);
// 检查是否有返回数据
if (ESP01S_Get_RECDataFlag()) {
ESP01S_Get_RECData(response); // 获取返回数据
if (strstr(response, "OK") != NULL) {
result = 1; // 如果包含 "OK",则重启成功
}
}
return result; // 返回重启结果
}
/**
* 获取当前连接的 WiFi 网络名称(SSID)
*
* 发送 `AT+CWJAP?` 命令以获取当前连接的 WiFi 信息,并解析返回的 SSID。
*
* @param wifiname 用于存储 WiFi 名称的字符串
* @return 1:成功获取 WiFi 名称,0:失败
*/
int ESP_AT_Get_WIFI_Name(char *wifiname) {
unsigned char result = 0; // 初始化结果为失败
char response[ESP_BUFFER_SIZE]; // 用于存储模块返回的数据
// 清空接收缓冲区
ESP01S_Clear_DataBuffer();
// 发送命令
ESP01S_Send_ATCmd("AT+CWJAP?\r\n");
// 等待模块响应
Delay_ms(100);
// 检查是否有返回数据
if (ESP01S_Get_RECDataFlag()) {
ESP01S_Get_RECData(response); // 获取返回数据
// 检查是否包含 WiFi 信息
if (strstr(response, "+CWJAP:") != NULL) {
// 解析 WiFi 名称
char *start = strstr(response, "+CWJAP:\"") + 8; // 找到 "+CWJAP:" 后的位置
if (start != NULL) {
char *end = strchr(start, '"'); // 找到第一个结束引号位置
if (end != NULL) {
*end = '\0'; // 将结束引号替换为字符串结束符
strcpy(wifiname, start); // 复制 WiFi 名称到 wifiname
result = 1; // 获取成功
}
}
} else if (strstr(response, "ERROR") != NULL) {
result = 0; // 如果返回 "ERROR",则获取失败
}
}
return result;
}
/**
* 连接到指定的 WiFi 网络
*
* 发送 `AT+CWJAP=<ssid>,<pwd>` 命令以连接到指定的 WiFi 网络,并检查返回的 `WIFI CONNECTED` 以确认连接成功。
*
* @param wifiname WiFi 名称(SSID)
* @param wifipwd WiFi 密码
* @return 1:连接成功,0:连接失败
*/
int ESP_AT_Link_WIFI(char *wifiname, char *wifipwd) {
char cmd[128]; // 用于存储 AT 命令的缓冲区
char response[ESP_BUFFER_SIZE]; // 用于存储模块返回的数据
// 清空接收缓冲区
ESP01S_Clear_DataBuffer();
// 构造 AT+CWJAP 命令
sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", wifiname, wifipwd);
// 发送连接命令
ESP01S_Send_ATCmd(cmd);
// 等待模块响应
Delay_s(5);
// 检查是否有返回数据
if (ESP01S_Get_RECDataFlag()) {
ESP01S_Get_RECData(response); // 获取返回数据
// 检查是否连接成功
if (strstr(response, "WIFI CONNECTED") != NULL) {
return 1; // 如果返回 "WIFI CONNECTED",则连接成功
} else if (strstr(response, "ERROR") != NULL || strstr(response, "FAIL") != NULL) {
return 0; // 如果返回 "ERROR" 或 "FAIL",则连接失败
}
}
return 0; // 如果超时仍未连接成功,返回失败
}
/**
* 断开当前连接的 WiFi 网络
*
* 发送 `AT+CWQAP` 命令以断开当前连接的 WiFi,并检查返回的 `WIFI DISCONNECT` 或 `OK` 以确认断开成功。
*
* @return 1:断开成功,0:断开失败
*/
int ESP_AT_Exit_WIFI(void) {
unsigned char result = 0; // 初始化结果为失败
char response[ESP_BUFFER_SIZE]; // 用于存储模块返回的数据
// 清空接收缓冲区
ESP01S_Clear_DataBuffer();
// 发送断开命令
ESP01S_Send_ATCmd("AT+CWQAP\r\n");
// 等待模块响应
Delay_ms(100);
// 检查是否有返回数据
if (ESP01S_Get_RECDataFlag()) {
ESP01S_Get_RECData(response); // 获取返回数据
// 检查是否断开成功
if (strstr(response, "WIFI DISCONNECT") != NULL || strstr(response, "OK") != NULL) {
result = 1; // 如果返回 "WIFI DISCONNECT" 或 "OK",则断开成功
} else if (strstr(response, "ERROR") != NULL) {
result = 0; // 如果返回 "ERROR",则断开失败
}
}
return result;
}
/**
* 获取模块的 IP 地址
*
* 发送 `AT+CIFSR` 命令以获取模块的 IP 地址,并解析返回的 `STAIP` 以确认获取成功。
*
* @param RES_IP 用于存储获取到的 IP 地址的字符串
* @return 1:成功获取 IP 地址,2:未连接 WiFi,0:失败
*/
int ESP_AT_Get_IP(char *RES_IP) {
unsigned char result = 0; // 初始化结果为失败
char response[ESP_BUFFER_SIZE]; // 用于存储模块返回的数据
// 清空接收缓冲区
ESP01S_Clear_DataBuffer();
// 发送获取 IP 地址的命令
ESP01S_Send_ATCmd("AT+CIFSR\r\n");
// 等待模块响应
Delay_ms(100);
// 检查是否有返回数据
if (ESP01S_Get_RECDataFlag()) {
ESP01S_Get_RECData(response); // 获取返回数据
// 检查是否包含 STAIP
if (strstr(response, "STAIP") != NULL) {
// 解析 IP 地址
char *start = strstr(response, "STAIP,\"") + 7; // 找到 "STAIP," 后的引号位置
if (start != NULL) {
char *end = strchr(start, '"'); // 找到结束引号位置
if (end != NULL) {
*end = '\0'; // 将结束引号替换为字符串结束符
strcpy(RES_IP, start); // 复制 IP 地址到 RES_IP
// 检查是否为 0.0.0.0
if (strcmp(RES_IP, "0.0.0.0") == 0) {
result = 2; // 未连接 WiFi
} else {
result = 1; // 获取成功
}
}
}
}
}
return result; // 返回结果
}