STM32驱动ESP01(HAL库)

一、简介

实测VCC接5V通信将不正常。

二、USB-TTL与ESP-01

我们可以通过USB-TTL与ESP-01连接,通过AT指令设置或检查ESP-01工作是否正常。

RX和TX反接其他正常接线就行。ESP-01默认波特率为115200。

当我们通过串口助手发送指令“AT”,若接收到“OK”则表示模块正常。

注意要勾选“发送新行”

该模块支持STA模式、AP模式、STA兼AP模式三种。

(1)STA模式

配置为STA模式的AT指令为:AT+CWMODE=1

此时ESP8266模块已经被设置为了STA模式。我们可以连接家中的WIFI。

连接WIFI的AT指令为:AT+CWJAP=AT+CWJAP="WIFI ID","WIFI 密码"

例如我这里是:AT+CWJAP="Redmi K40","123456789"

显示WIFI GOT IP OK 则表示连接成功。

我们此时就可以通过AT指令“AT+CIFSR”查询IP地址

此时我们的电脑和ESP8266模块都连接到了同一个路由器。

我们就可以通过电脑创建TCP服务器,两者就可以进行通信了。

我们打开网络调试助手

创建TCP Server

然后在串口助手上用AT指令连接该TCP Server

AT指令为:AT+CIPSTART="TCP","IP地址",8080

注意英文的双引号和逗号

连接成功也会返回OK

测试两者就可以进行通信了

我们需要先告诉服务器我们需要发送的长度,如AT+CIPSEND=4

看到出现>符号后就可以发送了,如:good

(2)AP模式

首先,我们通过AT指令,AT+CWMODE=2配置ESP8266模块为AP模式

然后,我们通过AT指令使能多链接,AT+CIPMUX=1

多链接的意思为:

反之,AT+CIPMUX=0,表示设置为单链接。

接着,我们就可以通过ESP8266模块建立TCP服务器(上一小节的STA模式是通过PC建立TCP 服务器)ESP8266模块建立TCP服务器的AT指令为:AT+CIPSERVER=1

创建成功之后我们就用电脑连接AI开头的WIFI。连接成功后串口助手上会显示OK等信息

最后,我们就可以通过网络调试助手连接由ESP8266创建的TCP SERVER后就可以进行通信了。

(通信过程类似)

IP地址默认为192.168.4.1,也可以通过AT指令,AT+CIPSR查询,PORT默认为333

三、STM32与ESP-01进行通信(HAL库代码)

我们使用的是STM32最小系统板,CUBEMX+CUBEIDE。

代码是改的这位博主的ESP-01

串口3连接USB-TTL用来打印一些信息,设置如下:

串口2连接ESP-01模块,用于STM32与ESP-01模块进行通信,使用的方式是开启了串口2的DMA(DMA+空闲中断)

两个串口的波特率均为115200,串口2和串口3都开启DMA

并开启串口2和串口3的中断

首先,我们先写ESP-01模块的驱动代码,driver_esp.c

#include "driver_esp.h"



uint8_t WIFI_Name_Cipher[]="AT+CWJAP=\"Redmi K40\",\"123456789\"\r\n";

#define ESP01_UART_HANDLE	huart2

void esp01_uart_send_data(uint8_t *data,uint16_t data_len)
{
	HAL_UART_Transmit(&ESP01_UART_HANDLE, data , data_len,100 );
}

/*****************************************上面是需要修改的地方******************************************************/
/*私有定义*/
uint8_t g_esp8266_rx_buffer[256];   // ESP8266响应数据接收缓冲区
/*****************************************函数******************************************************/

/**
 * @brief  ESP8266发送命令
 * @param  cmd为AT指令,res为返回值
 * @return 成功返回1,失败返回0
 * 通过串口2发送AT指令给esp-01s模块,如果检索到串口2收到esp-01s回复的字符中存在指定字符(res),则表示成功且返回1,否则失败返回0
  *其中cmd是需要发送的AT指令,res是esp-01s模块回复(发送)给串口2的字符消息
 */
