
一、适用场景
适用场景:给 STM32 或其它 MCU 添加 Wi-Fi(数据上报、OTA、远程控制、MQTT、HTTP/REST、Web 控制面板);或将 ESP8266 作为独立微控制器(NodeMCU/Arduino 栈)快速做物联网原型、Wi-Fi 网关、局域网 Web 服务器与 Wi-Fi → 串口透传桥。
二、器材清单
ESP8266 模块(ESP-01)×1
若干杜邦线(母对母/母对公)×1组
stm32f103(或其它 STM32)开发板 ×1
三、工作原理(要点)
ESP8266 是集成了 Wi-Fi 协议栈的低成本 SoC,既可作 Wi-Fi 外围(通过 AT 固件用串口控制),也可单独作为主 MCU(烧入 NodeMCU/Arduino/ESP-IDF 程序运行)。常见和稳定的交互方式有:
AT 固件 + STM32 UART:STM32 用串口发 AT 指令控制 ESP8266 做 STA/AP、TCP/UDP、MQTT 等。
设备模式指令

AP模式指令

ESP 自主运行(Arduino/ESP-IDF/NodeMCU):直接在 ESP8266 上编写逻辑并连接传感器/执行器(适合快速原型)。
四、接线示意(以 ESP-01 为例)
VCC → 3.3V 稳定电源(注意不是 5V)
GND → GND(与 MCU 共地)
HAL库/标准库
PB10 → TX(模块)
PB11 → RX(模块)
- 示例代码
标准库
设备模式
cpp
/**
******************************************************************************
* @file bsp_usart.c
* @author fire
* @version V1.0
* @date 2013-xx-xx
* @brief 重定向c库printf函数到usart端口
******************************************************************************
* @attention
*
* 实验平台:野火STM32 F103-指南者 开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :https://fire-stm32.taobao.com
*
******************************************************************************
*/
#include "bsp_usart.h"
#include "bsp_SysTick.h"
#include "stdio.h"
#include "stm32f10x.h"
#include <string.h>
#define newRESET "AT+RST\r\n"//重启模块指令
int oknum=0,flagnum=0,lednum=0;
char buffer[12],buffer1[12],show1[20];
int AT_OK_Flag = 0; //OK返回值的标志位
int AT_Connect_Net_Flag = 0; //WIFI GOT IP返回值的标志位
/**
* @brief 配置嵌套向量中断控制器NVIC
* @param 无
* @retval 无
*/
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
static void NVIC_Configuration1(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ1;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief USART GPIO 配置,工作参数配置
* @param 无
* @retval 无
*/
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打开串口GPIO的时钟
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
// 打开串口外设的时钟
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No ;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(DEBUG_USARTx, &USART_InitStructure);
// 串口中断优先级配置
NVIC_Configuration();
// 使能串口接收中断
USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
// 使能串口
USART_Cmd(DEBUG_USARTx, ENABLE);
}
void USART_Config1(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打开串口GPIO的时钟
DEBUG_USART_GPIO_APBxClkCmd1(DEBUG_USART_GPIO_CLK1, ENABLE);
// 打开串口外设的时钟
DEBUG_USART_APBxClkCmd1(DEBUG_USART_CLK1, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT1, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT1, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE1;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No ;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(DEBUG_USARTx1, &USART_InitStructure);
// 串口中断优先级配置
NVIC_Configuration1();
// 使能串口接收中断
USART_ITConfig(DEBUG_USARTx1, USART_IT_RXNE, ENABLE);
// 使能串口
USART_Cmd(DEBUG_USARTx1, ENABLE);
}
/***************** 发送一个字节 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到USART */
USART_SendData(pUSARTx,ch);
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
/****************** 发送8位的数组 ************************/
void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
{
uint8_t i;
for(i=0; i<num; i++)
{
/* 发送一个字节数据到USART */
Usart_SendByte(pUSARTx,array[i]);
}
/* 等待发送完成 */
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}
/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
do
{
Usart_SendByte( pUSARTx, *(str + k) );
k++;
} while(*(str + k)!='\0');
/* 等待发送完成 */
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
{}
}
/***************** 发送一个16位数 **********************/
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
uint8_t temp_h, temp_l;
/* 取出高八位 */
temp_h = (ch&0XFF00)>>8;
/* 取出低八位 */
temp_l = ch&0XFF;
/* 发送高八位 */
USART_SendData(pUSARTx,temp_h);
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
/* 发送低八位 */
USART_SendData(pUSARTx,temp_l);
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
void USART2_IRQHandler( void )
{
static int i = 0;//静态变量,被初始化一次
uint8_t tmp;
char *ret,*ret2,*ret3;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
tmp = USART_ReceiveData(USART2);
Usart_SendByte(USART1,tmp);//打印从esp-01s接收到的数据
// if((tmp == 'W' || tmp == 'O' || tmp == 'L')&& first==1){
if(tmp == 'W' || tmp == 'O'|| tmp == 'L'){
ret = strchr(buffer,'W');
ret2 = strchr(buffer,'O');
ret3 = strchr(buffer,'L');
if((ret!=NULL)||(ret2!=NULL)||(ret3!=NULL))//防止前面有识别到时后面有出现关键字符,如WOFI_G,因为它识别到关键字符时会清零,所以要避开这种情况
{
}else
i = 0;
}
buffer[i++] = tmp;
if(i>=3)//判断是否是ok
{
if(buffer[0] == 'O' && buffer[1] == 'K'){
AT_OK_Flag = 1;
oknum=flagnum=lednum=0;//如果出现关键字符,清除其标志位
memset(buffer, '\0', 12);
i = 0;
}else
oknum=1;//非ok标志位
//灯控指令
if(buffer[0] == 'L' && buffer[2] == '1'){
GPIO_ResetBits(GPIOE,GPIO_Pin_1);//点亮D5
oknum=flagnum=lednum=0;
memset(buffer, '\0', 12);
}else if(buffer[0] == 'L' && buffer[2] == '0'){
GPIO_SetBits(GPIOE,GPIO_Pin_1);//熄灭D5
oknum=flagnum=lednum=0;
memset(buffer, '\0', 12);
}else{
lednum=1;
}
}
if(i>=7)
{
if(buffer[0] == 'W' && buffer[5] == 'G'){//入网成功的判断依据WIFI GOT IP
AT_Connect_Net_Flag = 1;
oknum=flagnum=lednum=0;
memset(buffer, '\0', 12);
i = 0;
}else
flagnum=1;//非WIFI GOT IP标志位
}
if(oknum==1 && flagnum==1 && lednum==1)//非关键字符串处理
{
i = 0;
oknum=flagnum=lednum=0;
memset(buffer, '\0', 12);
}
//联网失败出现FAIL字样捕获
// if(buffer[0] == 'F' && buffer[1] == 'A'){
// for(i=0;i<5;i++){
// GPIO_ResetBits(GPIOD,GPIO_Pin_3);
// Delay_us(1000000);
// GPIO_SetBits(GPIOD,GPIO_Pin_3);
// Delay_us(1000000);
// }
// Usart_SendString(USART1,newRESET);
// memset(buffer, '\0', 12);
// }
if(i == 12)//超出缓冲区上限处理,虽然实际上不太可能出现这种情况
{
i = 0;
oknum=flagnum=lednum=0;
memset(buffer, '\0', 12);
}
}
}
void USART1_IRQHandler( void )
{
static int j = 0;//静态变量,被初始化一次
uint8_t tmp;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
}
}
#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "bsp_usart.h"
extern char buffer[12];
#define LJWL "AT+CWJAP=\"ART\",\"19181716\"\r\n" //联网指令
#define LRST "AT+RST\r\n" //重启指令
#define LJFWQ "AT+CIPSTART=\"TCP\",\"192.168.43.17\",8880\r\n" //连接服务器指令
#define TCMS "AT+CIPMODE=1\r\n" //透传指令
#define SJCS "AT+CIPSEND\r\n" //数据传输开始指令
extern int AT_OK_Flag; //OK返回值的标志位
extern int AT_Connect_Net_Flag; //WIFI GOT IP返回值的标志位
int main()
{
int i;
SysTick_Init();
USART_Config();
USART_Config1();
Usart_SendString(USART1,"TIMEWAIT\r\n");//等待esp-01s上电的初始化
Delay_us(10000000);
Usart_SendString(USART1,"TIMEWAITOK\r\n");
// Usart_SendString(USART1,LJWL);//发送联网AT指令并等待成功,由于已经连过网了,所以这里指令就算发出去受到的也是error,没什么意义
AT_Connect_Net_Flag=0;//提前清除标志位,因为本身上电后就会有很多初始化的数据过来,防止这些数据误触发了标志位
Usart_SendString(USART2,LRST);
while(!AT_Connect_Net_Flag);
Delay_us(500000);//最好加上防止指令过快
Usart_SendString(USART1,"20%\r\n");//查看当前联网进度
AT_OK_Flag=0;
Usart_SendString(USART2,LJFWQ);//发送连服务器指令并等待成功
while(!AT_OK_Flag);
AT_OK_Flag = 0;
Delay_us(500000);
Usart_SendString(USART1,"40%\r\n");
AT_OK_Flag=0;
Usart_SendString(USART2,TCMS);//发送透传模式指令并等待成功
while(!AT_OK_Flag);
AT_OK_Flag = 0;
Delay_us(500000);
Usart_SendString(USART1,"60%\r\n");
AT_OK_Flag=0;
Usart_SendString(USART2,SJCS);//发送数据传输指令并等待成功
Delay_us(500000);
while(!AT_OK_Flag);
if(AT_Connect_Net_Flag){
GPIO_ResetBits(GPIOD,GPIO_Pin_3);
}
if(AT_OK_Flag){
GPIO_ResetBits(GPIOD,GPIO_Pin_2);//点亮D6,代表连接服务器并打开透传模式成功
}
Usart_SendString(USART1,"85%\r\n");
Usart_SendString(USART1,"100%\r\n");
while(1){
Delay_us(1500000);
//"心跳包"
Usart_SendString(USART2,"xiaoliu shuai\r\n");
}
}
AP模式
cpp
#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "bsp_usart.h"
extern char buffer[12];
#define LJWL "AT+CWMODE=3\r\n" //工作在路由模式
#define LRST "AT+CIPMUX=1\r\n" //使能多链接
#define LJFWQ "AT+CIPSERVER=1\r\n" //建立tcp服务器
#define TCMS "AT+CIPSEND=0,6\r\n" //发送数据
//#define SJCS "AT+CIPSEND\r\n" //数据传输开始指令
extern int AT_OK_Flag; //OK返回值的标志位
extern int AT_Clicent; //WIFI GOT IP返回值的标志位
int main()
{
int i;
SysTick_Init();
USART_Config();
USART_Config1();
Usart_SendString(USART1,"TIMEWAIT\r\n");//等待esp-01s上电的初始化
Delay_us(10000000);
Usart_SendString(USART1,"20%\r\n");
AT_OK_Flag=0;
Usart_SendString(USART2,LJWL);//发送透传模式指令并等待成功
while(!AT_OK_Flag);
AT_OK_Flag = 0;
Delay_us(500000);
Usart_SendString(USART1,"40%\r\n");
AT_OK_Flag=0;
Usart_SendString(USART2,LRST);//发送透传模式指令并等待成功
while(!AT_OK_Flag);
AT_OK_Flag = 0;
Delay_us(500000);
Usart_SendString(USART1,"60%\r\n");
AT_OK_Flag=0;
Usart_SendString(USART2,LJFWQ);//发送数据传输指令并等待成功
while(!AT_OK_Flag);
AT_OK_Flag = 0;
Delay_us(500000);
Usart_SendString(USART1,"85%\r\n");
AT_Clicent=0;
while(!AT_Clicent);
AT_Clicent=0;
Usart_SendString(USART1,"100%\r\n");
while(1){
Usart_SendString(USART2,TCMS);
Delay_us(2000000);
//"心跳包"
Usart_SendString(USART2,"helloC");
Delay_us(2000000);
}
}
/**
******************************************************************************
* @file bsp_usart.c
* @author fire
* @version V1.0
* @date 2013-xx-xx
* @brief 重定向c库printf函数到usart端口
******************************************************************************
* @attention
*
* 实验平台:野火STM32 F103-指南者 开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :https://fire-stm32.taobao.com
*
******************************************************************************
*/
#include "bsp_usart.h"
#include "bsp_SysTick.h"
#include "stdio.h"
#include "stm32f10x.h"
#include <string.h>
#define newRESET "AT+RST\r\n"//重启模块指令
int oknum=0,flagnum=0;
char buffer[12],buffer1[12],show1[20];
int AT_OK_Flag = 0; //OK返回值的标志位
int AT_Clicent = 0; //WIFI GOT IP返回值的标志位
/**
* @brief 配置嵌套向量中断控制器NVIC
* @param 无
* @retval 无
*/
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
static void NVIC_Configuration1(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ1;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief USART GPIO 配置,工作参数配置
* @param 无
* @retval 无
*/
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打开串口GPIO的时钟
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
// 打开串口外设的时钟
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No ;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(DEBUG_USARTx, &USART_InitStructure);
// 串口中断优先级配置
NVIC_Configuration();
// 使能串口接收中断
USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
// 使能串口
USART_Cmd(DEBUG_USARTx, ENABLE);
}
void USART_Config1(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打开串口GPIO的时钟
DEBUG_USART_GPIO_APBxClkCmd1(DEBUG_USART_GPIO_CLK1, ENABLE);
// 打开串口外设的时钟
DEBUG_USART_APBxClkCmd1(DEBUG_USART_CLK1, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT1, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT1, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE1;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No ;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(DEBUG_USARTx1, &USART_InitStructure);
// 串口中断优先级配置
NVIC_Configuration1();
// 使能串口接收中断
USART_ITConfig(DEBUG_USARTx1, USART_IT_RXNE, ENABLE);
// 使能串口
USART_Cmd(DEBUG_USARTx1, ENABLE);
}
/***************** 发送一个字节 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到USART */
USART_SendData(pUSARTx,ch);
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
/****************** 发送8位的数组 ************************/
void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
{
uint8_t i;
for(i=0; i<num; i++)
{
/* 发送一个字节数据到USART */
Usart_SendByte(pUSARTx,array[i]);
}
/* 等待发送完成 */
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}
/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
do
{
Usart_SendByte( pUSARTx, *(str + k) );
k++;
} while(*(str + k)!='\0');
/* 等待发送完成 */
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
{}
}
/***************** 发送一个16位数 **********************/
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
uint8_t temp_h, temp_l;
/* 取出高八位 */
temp_h = (ch&0XFF00)>>8;
/* 取出低八位 */
temp_l = ch&0XFF;
/* 发送高八位 */
USART_SendData(pUSARTx,temp_h);
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
/* 发送低八位 */
USART_SendData(pUSARTx,temp_l);
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
void USART2_IRQHandler( void )
{
static int i = 0;//静态变量,被初始化一次
uint8_t tmp;
char *ret,*ret2,*ret3,*ret4;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
tmp = USART_ReceiveData(USART2);
Usart_SendByte(USART1,tmp);//打印从esp-01s接收到的数据
if(tmp == 'W' || tmp == 'O'|| tmp == 'L' || tmp == '0'){
ret = strchr(buffer,'W');
ret2 = strchr(buffer,'O');
ret3 = strchr(buffer,'L');
ret4 = strchr(buffer,'0');
if((ret!=NULL)||(ret2!=NULL)||(ret3!=NULL)||(ret4!=NULL))//防止前面有识别到时后面有出现关键字符,如WOFI_G,因为它识别到关键字符时会清零,所以要避开这种情况
{
}else
i = 0;
}
buffer[i++] = tmp;
if(i>=3)//判断是否是ok
{
if(buffer[0] == 'O' && buffer[1] == 'K'){
AT_OK_Flag = 1;
oknum=flagnum=0;//如果出现关键字符,清除其标志位
memset(buffer, '\0', 12);
i = 0;
}else
oknum=1;//非ok标志位
}
if(i>=7)
{
if(buffer[0] == '0' && buffer[4] == 'N'){//入网成功的判断依据WIFI GOT IP
AT_Clicent = 1;
oknum=flagnum=0;
memset(buffer, '\0', 12);
i = 0;
}else
flagnum=1;//非WIFI GOT IP标志位
}
if(oknum==1 && flagnum==1)//非关键字符串处理
{
i = 0;
oknum=flagnum=0;
memset(buffer, '\0', 12);
}
//联网失败出现FAIL字样捕获
// if(buffer[0] == 'F' && buffer[1] == 'A'){
// for(i=0;i<5;i++){
// GPIO_ResetBits(GPIOD,GPIO_Pin_3);
// Delay_us(1000000);
// GPIO_SetBits(GPIOD,GPIO_Pin_3);
// Delay_us(1000000);
// }
// Usart_SendString(USART1,newRESET);
// memset(buffer, '\0', 12);
// }
if(i == 12)//超出缓冲区上限处理,虽然实际上不太可能出现这种情况
{
i = 0;
oknum=flagnum=0;
memset(buffer, '\0', 12);
}
}
}
void USART1_IRQHandler( void )
{
static int j = 0;//静态变量,被初始化一次
uint8_t tmp;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
}
}
HAL库
设备模式

