超详细基于stm32hal库的esp8266WiFi模块驱动程序(可直接移植)

目录

前言:

1 前期准备

1.1 了解mqtt通信协议

1.1.1核心组件

1.2 ESP8266固件烧录

1.3 启动EMQX服务器

1.3.1大概了解emqx的使用

2 驱动代码讲解应用

2.1 硬件接线

2.2 AT指令

2.3 驱动代码

2.4 效果展示


前言:

esp8266支持mqtt通信协议,在一些只能在局域网环境下通信来说是十分便捷的(比如智能家居环境),下面这个工程就是stm32单片机结合esp8266作为客户端与其他客户端设备互相通信。

1 前期准备

1.1 了解mqtt通信协议

        MQTT (Message Queuing Telemetry Transport) 是一种轻量级、开放标准、基于发布/订阅模式的消息传输协议。它最初由 IBM 和 Eurotech 在 1999 年设计,用于连接石油管道上的远程传感器与卫星链路。如今,它已成为物联网 (IoT) 领域事实上的标准通信协议。

1.1.1核心组件

1. 发布者 (Publisher): 产生并发送消息的客户端(设备或应用)。例如:在我们的工程里我们将单片机采集到的数据通过串口转发给esp8266,而esp充当消息的发布者。
2. 订阅者 (Subscriber): 接收其感兴趣消息的客户端(设备或应用)。例如:手机 App 订阅温度读数以显示,或者空调控制器订阅温度读数来决定是否开启。
3. 代理服务器 (Broker): MQTT 通信的核心枢纽。它负责:
接收来自发布者的消息。
根据消息的主题 (Topic) 将其过滤并转发给所有订阅了该主题的订阅者。
管理客户端连接(认证、授权、会话状态)。
存储 QoS 消息以确保可靠传输(根据 QoS 级别)。
处理遗嘱消息 (Last Will & Testament)。

在这个工程里我们使用开源的mqtt服务系统EMQX.


4. 主题 (Topic): 这是 MQTT 实现通信的关键机制。 主题是一个 UTF-8 字符串,充当消息的“地址”或“路由标签”。发布者发布消息时必须指定一个主题。订阅者通过订阅特定的主题(或使用通配符)来表明它希望接收哪些主题的消息。例如:home/livingroom/temperature, factory/machine42/vibration。
5. 消息 (Message): 包含实际传输的数据(Payload),可以是任何格式(JSON, XML, 二进制, 纯文本等)。消息总是与一个主题相关联

1.2 ESP8266固件烧录

esp8266要使用mqtt通信需要烧录含mqtt的固件网上可以找到很多教程(一些厂家出厂自带固件)

1.3 启动EMQX服务器

需要在本地部署emqx服务器过程不难

这里推荐一个教程Windows下载安装EMQX_emqx下载-CSDN博客

1.3.1大概了解emqx的使用

在首页我们可以查看到连接服务器的设备有哪些(每一个设备有自己独立端口点开可以查看)

我们可以在服务器里创建客户端位置如下

使用规则也很简单最基本的,订阅了同一个主题的设备,当其他设备发送消息的时候,己设备可以看到,同样的当己设备发布消息的时候,其他跟我订阅同一主题的设备就可以收到己设备发送的消息。也是这样实现了多个设备之间的互相通信。

2 驱动代码讲解应用

2.1 硬件接线

只需要用到esp8266的4各引脚,gnd,3.3v,tx,rx(tx rx分别与单片机的串口交叉相连)如下图

2.2 AT指令

esp8266可以使用AT查看设备的一些远行状态下面给出以下常用的AT指令

2.3 驱动代码

这里我使用stm32hal库写了一段容易移植的代码,文件构成为ESP8266.c(关于esp8266的驱动代码),ESP8266.h,comation.c(系统驱动代码),comation.h,head.h(包含要用到的头文件)只需要在主函数里初始化一下就可以使用了。