_Bool ESP8266_Send_Cmd(char *cmd, char *res)
{
	uint8_t TimeOut = 20;
	esp01_uart_send_data(cmd, strlen(cmd));
	while (TimeOut --)
	{
		if (strstr(g_esp8266_rx_buffer, res) != NULL)
			return 1; //Success
		HAL_Delay(100);
	}
	return 0; //Fail
}
/**
  * @brief   测试命名
  * @param   None
  * @retval  None
 **/
_Bool ESP8266_TEST(void)
{
	return ESP8266_Send_Cmd("AT\r\n","OK");
}
/**
  * @brief   选择ESP8266的工作模式
  * @param   enumMode 模式类型 STA AP STA_AP
  * @retval  返回 true 发送成功,false 失败
 **/
_Bool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode)
{
	switch (enumMode)
	{
		case STA:
			return ESP8266_Send_Cmd("AT+CWMODE=1\r\n", "OK");
		case AP:
			return ESP8266_Send_Cmd("AT+CWMODE=2\r\n", "OK");
		case STA_AP:
			return ESP8266_Send_Cmd("AT+CWMODE=3\r\n", "OK");
		default:
			return 0;
	}
}

/**
 * @brief  设置ESP8266的连接模式(单连接/多连接)
 * @param  mode 0=单连接模式,1=多连接模式
 * @return 成功返回1,失败返回0
 */
_Bool ESP8266_Set_MultiplesMode(uint8_t mode)
{
	char cmd[32];
	//构造AT指令:AT+CIPMUX=<mode>\r\n
	sprintf(cmd, "AT+CIPMUX=%d\r\n", mode);
	return ESP8266_Send_Cmd(cmd, "OK");
}
/**
 * @brief  连接WIFI
 * @param  None
 * @return 成功返回1,失败返回0
 * @Note   注意修改WIFI_Name_Cipher
 */
_Bool ESP8266_JoinAP(void)
{
	return ESP8266_Send_Cmd(WIFI_Name_Cipher,"OK");
}
/**
 * @brief  连接TCP服务器(自动适配单连接/多连接模式)
 * @param  id    连接ID(仅在多连接模式下有效,单连接模式传0)
 * @param  ip    服务器IP地址(如 "192.168.1.100")
 * @param  port  服务器端口号(如 8080)
 * @return 成功返回1,失败返回0
 */
_Bool ESP8266_Connect_TCPServer(uint8_t id, const char* ip, uint16_t port) {
    char cmd[128];
    // 根据当前模式构造AT指令
    if (strstr(g_esp8266_rx_buffer, "+CIPMUX:1") != NULL) {
        // 多连接模式:AT+CIPSTART=<id>,"TCP","<ip>",<port>\r\n
        sprintf(cmd, "AT+CIPSTART=%d,\"TCP\",\"%s\",%d\r\n", id, ip, port);
    } else {
        // 单连接模式:AT+CIPSTART="TCP","<ip>",<port>\r\n
        sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%d\r\n", ip, port);
    }
    return ESP8266_Send_Cmd(cmd, "OK");
}

接下来是源文件

#ifndef __DRIVER_ESP_H
#define __DRIVER_ESP_H

#include "main.h"
#include "usart.h"
#include <string.h>
#include <stdio.h>

//ESP8266模式选择
typedef enum
{
    STA,
    AP,
    STA_AP
}ENUM_Net_ModeTypeDef;

_Bool ESP8266_TEST(void);//测试命令 发送“AT”
_Bool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode); //设置模式 STA AP STA_AP
_Bool ESP8266_Set_MultiplesMode(uint8_t mode);//选择多链路 1多 0单
_Bool ESP8266_JoinAP(void);//加入WIFI
_Bool ESP8266_Connect_TCPServer(uint8_t id, const char* ip, uint16_t port);//建立TCP服务器
_Bool ESP8266_Send_Cmd(char *cmd, char *res);

#endif

这个驱动文件封装了几个AT指令,如果需要其他命令可以自己封装

_Bool ESP8266_TEST(void);//测试命令 发送“AT”
_Bool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode); //设置模式 STA AP STA_AP
_Bool ESP8266_Set_MultiplesMode(uint8_t mode);//选择多链路 1多 0单
_Bool ESP8266_JoinAP(void);//加入WIFI
_Bool ESP8266_Connect_TCPServer(uint8_t id, const char* ip, uint16_t port);//建立TCP服务器
_Bool ESP8266_Send_Cmd(char *cmd, char *res);//发送命名

