Clion开发STM32之ESP8266系列(四)
前言
上一篇: Clion开发STM32之ESP8266系列(三)
本篇主要内容
- 实现esp8266需要实现的函数
- 串口3中断函数的自定义(这里没有使用HAL提供的)
- 封装esp8266服务端的代码和测试
正文
主要修改部分
核心配置头文件(添加一些宏定义)
- sys_core_conf.h文件中


实现esp8266需要实现的函数

源码
/******************************************************************************** @author scl* @email shchlu188@163.com* @brief 实现esp8266的驱动******************************************************************************/
#include "module_esp8266.h"
#include "bsp.h"extern data_frame_t esp_rx_frame;static void sys_delay(uint32_t ms) {HAL_Delay(ms);
}/*** @brief esp8266 驱动外设初始化*/
void esp8266_driver_init() {/*设置系esp8266延时回调*/esp8266_set_delay_call(sys_delay);/*配置 CH_PD 引脚*/gpio_init(GPIOB, GPIO_PIN_8, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_HIGH);/* 配置 RST 引脚*/gpio_init(GPIOB, GPIO_PIN_9, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_HIGH);/*串口配置*/com3_init(115200);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8 | GPIO_PIN_9, GPIO_PIN_SET);/*开启串口中断*/UART_ENABLE_IT(USART3, UART_IT_RXNE); /** 开启串口中断*/UART_ENABLE_IT(USART3, UART_IT_IDLE); /** 开启串口空闲中断*/
}/*** @brief esp8266 复位引脚* @param flag true: 置高; false: 置低*/
void esp8266_rst_pin(bool flag) {if (flag) {pin_high(GPIOB, GPIO_PIN_9);} else {pin_low(GPIOB, GPIO_PIN_8);}
}/*** @brief esp8266 使能引脚* @param flag true: 使能*/
void esp8266_ch_enable(bool flag) {if (flag) {pin_high(GPIOB, GPIO_PIN_8);} else {pin_low(GPIOB, GPIO_PIN_8);}
}/*** @brief esp8266 发送数据* @param data* @param len*/
void esp8266_send(void *data, uint16_t len) {HAL_UART_Transmit(com_handle_get(com3), data, len, 1000);
}/*** @brief 清空接收缓冲区*/
void esp8266_clear_buf(void) {esp_rx_frame.InfAll = 0;
}/*** @brief esp8266 接收数据* @return 接收数据*/
char *esp8266_rec() {if (esp_rx_frame.InfBit.frame_finished_flag != 0) {/*添加结束符*/esp_rx_frame.p_rx_buf[esp_rx_frame.InfBit.frame_len] = '\0';esp_rx_frame.InfAll = 0;// 清除一次标志位return esp_rx_frame.p_rx_buf;}return NULL;
}/*** @brief esp8266 构造指令的缓存区* @return*/
char *esp8266_get_cmd_buf() {static char esp8266_buf[200] = {0};return esp8266_buf;
}
对应的串口3中断函数的编写

extern data_frame_t esp_rx_frame;static inline void esp8266_tcp_server_IRQHandler() {uint8_t ucTemp;if (UART_GET_FLAG(USART3, UART_FLAG_RXNE)) {ucTemp = READ_REG(USART3->DR);// 读取数据if (esp_rx_frame.InfBit.frame_len < (esp_rx_frame.rx_buf_len - 1)) {esp_rx_frame.p_rx_buf[esp_rx_frame.InfBit.frame_len++] = ucTemp;}}//数据帧接收完毕if (UART_GET_FLAG(USART3, UART_FLAG_IDLE)) {esp_rx_frame.InfBit.frame_finished_flag = 1;// 添加结束符esp_rx_frame.p_rx_buf[esp_rx_frame.InfBit.frame_len] = '\0';//由软件序列清除中断标志位(先读USART_SR,然后读USART_DR)_UART_CLEAR_PEFLAG(USART3);}
}void USART3_IRQHandler(void) {/* HAL库中断处理函数*/// HAL_UART_IRQHandler(&com3_handle);/* 自定义中断处理函数*/esp8266_tcp_server_IRQHandler();
}
封装esp8266服务端的代码(针对驱动层再进行一个封装)
头文件
/******************************************************************************** @author scl* @email shchlu188@163.com******************************************************************************/#ifndef STM32F103VET6_ESP8266_ESP8266_SERVICE_H
#define STM32F103VET6_ESP8266_ESP8266_SERVICE_H#include "service_include.h"
/*wifi 账号*/
#define WIFI_SSID "账号"
/*wifi 密码*/
#define WIFI_PWD "密码"
/*尝试执行次数*/
#define TRY_CNT 3
/*本地IP配置*/
#define LOCAL_SERVER_IP "192.168.199.12"
/*本地端口配置*/
#define LOCAL_SERVER_PORT 8000
/*宏定义调试日志*/
#define esp_ps(fmt, ...) os_ps(fmt,##__VA_ARGS__)
/*************************************ESP 服务端 STA模式**********************************************/
/*** @brief esp8266 在sta模式下初始化 sever* @return*/
bool esp_sta_tcp_server_init(void);
/*** @brief esp8266 在sta模式下获取ip* @param dstIp 保存ip* @param len dstIp的长度* @return*/
bool esp_sta_tcp_server_get_ip(char *dstIp, uint8_t len);
/*** @brief esp8266 客户端请求处理* @param data 接收的数据* @param len 数据长度* @return*/
bool esp_sta_tcp_server_request_handle(char *data, uint16_t len);#endif //STM32F103VET6_ESP8266_ESP8266_SERVICE_H
源文件
/******************************************************************************** @author scl* @email shchlu188@163.com******************************************************************************/#include "esp8266_service.h"
#include "module_esp8266.h"
#include "bsp.h"/*** @brief 禁止接收数据(静态内联函数)*/
sys_force_static_inline void esp_disable_rec() {UART_DISABLE_IT(USART3, UART_IT_RXNE);
}sys_force_static_inline void esp_enable_rec() {UART_ENABLE_IT(USART3, UART_IT_RXNE);
}bool esp_sta_tcp_server_init(void) {esp_ps("--esp_sta_tcp_server_init start---\r\n");/*使能信号*/esp8266_ch_enable(true);/*测试AT指令*/try_cnt_run (esp8266_base_at_cmd_test(10, 500), 1);esp_ps("esp8266_base_at_cmd_test ok\r\n");/*动态分配IP地址*/try_cnt_run(esp8266_dhcp_cur_set(sta_mode, true, -1), TRY_CNT);/* 设置为STA模式 */try_cnt_run(esp8266_wifi_mode_cur_set(sta_mode, -1), TRY_CNT);esp_ps("esp8266_mode_cur_set ok\r\n");/* 设备本地设备ip*/try_cnt_run(esp8266_ip_sta_cur_set(LOCAL_SERVER_IP, NULL, NULL, -1), TRY_CNT);esp_ps("esp8266_ip_sta_cur_set ok\r\n");/*连接WiFi*/try_cnt_run (esp8266_wifi_join_cur_set(WIFI_SSID, WIFI_PWD, NULL, -1), TRY_CNT);esp_ps("esp8266_wifi_join_cur_set ok\r\n");/*允许多连接*/try_cnt_run (esp8266_mul_connect_set(true, -1), TRY_CNT);esp_ps("esp8266_mul_connect_set ok\r\n");/*开启服务器模式*/try_cnt_run (esp8266_server_tcp_start(true, LOCAL_SERVER_PORT, -1), TRY_CNT);esp_ps("esp8266_server_tcp_start ok\r\n");/*设置服务器链接超时时间*/try_cnt_run (esp8266_server_tcp_timeout_set(20, -1), TRY_CNT);esp_ps("esp8266_server_tcp_timeout_set ok\r\n");esp_ps("--esp_sta_tcp_server_init end---\r\n");return true;
}bool esp_sta_tcp_server_get_ip(char *dstIp, uint8_t len) {esp_ps("--esp_sta_tcp_server_get_ip start---\r\n");try_cnt_run (esp8266_ip_sta_inquire(dstIp, len, -1), TRY_CNT);esp_ps("--esp_sta_tcp_server_get_ip end---\r\n");return true;
}
/*** @brief 解析接收的数据* @param rec_data 接收的数据* @param no_id socket id* @param data_len 发送的数据长度* @return 实际数据的位置*/
sys_force_static_inline char *parse_rec_data(char *rec_data, uint8_t *no_id, uint16_t *data_len) {static char *pre_str = "+IPD,";char *p_data = strstr(rec_data, pre_str);// 数据解析错误 +IPD,0,2:12if (!p_data) return false;/*跳过前缀*/p_data += strlen(pre_str);/*解析socket id 号*/*no_id = strtol(p_data, &p_data, 10);if (!*p_data) return false;/*解析数据长度 */*data_len = strtol(p_data + 1, &p_data, 10);if (!*p_data) return false;/*获取数据*/p_data += 1;return p_data;
}bool esp_sta_tcp_server_request_handle(char *data, uint16_t len) {/* 禁止esp多个客户端同时发送数据 */uint16_t data_len = 0;/*实际客户端发送的数据长度*/uint8_t socket_id;/*实际客户端连接的端口号*/bool result_flag = true;/*禁止接收,保证同一时间只只处理一个请求 */esp_disable_rec();/*实际客户端发送的数据位置*/char *p_data = parse_rec_data(data, &socket_id, &data_len);if (p_data) {// todo 这里就是做业务逻辑控制的地方,目前只是回显esp_ps("parse_rec_data:%d %d %s\r\n", socket_id, data_len, p_data);if (esp8266_server_tcp_send_to(socket_id, p_data, data_len, -1)) {esp_ps("response ok\r\n");} else {esp_ps("response error\r\n");}} else {result_flag = false;}/*清除这次的请求数据,保证下次数据为最新的*/esp8266_clear_buf();/*开启请求,保证同一时间只只处理一个请求 */esp_enable_rec();return result_flag;
}
esp8266驱动配置文件的编写

/******************************************************************************** @author scl* @email shchlu188@163.com******************************************************************************/
#include "app_conf.h"
#include "module_esp8266.h"
#include "service.h"/*创建数据接收帧*/
static char rx_buf[1024] = {0};
data_frame_t esp_rx_frame = {.p_rx_buf=rx_buf, .rx_buf_len=1024};static void driver_init(void) {/*esp8266初始化*/esp8266_driver_init();
}/*这句话就是将驱动导出到段中*/
DRIVER_EXPORT(esp8266_driver, driver_init);/*** 测试阶段暂时使用此方法* */
void app_run() {if (esp_sta_tcp_server_init()) {os_ps("--esp_sta_tcp_server_init ok--\r\n");while (1) {if (esp_rx_frame.InfBit.frame_finished_flag) {esp_sta_tcp_server_request_handle(esp_rx_frame.p_rx_buf, esp_rx_frame.InfBit.frame_len);}}} else {os_ps("--esp_sta_tcp_server_init error--\r\n");}}
代码测试
- 本次设置esp8266模块的IP为192.168.199.12,端口号为8000
主入口函数调整
### 下载程序
观察日志记录

用客户端去连接192.168.199.12:8000

客户端

查看串口
- 接收数据正常


结尾
- ESP8266系列的章节也就更新完成,目前基础功能模板工程已经完。
- 目前可以根据此工程执行对应的指令控制的逻辑了。
- 后续在此基础之上设计一个指令集动态加载服务器接收处理和响应的框架。
- 完整的项目已上传到gitee,有需要自行查看开头结尾的git地址.
下个系列的目标
- 整合Freertos
- 整合Modbus协议和自定义协议框架
相关文章:
Clion开发STM32之ESP8266系列(四)
前言 上一篇: Clion开发STM32之ESP8266系列(三) 本篇主要内容 实现esp8266需要实现的函数串口3中断函数的自定义(这里没有使用HAL提供的)封装esp8266服务端的代码和测试 正文 主要修改部分 核心配置头文件(添加一些宏定义) sys_core_conf.h文件中…...
降本增效,StarRocks 在同程旅行的实践
作者:周涛 同程旅行数据中心大数据研发工程师 同程旅行是中国在线旅游行业的创新者和市场领导者。作为一家一站式平台,同程旅行致力于满足用户旅游需求,秉持 "让旅行更简单、更快乐" 的使命,主要通过包括微信小程序、AP…...
INTP型人格适合选择哪些专业?
INTP人格内倾理性人格、具有强烈的好奇心、创造性和独立性的特点。他们善于独立思考和寻找问题的本质,并对抽象的想法和理论感兴趣。 INTP人格的人具有很强的逻辑思维和分析能力,他们的思维方式非常系统,追求完美和准确。因此他们适合选择需…...
【LeetCode热题100】打卡第16天:组合总和
文章目录 组合总和⛅前言🔒题目🔑题解 组合总和 ⛅前言 大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏! 精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数…...
tinkerCAD案例:1.戒子环
基本戒指 在本课中,您将学习使用圆柱形状制作戒指。来吧! 说明 将圆柱体拖动到工作平面上并使其成为孔。 圆柱体应缩放以适合其制造手指。 在本例中,我们将使用 17mm 作为直径,但请根据您的需要随意调整尺寸。 将“圆柱”形状拖…...
RPC接口测试技术-Tcp 协议的接口测试
【摘要】 首先明确 Tcp 的概念,针对 Tcp 协议进行接口测试,是指基于 Tcp 协议的上层协议比如 Http ,串口,网口, Socket 等。这些协议与 Http 测试方法类似(具体查看接口自动化测试章节)…...
MyBatis Plus基本用法-SpringBoot框架
依赖 使用 Mybatis Plus 框架时,需要添加以下依赖: <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>latest-version</version> </dependency…...
指针--指针变量的定义和初始化
存放变量的地址需要一种特殊类型的变量,这种特殊的数据类型就是指针(Pointer)。 具有指针类型的变量,称为指针变量,它时专门用于存储变量的地址值和变量。 其定义形式如下: 类型关键字 * 指针变量名&#x…...
Web基本概念
一、前言 World Wide Web的简称,是一个由许多互相链接的超文本组成的系统,通过互联网访问 (为用户提供信息) 静态网页 仅适用于不能经常更改内容的网页; 动态网页 网络编程技术创建的页面;通过在传统的静态…...
Niagara—— Texture Sample 与 Particle Subuv 区别
目录 一,Texture Sample 二,Particle Subuv 一,Texture Sample 此节点是最基本的采样节点,依据UV坐标来采样Texture; MipValueMode,设置采样的Mipmap Level; None,根据当前Texture…...
如何在食品行业运用IPD?
食品是我国重要的民生产业之一,是保障和满足人民群众不断增长消费需求的重要支撑。食品指各种供人食用或者饮用的成品和原料以及按照传统既是食品又是药品的物品,包括加工食品,半成品和未加工食品,不包括烟草或只作药品用的物质。…...
如何用pandas进行条件分组计算?
Pandas提供了强大的分组聚合功能,可以轻松进行条件分组计算和统计。本文通过一个例子,展示如何使用Pandas的.groupby()和.agg()方法进行条件分组计算。 准备数据 假设有这样一个字典数据: dict { 姓名: [张三,李四,王五&#x…...
tomcat如何调优,涉及哪些参数?
Tomcat是一个流行的开源Java Servlet容器,用于部署和管理Java Web应用程序。调优Tomcat可以提高性能、并发处理能力和稳定性。以下是一些常见的Tomcat调优参数和技巧: 1.调整内存参数: -Xms:指定Tomcat启动时的初始堆内存大小。 -…...
java培训机构学校教学教务选课管理平台springboot+vue
近年来,随着培训机构机构规模的逐渐增大,人工书写的方式已经不能满足如此庞大的数据。为了更好的适应信息时代的高效性,一个利用计算机来实现培训机构教务管理工作的系统将必然诞生。基于这一点,设计了一个培训机构教务管理系统&a…...
半导体(TSS)放电管的两大选购注意事项及选型小策略
固体放电管,是以半导体工艺制作而成的,因此我们也称为半导体(TSS)放电管,它常在电路中并联使用,具备伏安特性。 TSS放电管在电路中类似开关,在正常工作时不动作,但一般被保护电路受到…...
05-使用Vue3 + Vue CLI 实现前端模块的搭建
1、环境准备 流程:安装node得到npm,使用npm安装vue cli(脚手架),使用vue cli创建项目。 Vue CLI版本和Node版本有关,用Node V12只能下载到Vue CLI V4.X,必须用Node V18才能下载到Vue CLI V5.X IDEA支持配置多个版本的Node,类似配置多个JDK。 node.js安装 1、官网下载…...
3.1 增加多进程执行playwright
增加了多进程的方式执行测试代码,对代码改动比较大 1、case case目录依然是自动生成 2、config dir_collection.py新增了配置 mkdir_collections [case,log,img, ] del_collections [results,report ] del_regex temp3、data/img/log/resource/video data/im…...
关于单片机的时钟浅谈及STM32F103/F030单片机的内外时钟切换问题
绪论 本文主要讲解单片机的时钟系统的相关知识,并进行超频测试,同时介绍如何在STM32F0单片机上进行内外时钟的切换,在不使用外部晶振或者外部晶振不启动时自动切换内部时钟的方法。 一、杂谈 问题来源于群里的一次问答: 诚然&…...
centos6.10环境下安装php7.4(基于WLNMP包)
centos6系统已经被官网停止维护,要安装软件必须用第三方的RPM包,下面使用yum安装php7.4正式版,当前基于WLNMP提供的一键安装包来安装 1、添加epel源 yum install epel-release yum install epel-release 2、添加WLNMP一键安装包源 rpm -iv…...
Qt使用第三方库openssl进行RSA加密解密操作详解
一、openssl库的编译,可以参考文档: https://blog.csdn.net/liang19890820/article/details/51658574/ 因为我这里使用的是windows操作系统,可以直接下载exe格式的安装文件,直接安装即可,就包含了我们需要的头文件和库文件,省去了编译操作。exe安装文件下载地址: htt…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