cpp
#include "bsp_esp8266.h"
#include "common.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "cJSON.h"
#include <stdlib.h>
#define NET_TIME "GET http://api.k780.com:88/?app=life.time&appkey=70087&sign=b68078fc7206f646d911624cd3e1ad6d&format=json\r\n\r\n"
char * netstr;
uint32_t start;
void realtime()
{
// while(ESP8266_Link_Server(enumTCP,"45.76.213.158","88",Single_ID_0) == 0);
// ESP8266_SendString(DISABLE,NET_TIME,strlen(NET_TIME),Single_ID_0);
// netstr = ESP8266_ReceiveString(DISABLE,5000);
// if(netstr){
// cJSON * root = cJSON_Parse(netstr);
// if(root){
// cJSON * item = cJSON_GetObjectItem(root,"result");
// if(item){
// item = cJSON_GetObjectItem(item,"timestamp");
// if(item){
// RTC_WaitForLastTask();
// RTC_SetCounter(atoi(item->valuestring));
// RTC_WaitForLastTask();
// }
// }
// cJSON_Delete(root);
// }
// }
}
void macESP8266_USART_IDE_FUN(void)
{
if (__HAL_UART_GET_FLAG(&macESP8266_USARTx, UART_FLAG_IDLE) != RESET)
{
__HAL_UART_CLEAR_IDLEFLAG(&macESP8266_USARTx); // 清除IDLE标志
strEsp8266_Fram_Record.InfBit.FramFinishFlag = 1;
// 可选:重启接收(如果用 HAL_UART_Receive_IT 或 HAL_UART_Receive_DMA)
// HAL_UART_Receive_IT(&huart3, (uint8_t *)strEsp8266_Fram_Record.Data_RX_BUF, RX_BUF_MAX_LEN);
}
}
void macESP8266_USART_INT_FUN(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART3)
{
uint8_t ucCh = uart3_rx_temp; // 临时变量接收
if (strEsp8266_Fram_Record.InfBit.FramLength < RX_BUF_MAX_LEN - 1)
{
strEsp8266_Fram_Record.Data_RX_BUF[strEsp8266_Fram_Record.InfBit.FramLength++] = ucCh;
}
// 继续接收下一字节
HAL_UART_Receive_IT(&huart3, &uart3_rx_temp, 1);
}
}
static void ESP8266_GPIO_Config ( void );
static void ESP8266_USART_Config ( void );
static void ESP8266_USART_NVIC_Configuration ( void );
struct STRUCT_USARTx_Fram strEsp8266_Fram_Record = { 0 };
struct STRUCT_USARTx_Fram strUSART_Fram_Record = { 0 };
/**
* @brief ESP8266初始化函数
* @param 无
* @retval 无
*/
void ESP8266_Init ( void )
{
ESP8266_GPIO_Config ();
// ESP8266_USART_Config ();
macESP8266_RST_HIGH_LEVEL();
macESP8266_CH_ENABLE();
// 启动第一次接收,让 HAL_UART_RxCpltCallback/IDLE 触发
HAL_UART_Receive_IT(&huart3, (uint8_t *)&uart3_rx_temp, 1);
}
/**
* @brief 初始化ESP8266用到的GPIO引脚
* @param 无
* @retval 无
*/
static void ESP8266_GPIO_Config ( void )
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* 配置 CH 引脚*/
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = macESP8266_CH_PD_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* 配置 RST 引脚*/
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = macESP8266_RST_PIN;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
///**
// * @brief 初始化ESP8266用到的 USART
// * @param 无
// * @retval 无
// */
//static void ESP8266_USART_Config ( void )
//{
// GPIO_InitTypeDef GPIO_InitStructure;
// USART_InitTypeDef USART_InitStructure;
//
//
// /* config USART clock */
// macESP8266_USART_APBxClock_FUN ( macESP8266_USART_CLK, ENABLE );
// macESP8266_USART_GPIO_APBxClock_FUN ( macESP8266_USART_GPIO_CLK, ENABLE );
//
// /* USART GPIO config */
// /* Configure USART Tx as alternate function push-pull */
// GPIO_InitStructure.GPIO_Pin = macESP8266_USART_TX_PIN;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_Init(macESP8266_USART_TX_PORT, &GPIO_InitStructure);
//
// /* Configure USART Rx as input floating */
// GPIO_InitStructure.GPIO_Pin = macESP8266_USART_RX_PIN;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
// GPIO_Init(macESP8266_USART_RX_PORT, &GPIO_InitStructure);
//
// /* USART1 mode config */
// USART_InitStructure.USART_BaudRate = macESP8266_USART_BAUD_RATE;
// USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// USART_InitStructure.USART_StopBits = USART_StopBits_1;
// USART_InitStructure.USART_Parity = USART_Parity_No ;
// USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
// USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// USART_Init(macESP8266_USARTx, &USART_InitStructure);
//
//
// /* 中断配置 */
// USART_ITConfig ( macESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中断
// USART_ITConfig ( macESP8266_USARTx, USART_IT_IDLE, ENABLE ); //使能串口总线空闲中断
// ESP8266_USART_NVIC_Configuration ();
//
//
// USART_Cmd(macESP8266_USARTx, ENABLE);
//
//
//}
///**
// * @brief 配置 ESP8266 USART 的 NVIC 中断
// * @param 无
// * @retval 无
// */
//static void ESP8266_USART_NVIC_Configuration ( void )
//{
// NVIC_InitTypeDef NVIC_InitStructure;
//
//
// /* Configure the NVIC Preemption Priority Bits */
// NVIC_PriorityGroupConfig ( macNVIC_PriorityGroup_x );
// /* Enable the USART2 Interrupt */
// NVIC_InitStructure.NVIC_IRQChannel = macESP8266_USART_IRQ;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
//}
/*
* 函数名:ESP8266_Rst
* 描述 :重启WF-ESP8266模块
* 输入 :无
* 返回 : 无
* 调用 :被 ESP8266_AT_Test 调用
*/
void ESP8266_Rst ( void )
{
#if 0
ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 );
#else
macESP8266_RST_LOW_LEVEL();
HAL_Delay ( 500 );
macESP8266_RST_HIGH_LEVEL();
#endif
}
/*
* 函数名:ESP8266_Cmd
* 描述 :对WF-ESP8266模块发送AT指令
* 输入 :cmd,待发送的指令
* reply1,reply2,期待的响应,为NULL表不需响应,两者为或逻辑关系
* waittime,等待响应的时间
* 返回 : 1,指令发送成功
* 0,指令发送失败
* 调用 :被外部调用
ESP8266_Cmd ( "AT", "OK", NULL, 500 )
*/
bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime )
{
bool res = false;
strEsp8266_Fram_Record .InfBit .FramLength = 0; //从新开始接收新的数据包
macESP8266_Usart ( "%s\r\n", cmd );
if ( ( reply1 == 0 ) && ( reply2 == 0 ) ) //不需要接收数据
return true;
while(1){
//HAL_Delay ( waittime ); //延时
HAL_Delay ( 1 ); //延时
waittime--;
if(waittime==0) break;
if(strEsp8266_Fram_Record .InfBit .FramFinishFlag==0)continue;
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
// macPC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF );
//strEsp8266_Fram_Record .InfBit .FramLength = 0; //清除接收标志
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
if ( ( reply1 != 0 ) && ( reply2 != 0 ) ){
res = ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) ||
( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
}
else if ( reply1 != 0 ){
res = ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) );
}else{
res = ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
}
if(res) break;
}
return res;
}
/*
* 函数名:ESP8266_AT_Test
* 描述 :对WF-ESP8266模块进行AT测试启动
* 输入 :无
* 返回 : 无
* 调用 :被外部调用
*/
//void ESP8266_AT_Test ( void )
//{
// macESP8266_RST_HIGH_LEVEL();
//
// HAL_Delay ( 1000 );
//
// while ( ! ESP8266_Cmd ( "AT", "OK", NULL, 500 ) ) ESP8266_Rst ();
//}
void ESP8266_AT_Test ( void )
{
char count=0;
macESP8266_RST_HIGH_LEVEL();
HAL_Delay ( 2000 );
while ( count < 10 )
{
if( ESP8266_Cmd ( "AT", "OK", NULL, 500 ) ) return;
ESP8266_Rst();
++ count;
}
}
/*
* 函数名:ESP8266_Net_Mode_Choose
* 描述 :选择WF-ESP8266模块的工作模式
* 输入 :enumMode,工作模式
* 返回 : 1,选择成功
* 0,选择失败
* 调用 :被外部调用
*/
bool ESP8266_Net_Mode_Choose ( ENUM_Net_ModeTypeDef enumMode )
{
switch ( enumMode )
{
case STA:
return ESP8266_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 );
case AP:
return ESP8266_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 );
case STA_AP:
return ESP8266_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 );
default:
return false;
}
}
/*
* 函数名:ESP8266_JoinAP
* 描述 :WF-ESP8266模块连接外部WiFi
* 输入 :pSSID,WiFi名称字符串
* :pPassWord,WiFi密码字符串
* 返回 : 1,连接成功
* 0,连接失败
* 调用 :被外部调用
*/
bool ESP8266_JoinAP ( char * pSSID, char * pPassWord )
{
char cCmd [120];
sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord );
return ESP8266_Cmd ( cCmd, "OK", NULL, 1000 );
}
/*
* 函数名:ESP8266_BuildAP
* 描述 :WF-ESP8266模块创建WiFi热点
* 输入 :pSSID,WiFi名称字符串
* :pPassWord,WiFi密码字符串
* :enunPsdMode,WiFi加密方式代号字符串
* 返回 : 1,创建成功
* 0,创建失败
* 调用 :被外部调用
*/
bool ESP8266_BuildAP ( char * pSSID, char * pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode )
{
char cCmd [120];
sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", pSSID, pPassWord, enunPsdMode );
return ESP8266_Cmd ( cCmd, "OK", 0, 1000 );
}
/*
* 函数名:ESP8266_Enable_MultipleId
* 描述 :WF-ESP8266模块启动多连接
* 输入 :enumEnUnvarnishTx,配置是否多连接
* 返回 : 1,配置成功
* 0,配置失败
* 调用 :被外部调用
*/
bool ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx )
{
char cStr [20];
sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) );
return ESP8266_Cmd ( cStr, "OK", 0, 500 );
}
/*
* 函数名:ESP8266_Link_Server
* 描述 :WF-ESP8266模块连接外部服务器
* 输入 :enumE,网络协议
* :ip,服务器IP字符串
* :ComNum,服务器端口字符串
* :id,模块连接服务器的ID
* 返回 : 1,连接成功
* 0,连接失败
* 调用 :被外部调用
*/
bool ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id)
{
char cStr [100] = { 0 }, cCmd [120];
switch ( enumE )
{
case enumTCP:
sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum );
break;
case enumUDP:
sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum );
break;
default:
break;
}
if ( id < 5 )
sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr);
else
sprintf ( cCmd, "AT+CIPSTART=%s", cStr );
return ESP8266_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );
}
/*
* 函数名:ESP8266_StartOrShutServer
* 描述 :WF-ESP8266模块开启或关闭服务器模式
* 输入 :enumMode,开启/关闭
* :pPortNum,服务器端口号字符串
* :pTimeOver,服务器超时时间字符串,单位:秒
* 返回 : 1,操作成功
* 0,操作失败
* 调用 :被外部调用
*/
bool ESP8266_StartOrShutServer ( FunctionalState enumMode, char * pPortNum, char * pTimeOver )
{
char cCmd1 [120], cCmd2 [120];
if ( enumMode )
{
sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum );
sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver );
return ( ESP8266_Cmd ( cCmd1, "OK", 0, 500 ) &&
ESP8266_Cmd ( cCmd2, "OK", 0, 500 ) );
}
else
{
sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum );
return ESP8266_Cmd ( cCmd1, "OK", 0, 500 );
}
}
/*
* 函数名:ESP8266_Get_LinkStatus
* 描述 :获取 WF-ESP8266 的连接状态,较适合单端口时使用
* 输入 :无
* 返回 : 2,获得ip
* 3,建立连接
* 3,失去连接
* 0,获取状态失败
* 调用 :被外部调用
*/
uint8_t ESP8266_Get_LinkStatus ( void )
{
if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
{
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) )
return 2;
else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) )
return 3;
else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) )
return 4;
}
return 0;
}
/*
* 函数名:ESP8266_Get_IdLinkStatus
* 描述 :获取 WF-ESP8266 的端口(Id)连接状态,较适合多端口时使用
* 输入 :无
* 返回 : 端口(Id)的连接状态,低5位为有效位,分别对应Id5~0,某位若置1表该Id建立了连接,若被清0表该Id未建立连接
* 调用 :被外部调用
*/
uint8_t ESP8266_Get_IdLinkStatus ( void )
{
uint8_t ucIdLinkStatus = 0x00;
if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
{
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:0," ) )
ucIdLinkStatus |= 0x01;
else
ucIdLinkStatus &= ~ 0x01;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:1," ) )
ucIdLinkStatus |= 0x02;
else
ucIdLinkStatus &= ~ 0x02;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:2," ) )
ucIdLinkStatus |= 0x04;
else
ucIdLinkStatus &= ~ 0x04;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:3," ) )
ucIdLinkStatus |= 0x08;
else
ucIdLinkStatus &= ~ 0x08;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:4," ) )
ucIdLinkStatus |= 0x10;
else
ucIdLinkStatus &= ~ 0x10;
}
return ucIdLinkStatus;
}
/*
* 函数名:ESP8266_Inquire_ApIp
* 描述 :获取 F-ESP8266 的 AP IP
* 输入 :pApIp,存放 AP IP 的数组的首地址
* ucArrayLength,存放 AP IP 的数组的长度
* 返回 : 0,获取失败
* 1,获取成功
* 调用 :被外部调用
*/
uint8_t ESP8266_Inquire_ApIp ( char * pApIp, uint8_t ucArrayLength )
{
char uc;
char * pCh;
ESP8266_Cmd ( "AT+CIFSR", "OK", 0, 500 );
pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "APIP,\"" );
if ( pCh )
pCh += 6;
else
return 0;
for ( uc = 0; uc < ucArrayLength; uc ++ )
{
pApIp [ uc ] = * ( pCh + uc);
if ( pApIp [ uc ] == '\"' )
{
pApIp [ uc ] = '\0';
break;
}
}
return 1;
}
/*
* 函数名:ESP8266_UnvarnishSend
* 描述 :配置WF-ESP8266模块进入透传发送
* 输入 :无
* 返回 : 1,配置成功
* 0,配置失败
* 调用 :被外部调用
*/
bool ESP8266_UnvarnishSend ( void )
{
if ( ! ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ) )
return false;
return
ESP8266_Cmd ( "AT+CIPSEND", "OK", ">", 500 );
}
/*
* 函数名:ESP8266_ExitUnvarnishSend
* 描述 :配置WF-ESP8266模块退出透传模式
* 输入 :无
* 返回 : 无
* 调用 :被外部调用
*/
void ESP8266_ExitUnvarnishSend ( void )
{
HAL_Delay ( 1000 );
macESP8266_Usart ( "+++" );
HAL_Delay ( 500 );
}
/*
* 函数名:ESP8266_SendString
* 描述 :WF-ESP8266模块发送字符串
* 输入 :enumEnUnvarnishTx,声明是否已使能了透传模式
* :pStr,要发送的字符串
* :ulStrLength,要发送的字符串的字节数
* :ucId,哪个ID发送的字符串
* 返回 : 1,发送成功
* 0,发送失败
* 调用 :被外部调用
*/
bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId )
{
char cStr [20];
bool bRet = false;
if ( enumEnUnvarnishTx )
{
macESP8266_Usart ( "%s", pStr );
bRet = true;
}
else
{
if ( ucId < 5 )
sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );
else
sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );
ESP8266_Cmd ( cStr, "> ", 0, 1000 );
bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 1000 );
}
return bRet;
}
/*
* 函数名:ESP8266_ReceiveString
* 描述 :WF-ESP8266模块接收字符串
* 输入 :enumEnUnvarnishTx,声明是否已使能了透传模式
* 返回 : 接收到的字符串首地址
* 调用 :被外部调用
*/
char * ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx, u32 waittime )
{
char * pRecStr = 0;
/* 先清理旧标志、未清则前面已做 */
while (!strEsp8266_Fram_Record.InfBit.FramFinishFlag && waittime--) {
HAL_Delay(10);
}
/* 加个尾 '\0' */
strEsp8266_Fram_Record.Data_RX_BUF[strEsp8266_Fram_Record.InfBit.FramLength] = '\0';
pRecStr = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" );
if ( pRecStr ){
char *end;
pRecStr = strstr(pRecStr, ":") + 1;
end = strstr(pRecStr, "CLOSED");
if(end){
*end = 0;
}
return pRecStr;
}
strEsp8266_Fram_Record .InfBit .FramLength = 0;
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
// while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag ){
// waittime--;
// HAL_Delay(10);
// if(waittime==0){
// return 0;
// }
// }
start = HAL_GetTick();
while (!strEsp8266_Fram_Record.InfBit.FramFinishFlag) {
if ((HAL_GetTick() - start) >= waittime) {
return 0;
}
// 不要再放 HAL_Delay,这里让中断随时进来处理
}
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
if ( enumEnUnvarnishTx )
pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;
else
{
pRecStr = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" );
if ( pRecStr ){
char *end;
pRecStr = strstr(pRecStr, ":") + 1;
end = strstr(pRecStr, "CLOSED");
if(end){
*end = 0;
}
}
}
return pRecStr;
}
uint8_t uart3_rx_temp;
char usart[100]={0};
extern struct STRUCT_USARTx_Fram strEsp8266_Fram_Record;
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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_USART1_UART_Init();
MX_USART3_UART_Init();
/* USER CODE BEGIN 2 */
// 启动接收中断
HAL_Delay(6000);
ESP8266_Init();
// 启动接收
// 手动启用 IDLE 中断(必须)
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
HAL_Delay(6000);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
HAL_UART_Transmit(&huart1, "ESP8266 AT Test...\r\n", strlen("ESP8266 AT Test...\r\n"), HAL_MAX_DELAY);
ESP8266_AT_Test();
if (!strstr(strEsp8266_Fram_Record.Data_RX_BUF, "OK"))
{
HAL_UART_Transmit(&huart1, "AT Test Failed!\r\n", strlen("AT Test Failed!\r\n"), HAL_MAX_DELAY);
while (1);
}
HAL_UART_Transmit(&huart1, "OK\r\n", strlen("OK\r\n"), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart1, "Joining AP...\r\n", strlen("Joining AP...\r\n"), HAL_MAX_DELAY);
if (ESP8266_JoinAP("yzzl", "yzzl2021"))
{
HAL_UART_Transmit(&huart1, "Join AP OK\r\n", strlen("Join AP OK\r\n"), HAL_MAX_DELAY);
}
else
{
HAL_UART_Transmit(&huart1, "Join AP Failed!\r\n", strlen("Join AP Failed!\r\n"), HAL_MAX_DELAY);
}
if (ESP8266_JoinAP("yzzl", "yzzl2021"))
{
HAL_UART_Transmit(&huart1, "Join AP OK\r\n", strlen("Join AP OK\r\n"), HAL_MAX_DELAY);
}
else
{
HAL_UART_Transmit(&huart1, "Join AP Failed!\r\n", strlen("Join AP Failed!\r\n"), HAL_MAX_DELAY);
}
if (ESP8266_JoinAP("yzzl", "yzzl2021"))
{
HAL_UART_Transmit(&huart1, "Join AP OK\r\n", strlen("Join AP OK\r\n"), HAL_MAX_DELAY);
}
else
{
HAL_UART_Transmit(&huart1, "Join AP Failed!\r\n", strlen("Join AP Failed!\r\n"), HAL_MAX_DELAY);
}
/* 6. 连接远程服务器测试 */
HAL_UART_Transmit(&huart1, "Link to server...\r\n", strlen("Link to server...\r\n"), HAL_MAX_DELAY);
if (ESP8266_Link_Server(enumTCP, "192.168.31.39", "8080", Single_ID_0))
HAL_UART_Transmit(&huart1, "CIPSTART OK\r\n", strlen("CIPSTART OK\r\n"), HAL_MAX_DELAY);
else
HAL_UART_Transmit(&huart1, "CIPSTART Failed!\r\n", strlen("CIPSTART Failed!\r\n"), HAL_MAX_DELAY);
/* 7. 发送测试数据 */
const char *testMsg = "Hello from STM32!";
HAL_UART_Transmit(&huart1, "Send data...\r\n", strlen("Send data...\r\n"), HAL_MAX_DELAY);
if (ESP8266_SendString(DISABLE, (char *)testMsg, strlen(testMsg), Single_ID_0))
HAL_UART_Transmit(&huart1, "SEND OK\r\n", strlen("SEND OK\r\n"), HAL_MAX_DELAY);
else
HAL_UART_Transmit(&huart1, "SEND Failed!\r\n", strlen("SEND Failed!\r\n"), HAL_MAX_DELAY);
/* 8. 接收服务器响应 */
HAL_UART_Transmit(&huart1, "Waiting response...\r\n", strlen("Waiting response...\r\n"), HAL_MAX_DELAY);
ESP8266_PrepareReceive();
char *rec = ESP8266_ReceiveString(DISABLE, 5000);
if (rec) {
sprintf(usart,"Received: %s\r\n", rec);
HAL_UART_Transmit(&huart1, usart, strlen(usart), HAL_MAX_DELAY);
}
else
HAL_UART_Transmit(&huart1, "No response or timeout\r\n", strlen("No response or timeout\r\n"), HAL_MAX_DELAY);
while (1)
{
ESP8266_PrepareReceive();
HAL_Delay(1000);
if (ESP8266_Cmd("AT+CIFSR", "OK", NULL, 500))
{
/* 假定 usart[64] */
snprintf(usart, sizeof(usart), "IP: %s\r\n", strEsp8266_Fram_Record.Data_RX_BUF);
HAL_UART_Transmit(&huart1, usart, strlen(usart), HAL_MAX_DELAY);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief This function handles USART3 global interrupt.
*/
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/* USER CODE END USART3_IRQn 0 */
/* USER CODE BEGIN USART3_IRQn 1 */
USART3_IDLE_IRQHandler();
HAL_UART_IRQHandler(&huart3); // HAL库处理通用中断
USART3_IDLE_IRQHandler(); // 手动处理IDLE中断
/* USER CODE END USART3_IRQn 1 */
}
六、讲解视频