接下来初始化代码 和空闲处理代码:(设置为STA模式并连接TCP服务器)

esp01_uart.c代码:

#include "esp01_uart.h"


extern uint8_t g_UART3_Rx_Buffer[256];
extern uint8_t g_esp8266_rx_buffer[256];   // ESP8266响应数据接收缓冲区
#define ESP01_UART_HANDLE	huart2
uint8_t g_uart2_rx_buffer[256];

#define IP		"192.168.160.197"
#define PORT	8080
/**
  * @brief   ESP8266初始化
  * @param   None
  * @retval  None
 **/
void ESP8266_Init(void)
{
	__HAL_UART_ENABLE_IT(&ESP01_UART_HANDLE, UART_IT_IDLE);
	HAL_UART_Receive_DMA(&ESP01_UART_HANDLE, g_uart2_rx_buffer, strlen(g_uart2_rx_buffer));
	while (!ESP8266_TEST());
	HAL_Delay(500);
	//设置为STA模式
	while (!ESP8266_Net_Mode_Choose(STA));
	HAL_Delay(500);
	//连接WIFI
	while (!ESP8266_JoinAP());
	HAL_Delay(1000);
	// 连接TCP模式
	while (!ESP8266_Connect_TCPServer(0, IP, PORT));
	HAL_Delay(500);
}
void ESP01_IDLE_CallBack(void)
{
	uint8_t idle = __HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE);

	  if(RESET != idle){
	      __HAL_UART_CLEAR_IDLEFLAG(&huart2);
	      HAL_UART_DMAStop(&huart2);

	      strcpy(g_esp8266_rx_buffer,g_uart2_rx_buffer);

	      //将串口2接收到的数据发送给串口3,
	      HAL_UART_Transmit(&huart3,g_esp8266_rx_buffer, strlen(g_esp8266_rx_buffer),100);

	      memset(g_uart2_rx_buffer,'\0',256);
	      HAL_UART_Receive_DMA(&huart2,g_uart2_rx_buffer,256);
	      HAL_UART_Receive_DMA(&huart3, g_UART3_Rx_Buffer, 256);
	  }
}

esp01_uart.h代码: 

#ifndef __ESP01_UART_H
#define __ESP01_UART_H

#include "main.h"
#include "driver_esp.h"
#include "usart.h"
#include "UART3_PRINTF.h"
#include <string.h>
#include <stdio.h>


void ESP8266_Init(void);
void ESP01_IDLE_CallBack(void);



#endif

接下来是UART3的空闲中断函数,

#include "UART3_PRINTF.h"

uint8_t g_UART3_Rx_Buffer[256];

extern uint8_t g_uart2_rx_buffer[256];

int _write(int fd, char *ptr, int len) {
    HAL_UART_Transmit(&huart3, (uint8_t *)ptr, len, 1000);
    return len;
}


void UART3_Init(void)
{
	  __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
	  HAL_UART_Receive_DMA(&huart3, g_UART3_Rx_Buffer, strlen(g_UART3_Rx_Buffer));
}

void UART3_IDLE_CallBack(void)
{
	  uint8_t idle = __HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE);
	      uint8_t UART3_Tx_Buffer[256];

	      if(RESET != idle) {
	          __HAL_UART_CLEAR_IDLEFLAG(&huart3);
	          HAL_UART_DMAStop(&huart3);

	          strcpy(UART3_Tx_Buffer, g_UART3_Rx_Buffer);
	          //回显发送字符
	          HAL_UART_Transmit(&huart3, UART3_Tx_Buffer, strlen(UART3_Tx_Buffer), 100);

	          memset(g_UART3_Rx_Buffer, '\0', 256);
//	          //如果发送的字符是AT指令,发送成功就回回显"AT CMD Send OK!"
//	          if(strstr(UART3_Tx_Buffer,"AT") != NULL){
	              HAL_UART_Transmit_DMA(&huart2, UART3_Tx_Buffer, strlen(UART3_Tx_Buffer));
//	              HAL_UART_Transmit(&huart3, "AT CMD Send OK!\r\n", strlen("AT CMD Send OK!\r\n"), 100);
//
//	          }
	          HAL_UART_Receive_DMA(&huart3, g_UART3_Rx_Buffer, 256);
	          HAL_UART_Receive_DMA(&huart2,g_uart2_rx_buffer,256);
	      }
}