因为该模块可以商店自动连接WiFi所以我在初始化的时候没有连接WiFi,如果想要换WiFi可以调用下面函数

/* @briefWIFI重连* @param* @return*/
void ESPWIFI_Reconnect(void)
{//断开WiFiUART_Printf(&huart2, "AT+CWQAP");HAL_Delay(1000);//连接WiFiUART_Printf(&huart2, "AT+CWJAP=\"%s\",\"%s\"\r\n",WIFI_NAME,WIFI_PASSWORD);
}

ESP8266.c

/** ESP8266.c**  Created on: Aug 11, 2025*      Author: ccc*/
#include "head.h"/** @brief esp初始化连接服务器* @param* @return* */
char esp_response[RESP_BUFFER_SIZE];//接收缓存区
uint16_t resp_index = 0;//接受标志位
uint8_t esprx_byte;
void Inint_esp8266(void)
{HAL_UART_Receive_IT(&huart2, &esprx_byte, 1);HAL_Delay(30);// 配置认证UART_Printf(&huart2, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n",MQTT_CLIENT_ID,MQTT_USERNAME,MQTT_PASSWORD);HAL_Delay(1000);// 连接服务器UART_Printf(&huart2, "AT+MQTTCONN=0,\"%s\",1883,0\r\n",MQTT_BROKER);HAL_Delay(3000);// 订阅主题UART_Printf(&huart2, "AT+MQTTSUB=0,\"%s\",1\r\n",MQTT_TOPIC);HAL_Delay(1000);}
/** @brief esp响应函数* @param* @return* */
void ESP8266_ReceiveHandler(UART_HandleTypeDef *huart)
{//  处理接收到的字节// 检查缓冲区是否已满if(resp_index >= RESP_BUFFER_SIZE - 1){resp_index = 0; // 重置缓冲区,防止溢出}// 存储接收到的字节esp_response[resp_index++] = esprx_byte;//  检测是否收到完整响应(以换行符结束)if(esprx_byte == '\n'){esp_response[resp_index] = '\0'; // 添加字符串结束符//  打印原始响应UART_Printf(&huart1, "ESP8266get: %s\n", esp_response);//  处理关键响应(以下消息使用串口1转发)if(strstr(esp_response, "OK") != NULL){UART_Printf(&huart1, "Getsuccessful!\n");}else if(strstr(esp_response, "ERROR") != NULL){UART_Printf(&huart1, "Getfailed!\n");}else if(strstr(esp_response, "+MQTTCONNECTED:0") != NULL){UART_Printf(&huart1, "MQTTConnection successful!\n");}else if(strstr(esp_response, "+MQTTDISCONNECTED:0") != NULL){UART_Printf(&huart1, "MQTTDisconnect!\n");}else if(strstr(esp_response, "MQTTSUBRECV:0") != NULL){// 解析MQTT消息// 格式: +MQTTSUBRECV:0,<topic>,<length>,<message>char *topic_start = strchr(esp_response, ',') + 1;char *topic_end = strchr(topic_start, ',');char *length_start = topic_end + 1;char *length_end = strchr(length_start, ',');char *msg_start = length_end + 1;// 提取主题int topic_len = topic_end - topic_start;char topic[topic_len + 1];strncpy(topic, topic_start, topic_len);topic[topic_len] = '\0';// 提取消息长度int msg_len = atoi(length_start);// 提取消息内容char message[msg_len + 1];strncpy(message, msg_start, msg_len);message[msg_len] = '\0';UART_Printf(&huart1, "getMQTTmessage: [topic] %s [message] %s\n", topic, message);}memset(esp_response, 0, sizeof(esp_response));resp_index = 0; // 重置缓冲区索引}//  重新启动接收,等待下一个字节HAL_UART_Receive_IT(&huart2, &esprx_byte, 1);
}
/** @brief esp发送函数* @param* @return* */
void Publish_Message(const char *message)
{// AT+MQTTPUB=0,<topic>,<message>,<qos>,<retain>UART_Printf(&huart2, "AT+MQTTPUB=0,\"%s\",\"%s\",0,0\r\n", MQTT_TOPIC, message);HAL_Delay(100);
}/* @briefWIFI重连* @param* @return*/
void ESPWIFI_Reconnect(void)
{//断开WiFiUART_Printf(&huart2, "AT+CWQAP");HAL_Delay(1000);//连接WiFiUART_Printf(&huart2, "AT+CWJAP=\"%s\",\"%s\"\r\n",WIFI_NAME,WIFI_PASSWORD);
}

ESP8266.h

/** ESP8266.h**  Created on: Aug 11, 2025*      Author: ccc*/#ifndef ESP8266_H_
#define ESP8266_H_#include "head.h"#define MQTT_BROKER        "192.168.124.20"  //服务器地址ip
#define MQTT_PORT          1883	//服务器端口号  1883不限制端口号
#define MQTT_CLIENT_ID     "mcus-test-client"	//客户端唯一标识
#define MQTT_USERNAME      "user"  //用户名,如不需要可留空
#define MQTT_PASSWORD      "pass"  //密码,如不需要可留空
#define MQTT_TOPIC	       "test2" //要订阅的主题
#define WIFI_NAME          "IPhone"//wifi名
#define WIFI_PASSWORD  	   "lyl975418"//wifi密码#define RESP_BUFFER_SIZE 256
extern char esp_response[RESP_BUFFER_SIZE];
extern uint16_t resp_index;
extern uint8_t esprx_byte;void Inint_esp8266(void);
void ESP8266_ReceiveHandler(UART_HandleTypeDef *huart);
void Publish_Message(const char *message);
void ESPWIFI_Reconnect(void);
#endif /* ESP8266_H_ */

comation.c

/** comation.c**  Created on: Aug 11, 2025*      Author: ccc*/
#include "head.h"
/** @brief格式化输出到串口上* @param* @return* */
void UART_Printf(UART_HandleTypeDef *USARTx, char *fmt,...)
{unsigned char UsartPrintfBuf[296];va_list ap;unsigned char *pStr = UsartPrintfBuf;va_start(ap, fmt);vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化va_end(ap);while(*pStr != '\0'){HAL_UART_Transmit (USARTx ,(uint8_t *)pStr++,1,10);}}
/* @brief串口中断回调函数* @param* @return* */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART2){//HAL_UART_Receive_IT(&huart2, &esprx_byte, 1);ESP8266_ReceiveHandler(&huart2);}}

comation.h

/** comation.h**  Created on: Aug 11, 2025*      Author: ccc*/#ifndef COMATION_H_
#define COMATION_H_
#include "head.h"void UART_Printf(UART_HandleTypeDef *USARTx, char *fmt,...);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
#endif /* COMATION_H_ */

head.h

/** head.h**  Created on: Aug 11, 2025*      Author: ccc*/#ifndef HEAD_H_
#define HEAD_H_
/**@系统头文件*/
#include "main.h"
#include "i2c.h"
#include "icache.h"
#include "usart.h"
#include "gpio.h"
#include "stdarg.h"
#include "stdio.h"
#include "stdbool.h"
#include <string.h>
#include <stdlib.h>/** 自定义头文件* */
#include "ESP8266.h"
#include "comation.h"
#endif /* HEAD_H_ */

2.4 效果展示

我们使用python写的客户端发布主题时,esp8266可以收到在串口助手展示

同样的我们使用esp8266发送消息时python也可以收到

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92988.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92988.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis认识缓存击穿

缓存击穿是指 一个非常热点的数据&#xff08;被高并发访问&#xff09;在缓存中过期失效的瞬间&#xff0c;导致大量并发请求同时穿透缓存&#xff0c;直接落到底层数据库&#xff0c;造成数据库瞬间压力剧增甚至崩溃的现象。关键特征和你的描述解析“数据库没有就需要命中的数…

TF-IDF——红楼梦案例

目录 用 TF-IDF 挖掘《红楼梦》各回目核心关键词&#xff1a;一个 NLP 实践案例 一、案例背景与目标 二、实现步骤 步骤 1&#xff1a;数据准备与分卷处理 1. 导入模块与创建目录 2. 打开源文件并初始化变量 3. 逐行处理文本内容 4. 写入卷内容并过滤前两行 5. 关闭最后…

【软考中级网络工程师】知识点之 IP QoS 技术

目录一、IP QoS 技术是什么1.1 定义与概念1.2 重要性和应用场景二、IP QoS 技术原理2.1 流量分类与标记2.2 流量整形与限速2.3 拥塞避免与管理2.4 资源预留协议&#xff08;RSVP&#xff09;三、IP QoS技术模型3.1 尽力而为服务模型3.2 综合服务模型&#xff08;IntServ&#x…

Git 常用命令速查表

一、仓库初始化与克隆命令说明git init在当前目录初始化本地仓库git clone <远程仓库地址>克隆远程仓库到本地&#xff08;例&#xff1a;git clone https://github.com/user/repo.git&#xff09;二、文件状态与提交命令说明git status查看工作区 / 暂存区文件状态git a…

第五十四章:AI模型的“压缩大师”:GPTQ、AWQ与bitsandbytes实战量化

AI模型压缩前言&#xff1a;让训练好的AI模型“轻装上阵”第一章&#xff1a;回顾与挑战&#xff1a;训练后量化&#xff08;PTQ&#xff09;的必要性1.1 量化原理与精度类型回顾&#xff1a;FP32到INT4/INT81.2 PTQ&#xff08;Post-Training Quantization&#xff09;&#x…

在Word和WPS文字一页中实现一栏与多栏混排

在Word和WPS文字的一页中如何实现分栏和不分栏的内容混排&#xff1f;只需要使用分栏功能。把光标放在要分栏的位置&#xff0c;插入分栏即可&#xff0c;最关键的点是分栏应用于“插入点之后”。如果不需要分栏&#xff0c;则栏数选择为1即可。一、Word和WPS文字的分栏设置路径…

Python调用C/C++函数库的多种方法与实践指南

Python作为一门高级编程语言&#xff0c;以其简洁的语法和丰富的库生态赢得了开发者的青睐。然而&#xff0c;在计算密集型任务中&#xff0c;Python的性能往往无法满足要求。Python调用C/C函数库成为提升应用性能的关键技术路径&#xff0c;通过将底层计算逻辑用C/C实现&#…

【21】OpenCV C++实战篇——OpenCV C++案例实战二十七《角度测量》

OpenCV C案例实战二十七《角度测量》 利用opencv获取三点所形成直线的角度

程序在计算机中的运行方式

程序在计算机中的运行是一个涉及硬件、操作系统和软件协同工作的复杂过程。我们可以将其分解为几个关键阶段来理解&#xff1a;1. 程序的诞生&#xff1a;从源代码到可执行文件 编写代码&#xff1a;程序员使用高级编程语言&#xff08;如C、Python、Java&#xff09;编写源代码…

虚拟卡券管理平台详细设计文档

文章目录**1. 文档概述**1.1 目标1.2 核心能力**2. 业务场景分析**2.1 用户场景2.2 关键业务流程卡券核销流程&#xff1a;**3. 整体架构设计**3.1 技术栈3.2 微服务拆分**4. 功能模块详细设计**▶ 4.1 卡券生命周期管理**4.1.1 卡券类型设计****4.1.2 关键状态机**▶ 4.2 卡券…

Oracle参数Process

RDBMS&#xff1a; 19.28 参考文档&#xff1a; IF:How to determine an optimum value for PROCESSES parameter (Doc ID 2012693.1) All About the Initialization Parameter PROCESSES and the Related Issues (Doc ID 2673195.1) How to calculate the proper value from …

【数据结构入门】树

目录 1.树的概念 父子结点 根节点|叶节点 结点的度 叶子结点或终端结点 兄弟结点 树的度 结点的层次 树的高度或深度 结点的祖先 堂兄弟结点 子孙 森林 2. 树的结构定义 2.1 左孩子右兄弟结构 2.2 数组表示法 3.树&非树 1.树的概念 树是一种非线性的数据结…

手把手教你用 Flink + CDC 实现 MySQL 数据实时导入 StarRocks(干货)

手把手教你用 Flink CDC 实现 MySQL 数据实时导入 StarRocks&#xff08;干货&#xff09; 如何利用 Apache Flink 结合 CDC&#xff08;Change Data Capture&#xff0c;变更数据捕获&#xff09;技术&#xff0c;将 MySQL 的数据实时导入 StarRocks&#xff0c;打造高效的实…

Rust:anyhow 高效错误处理库核心用法详解

以下是 anyhow 库在 Rust 中的核心用法详解&#xff08;结合最佳实践和示例&#xff09;&#xff1a; &#x1f530; 一、anyhow 的核心价值 用于简化错误处理&#xff0c;尤其适合&#xff1a; 需要快速原型开发的应用需要丰富错误上下文&#xff08;Context&#xff09;的场…

阿里云服务linux安装单机版

一、单机安装Redis 阿里教程 下载地址:redis下载地址 1、首先需要安装Redis所需要的依赖&#xff1a; yum install -y gcc tcl 2、下载Redis 注&#xff1a;也可以自己下好然后上传到云服务 wget https://gitcode.net/weixin_44624117/software/-/raw/master/software/Li…

python之uv使用

文章目录安装与更新standalonepip 安装创建以及初始化项目依赖管理uv run直接在命令行运行python代码片段直接运行项目中可执行脚本文件运行python包中快捷指令uv项目本地运行调试细节vscode 中运行调试uv项目命令行运行深入理解 uv lock, uv sync, uv lockuv lock 行为解析:uv…

【CV 目标检测】①——目标检测概述

一、目标检测概述 1.目标检测 目标检测&#xff08;Object Detection&#xff09;的任务是找出图像中所有感兴趣的目标&#xff0c;并确定它们的类别&#xff08;分类任务&#xff09;和位置&#xff08;回归任务&#xff09; 目标检测中能检测出来的物体取决于当前任务&…

C#图形库SciChart与ScottPlot及LiveCharts2对比

一.概述 1.SciChart SciChart 是一个专为企业级应用设计的高性能数据可视化库&#xff0c;提供跨平台的图表解决方案&#xff0c;支持 .NET、JavaScript、iOS 和 Android 等多个平台。它以卓越的渲染性能、丰富的专业图表类型和强大的交互功能著称&#xff0c; 广泛应用于金…

Win10电脑密码忘记如何进入操作系统

http://xq128.com/zj.htmlhttps://share.feijipan.com/s/LbFdbUKl下载后&#xff0c;准备一个空的U盘&#xff0c;大于4G。将U盘制作为PE盘。之后将制作好的PE盘插入到电脑中&#xff0c;启动待去除密码的电脑台式机&#xff0c;启动后一直按住F12&#xff0c;进入BIOS。选择下…

[免费]基于Python的网易云音乐热门歌单可视化大屏项目(flask+pandas+echarts+request库)【论文+源码+SQL脚本】

大家好&#xff0c;我是python222_小锋老师&#xff0c;看到一个不错的基于Python的网易云音乐热门歌单可视化大屏项目(flaskpandasechartsrequest库)&#xff0c;分享下哈。 项目视频演示 【免费】基于Python的网易云音乐热门歌单可视化大屏项目(flaskpandasecharts爬虫) Py…