(串口3就用于将ESP-01返回值显示到串口助手上)

最后将空闲中断函数写到IT.c中

将程序下载到单片机上:

 

我们还可以在ESP8266_Init初始化函数中实现AP模式。

void ESP8266_Init(void)
{
	__HAL_UART_ENABLE_IT(&ESP01_UART_HANDLE, UART_IT_IDLE);
	HAL_UART_Receive_DMA(&ESP01_UART_HANDLE, g_uart2_rx_buffer, strlen(g_uart2_rx_buffer));
	while (!ESP8266_TEST());
	HAL_Delay(500);
	//设置为AP模式
	while (!ESP8266_Net_Mode_Choose(AP));
	HAL_Delay(500);
	while (!ESP8266_Set_MultiplesMode(1));
	HAL_Delay(500);
	//建立TCP 服务器
    while(!ESP8266_Send_Cmd("AT+CIPSERVER=1\r\n","OK"));
    HAL_Delay(500);
}

 

 

 

 

 

### STM32ESP8266(ESP-01S)通过HAL实现通信 #### 使用串口进行初始化配置 为了使STM32能够与ESP8266 (ESP-01S)建立有效的通信,首先需要完成硬件连接以及软件上的初始化设置。具体来说,在硬件方面,需确保两个设备间的TX/RX引脚正确对接;而在软件层面,则涉及到了利用STM32 HAL来配置相应的UART接口参数。 对于STM32端而言,主要工作集中在`MX_USARTx_UART_Init()`函数内定义波特率、字长等属性[^1]: ```c static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 9600; // 设置波特率为9600bps huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } ``` 上述代码片段展示了如何针对USART1外设实例化一个UART句柄对象,并对其进行必要的初始化操作。这里特别指定了传输速率(即波特率)、字符长度以及其他一些重要的通讯特性。 #### 发送命令给ESP8266模块 一旦完成了基本的初始化之后,就可以向ESP8266发送AT指令来进行进一步的操作了。这通常涉及到调用`HAL_UART_Transmit()`方法传递特定格式的数据包到目标设备上。下面是一个简单的例子说明怎样构建并发出一条用于查询Wi-Fi状态的消息: ```c void Send_AT_Command(char *command, uint32_t timeout_ms){ /* 将字符串转换成常量数组 */ char cmd[]="AT+CIPSTATUS\r\n"; /* 向指定串口写入数据 */ HAL_UART_Transmit(&huart1,(uint8_t*)cmd,strlen(cmd),timeout_ms); } // 调用此函数可以获取当前WiFi连接状况 Send_AT_Command("AT+CIPSTATUS", 1000); ``` 这段程序实现了将预定义好的AT指令序列传送给ESP8266的功能,其中包含了结束符`\r\n`以符合标准要求。同时设置了合理的超时时间防止无限等待响应的情况发生。 #### 接收来自ESP8266的信息反馈 除了主动下发控制指令之外,还需要具备接收处理对方返回的结果的能力。为此可借助于中断机制或是轮询的方式读取缓冲区内的最新消息。采用非阻塞模式下的循环检测法如下所示: ```c char rxBuffer[64]; // 定义接收缓存大小为64字节 int index=0; while(HAL_UART_GetState(&huart1)!= HAL_UART_STATE_READY){} // 等待直到准备就绪 if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)){ while((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE))&&(index<sizeof(rxBuffer)-1)) rxBuffer[index++]=((char)(huart1.Instance->DR)); rxBuffer[index]='\0'; // 添加终止符形成有效C风格字符串 printf("Received:%s\n",rxBuffer); // 输出接收到的内容至终端显示 } ``` 以上代码段描述了一种简单的方法用来持续监听是否有新的输入到达,并将其存储在一个局部变量里供后续分析使用。当有新字符到来时会自动触发条件判断语句内部的动作直至整个报文被完全捕获为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值