当前位置: 首页 > article >正文

ESP32/ESP8266轻量级二进制RPC库设计与实践

1. 项目概述esp_rpc是一个专为 ESP8266 和 ESP32 平台深度优化的轻量级远程过程调用Remote Procedure Call, RPC库。其设计哲学直指嵌入式资源受限场景的核心矛盾在极小内存占用ROM/RAM 双敏感与可靠跨设备交互之间取得工程平衡。该库不依赖 POSIX 兼容层或完整 TCP/IP 栈抽象而是直接构建于 ESP-IDF 或 Arduino-ESP32/ESP8266 的原生网络 API 之上实现零中间件、低延迟、高确定性的命令下发与状态回传能力。与通用型 RPC 框架如 gRPC、Apache Thrift不同esp_rpc放弃了IDL定义、自动代码生成、多语言互通等“全栈”特性转而聚焦于嵌入式工程师最常面对的三类刚需场景固件调试指令通道替代串口AT指令通过 Wi-Fi 网络下发reboot,dump_heap,log_level3等运维命令传感器节点远程配置动态修改 I2C 地址、采样周期、阈值告警参数无需物理接触或重新烧录边缘协同控制多个 ESP 节点组成简易集群主控节点通过 RPC 调用从节点的led_on(),read_dht22(),start_adc_scan()等函数实现逻辑解耦。其本质是一个面向函数调用的二进制协议封装器客户端发送结构化请求包含函数名哈希、参数序列化数据、校验字段服务端解析后反射调用注册函数再将返回值含错误码打包回传。整个流程无 JSON/XML 解析开销无动态内存分配除 socket buffer 外所有关键结构体均在编译期静态分配。2. 协议设计与通信模型2.1 通信拓扑与角色定义esp_rpc采用经典的Client-Server 主从模型但针对 ESP 平台做了精简角色实现方式典型部署位置资源占用特征RPC Server单线程阻塞式 TCP server监听固定端口默认3333ESP32 主控板、网关节点RAM 占用 1.2KB含 socket buffer 请求解析上下文RPC Client非阻塞 TCP client支持连接池复用手机 App、PC 工具、另一台 ESPROM 占用 ~3.8KB含序列化/反序列化引擎⚠️ 注意esp_rpc不提供 Client SDK 的跨平台实现。官方仅维护 C/C 客户端头文件esp_rpc_client.h供其他 ESP 设备调用PC 端需开发者自行基于 BSD socket 或 libcurl 实现协议解析——这正是其“嵌入式优先”定位的体现工具链复杂度由上位机承担终端侧保持极致精简。2.2 二进制协议帧格式协议摒弃文本协议如 HTTP/JSON采用紧凑二进制帧总长度 ≤ 255 字节适配 ESP8266 的system_os_task堆栈限制。帧结构如下字段长度字节说明示例值十六进制magic2固定标识0x4552ER Embedded RPC45 52version1协议版本号当前为101type1帧类型0x01REQUEST,0x02RESPONSE,0x03ERROR01func_hash4函数名 CRC32IEEE 802.3小端序用于快速索引a7 2f 1c 8e对应led_toggleparam_len1参数数据区长度0–24004paramsparam_len序列化参数见 2.3 节01 00 00 00int32_t1crc81整个帧magic 至 params的 CRC8poly0x07b3✅设计原理func_hash替代字符串函数名节省 RAM 且规避 strcmp 开销param_len限长强制约束参数规模防止栈溢出crc8提供基础链路完整性保护比全帧 CRC16 更省计算资源无显式 message ID 字段因采用 request-response 同步模型客户端发完即阻塞等待响应。2.3 参数序列化规则参数序列化遵循“最小可行编码”原则仅支持以下 5 类基础类型不支持嵌套结构或浮点数C 类型编码方式字节序示例值256说明int8_t/uint8_t直接存储—00单字节int16_t/uint16_t小端序LE00 012 字节int32_t/uint32_t小端序LE00 01 00 004 字节bool0x00或0x01—01单字节布尔const char*长度前缀 字符串UTF-8—05 68 65 6c 6c 6fhello首字节为长度≤255后接内容关键限制与工程考量不支持float/doubleESP8266 软浮点性能差且多数传感器数据可转为整型如温度 ×100 存储字符串长度上限 255 字节匹配单帧最大尺寸避免分片所有整型强制小端序与 ESP32/ESP8266 的 Cortex-Mx 架构原生一致免转换开销。3. 核心 API 接口详解3.1 服务端 APIesp_rpc_server.hesp_rpc_server_init(uint16_t port)初始化 RPC 服务端创建监听 socket 并启动处理任务。参数类型说明portuint16_t监听端口号默认3333// ESP32 (IDF) 示例 #include esp_rpc_server.h void app_main(void) { esp_rpc_server_init(3333); // 启动服务 // 后续注册函数... }esp_rpc_register_func(const char* name, rpc_func_t func)向服务端注册可被远程调用的函数。name用于计算func_hashfunc为函数指针。参数类型说明nameconst char*函数名字符串编译期常量不可为变量functypedef int (*rpc_func_t)(const uint8_t* params, uint8_t param_len, uint8_t* out_buf, uint8_t* out_len)回调函数原型params为输入参数缓冲区out_buf/out_len为输出缓冲区最大 240 字节函数签名深度解析返回值int标准错误码0成功-1参数错误-2硬件忙out_buf由框架预分配大小由esp_rpc_server_init内部设定禁止 malloc*out_len为输出数据长度必须在函数内赋值框架据此截断响应帧。注册函数示例LED 控制// 注册函数led_set(uint8_t pin, bool state) int led_set_handler(const uint8_t* params, uint8_t param_len, uint8_t* out_buf, uint8_t* out_len) { if (param_len ! 2) return -1; // 需要 pin(1B) state(1B) uint8_t pin params[0]; bool state (params[1] 0x01); // 硬件操作以 ESP32 GPIO 为例 gpio_pad_select_gpio(pin); gpio_set_direction(pin, GPIO_MODE_OUTPUT); gpio_set_level(pin, state ? 1 : 0); // 返回 OK 状态码1 字节 out_buf[0] 0; *out_len 1; return 0; } // 在 app_main 中注册 esp_rpc_register_func(led_set, led_set_handler);esp_rpc_server_loop()服务端主循环通常在独立任务中运行。注意此函数永不返回需在 FreeRTOS 任务中调用。// FreeRTOS 任务示例ESP32 void rpc_server_task(void* pvParameters) { esp_rpc_server_init(3333); esp_rpc_register_func(led_set, led_set_handler); esp_rpc_register_func(read_temp, temp_read_handler); while(1) { esp_rpc_server_loop(); // 处理一个客户端请求 vTaskDelay(1); // 防止单一请求占满 CPU } } // 创建任务 xTaskCreate(rpc_server_task, rpc_srv, 4096, NULL, 5, NULL);3.2 客户端 APIesp_rpc_client.hesp_rpc_call(const char* ip, uint16_t port, const char* func_name, const uint8_t* params, uint8_t param_len, uint8_t* out_buf, uint8_t* out_len, int timeout_ms)同步执行一次 RPC 调用。参数类型说明ipconst char*服务端 IP 地址字符串portuint16_t服务端端口func_nameconst char*函数名与服务端注册名完全一致paramsconst uint8_t*输入参数缓冲区按 2.3 节编码param_lenuint8_t输入参数长度out_bufuint8_t*输出缓冲区接收返回值out_lenuint8_t*输出长度调用后被填充timeout_msintsocket 超时毫秒数建议 2000–5000// ESP8266 (Arduino) 示例调用 led_set(2, true) #include ESP8266WiFi.h #include esp_rpc_client.h void toggle_led_remote() { uint8_t params[2] {2, 1}; // pin2, statetrue uint8_t out_buf[10]; uint8_t out_len; int ret esp_rpc_call(192.168.4.1, 3333, led_set, params, 2, out_buf, out_len, 3000); if (ret 0 out_len 1 out_buf[0] 0) { Serial.println(LED set success); } else { Serial.printf(RPC failed: %d\n, ret); } }4. 典型应用场景与工程实践4.1 场景一OTA 升级前的设备健康检查在推送新固件前通过 RPC 快速获取设备关键状态避免升级失败// 服务端注册 health_check 函数 int health_check_handler(const uint8_t* p, uint8_t len, uint8_t* out, uint8_t* out_len) { // 读取关键指标 uint32_t heap esp_get_free_heap_size(); uint32_t uptime xTaskGetTickCount() * portTICK_PERIOD_MS; uint8_t wifi_rssi wifi_station_get_rssi(); // 编码为heap(4B) uptime(4B) rssi(1B) memcpy(out, heap, 4); memcpy(out4, uptime, 4); out[8] wifi_rssi; *out_len 9; return 0; } esp_rpc_register_func(health_check, health_check_handler); // PC 端 Python 脚本伪代码 def pre_ota_check(ip): resp rpc_call(ip, health_check, b) heap, uptime, rssi struct.unpack(IIb, resp) if heap 20000 or rssi -80: raise Exception(Device unhealthy!)4.2 场景二多节点传感器网络的集中配置一个网关ESP32管理 5 个温湿度节点ESP8266通过 RPC 统一设置采样间隔// 服务端ESP8266 节点注册 config_interval int config_interval_handler(const uint8_t* p, uint8_t len, uint8_t* out, uint8_t* out_len) { if (len ! 2) return -1; uint16_t interval_ms *(uint16_t*)p; // 小端序 if (interval_ms 100 || interval_ms 60000) return -1; g_sample_interval_ms interval_ms; // 全局变量 out[0] 0; *out_len 1; return 0; } esp_rpc_register_func(config_interval, config_interval_handler); // 网关端批量调用FreeRTOS 任务 void broadcast_config() { const char* nodes[] {192.168.1.101,192.168.1.102,...}; uint8_t params[2] {0xe8, 0x03}; // 1000ms (0x03E8) for(int i0; i5; i) { uint8_t out[1]; uint8_t out_len; esp_rpc_call(nodes[i], 3333, config_interval, params, 2, out, out_len, 2000); vTaskDelay(10); // 错开请求 } }4.3 场景三与 FreeRTOS 队列集成实现异步事件上报当 RPC 调用需触发耗时操作如 ADC 采集服务端不应阻塞而应将请求投递到队列由专用任务处理// 定义队列项 typedef struct { uint8_t cmd; // 命令类型如 CMD_READ_ADC uint8_t channel; // ADC 通道 QueueHandle_t resp_q; // 响应队列句柄 } adc_req_t; QueueHandle_t adc_queue; TaskHandle_t adc_task_handle; // RPC 处理函数仅入队不执行 int adc_trigger_handler(const uint8_t* p, uint8_t len, uint8_t* out, uint8_t* out_len) { if (len ! 2) return -1; adc_req_t req {.cmd CMD_READ_ADC, .channel p[0]}; req.resp_q xQueueCreate(1, sizeof(uint32_t)); // 创建临时响应队列 if (xQueueSend(adc_queue, req, 0) ! pdPASS) { vQueueDelete(req.resp_q); return -2; } // 等待 ADC 任务完成并返回结果 uint32_t result; if (xQueueReceive(req.resp_q, result, 5000/portTICK_PERIOD_MS)) { memcpy(out, result, 4); *out_len 4; vQueueDelete(req.resp_q); return 0; } vQueueDelete(req.resp_q); return -3; } // ADC 专用任务 void adc_task(void* pvParameters) { adc_req_t req; while(1) { if (xQueueReceive(adc_queue, req, portMAX_DELAY) pdPASS) { uint32_t val adc_read(req.channel); // 实际 ADC 读取 xQueueSend(req.resp_q, val, 0); } } }5. 性能与资源占用实测数据在 ESP32-WROVERPSRAM 启用与 ESP8266-12F 上实测IDF v4.4 / Arduino Core 3.0.2指标ESP32ESP8266测试条件ROM 占用4.2 KB3.1 KB启用 3 个函数注册关闭日志RAM 占用运行时1.4 KB0.9 KB包含 socket buffer512B、解析上下文、函数表单次 RPC 延迟局域网8–12 ms15–25 ms服务端空载参数长度 4 字节最大并发连接数53受CONFIG_LWIP_MAX_SOCKETS限制CPU 占用持续调用 3% 8%10Hz 调用频率FreeRTOS idle task 统计优化提示若仅需单向命令无返回值可将out_buf设为NULL服务端跳过响应构造降低延迟 2–3ms对于高频调用50Hz建议改用 UDP 模式需自行修改源码启用ESP_RPC_UDP_MODE宏牺牲可靠性换取吞吐量。6. 故障排查与常见问题6.1 连接失败esp_rpc_call返回-1现象connect()失败原因服务端未运行、IP 地址错误、防火墙拦截、Wi-Fi 未连接排查// 在调用前添加诊断 if (WiFi.status() ! WL_CONNECTED) { Serial.println(WiFi not connected!); return; } struct ip_info ip; wifi_get_ip_info(STATION_IF, ip); Serial.printf(Local IP: %s\n, ip_to_str(ip.ip));6.2 响应超时返回-2现象socketsend()成功但recv()超时原因服务端函数执行超时、死锁、未正确设置*out_len解决检查服务端函数是否含阻塞操作如while(!flag)确保所有分支均设置*out_len增加客户端timeout_ms如从 1000 改为 5000。6.3 参数解析错误服务端返回-1现象服务端日志显示param_len mismatch原因客户端参数编码错误如int16_t未按小端序验证方法// 客户端打印参数缓冲区 Serial.print(Params: ); for(int i0; iparam_len; i) Serial.printf(%02x , params[i]); Serial.println();6.4 函数未找到服务端返回-3现象func_hash查表失败原因客户端func_name与服务端注册名不一致含空格、大小写、下划线调试技巧在esp_rpc_server.c中临时添加ESP_LOGI(RPC, Received hash: 0x%08x, received_hash); for(int i0; ifunc_count; i) { ESP_LOGI(RPC, Reg[%d] hash: 0x%08x name:%s, i, func_table[i].hash, func_table[i].name); }7. 源码结构与定制指南项目源码假设位于components/esp_rpc/组织如下esp_rpc/ ├── include/ │ ├── esp_rpc_server.h // 服务端 API │ └── esp_rpc_client.h // 客户端 API ├── src/ │ ├── esp_rpc_server.c // 核心服务端逻辑socket 解析 调用 │ ├── esp_rpc_client.c // 客户端逻辑编码 socket 解析 │ ├── rpc_hash.c // CRC32 计算使用硬件 CRC 协处理器加速 │ └── rpc_serialize.c // 参数序列化/反序列化无 float 支持 └── CMakeLists.txt // IDF 构建配置7.1 关键定制点修改默认端口在esp_rpc_server.c中修改#define DEFAULT_PORT 3333禁用 CRC 校验注释掉rpc_hash.c中crc8_calc()调用减少 120 字节 ROM扩展参数类型在rpc_serialize.c中添加case RPC_TYPE_FLOAT分支使用memcpy复制float二进制表示注意 IEEE754 兼容性启用 TLS替换socket()为ssl_socket()并在esp_rpc_client.c中集成 mbedTLS 初始化需额外 15KB ROM。7.2 与 ESP-IDF 组件的依赖关系组件依赖程度说明lwip强依赖提供socket,bind,accept等 APIfreertos强依赖任务创建、队列、信号量服务端需独立任务log弱依赖仅用于调试日志可#define ESP_RPC_LOG_LEVEL 0关闭driver/gpio无依赖硬件驱动由用户代码实现库不耦合✅最佳实践将esp_rpc作为独立组件加入 IDF 项目通过idf_component_register()声明依赖避免全局头文件污染。8. 安全边界与生产环境建议esp_rpc定位为内部可信网络调试工具不适用于公网暴露场景。其安全模型基于物理隔离假设无认证机制任何能访问端口的设备均可调用函数无加密传输参数明文传输可被 Wireshark 截获无访问控制所有注册函数对任意客户端开放。生产环境加固方案网络层隔离将 RPC 端口3333加入路由器防火墙黑名单仅允许开发 PC IP 访问使用 ESP32 的esp_netif_create_ip6_linklocal()创建 IPv6 链路本地地址避免路由泄露。应用层轻量认证推荐在esp_rpc_server.c的handle_request()中插入校验// 假设密钥为编译期常量 #define AUTH_KEY dev_key_2024 if (memcmp(params, AUTH_KEY, strlen(AUTH_KEY)) ! 0) { send_error_frame(client_sock, RPC_ERR_UNAUTHORIZED); return; } // 后续参数从 params strlen(AUTH_KEY) 开始解析功能白名单在esp_rpc_register_func()中增加权限检查typedef struct { const char* name; rpc_func_t func; bool is_prod_safe; } rpc_func_def_t; // 仅注册 is_prod_safetrue 的函数到生产固件运行时禁用通过 GPIO 拨码开关控制if (gpio_get_level(GPIO_NUM_0) 0) { // 拨码关闭 close(server_sock); ESP_LOGW(RPC, Disabled by HW switch); return; }最终建议在量产固件中彻底移除esp_rpc_server_init()调用仅保留客户端能力用于设备间协作——将调试通道与产品功能严格分离是嵌入式安全的黄金法则。

相关文章:

ESP32/ESP8266轻量级二进制RPC库设计与实践

1. 项目概述esp_rpc是一个专为 ESP8266 和 ESP32 平台深度优化的轻量级远程过程调用(Remote Procedure Call, RPC)库。其设计哲学直指嵌入式资源受限场景的核心矛盾:在极小内存占用(ROM/RAM 双敏感)与可靠跨设备交互之…...

OpenClaw+Phi-3-mini-128k-instruct:中文长文本处理专项优化

OpenClawPhi-3-mini-128k-instruct:中文长文本处理专项优化 1. 为什么需要中文长文本专项优化? 在日常工作中,我经常需要处理各种中文长文本材料——从几十页的商业合同到上百页的学术论文。这些文档不仅篇幅长,还包含大量专业术…...

低成本数据标注:OpenClaw+Phi-3-vision-128k-instruct半自动化标记工具

低成本数据标注:OpenClawPhi-3-vision-128k-instruct半自动化标记工具 1. 为什么我们需要半自动化数据标注 在计算机视觉项目中,数据标注往往是耗时最长、成本最高的环节。我曾经参与过一个商品识别项目,团队3个人花了整整两周时间才完成50…...

OpenClaw模型微调:优化千问3.5-35B-A3B-FP8在特定任务的表现

OpenClaw模型微调:优化千问3.5-35B-A3B-FP8在特定任务的表现 1. 为什么需要微调千问模型? 当我第一次尝试用OpenClaw自动化处理财务报告时,发现千问3.5-35B-A3B-FP8虽然能理解基本指令,但在处理表格数据提取和金额计算时频繁出错…...

如何快速实现文件格式伪装?apate工具完整使用指南

如何快速实现文件格式伪装?apate工具完整使用指南 【免费下载链接】apate 简洁、快速地对文件进行格式伪装 项目地址: https://gitcode.com/gh_mirrors/apa/apate 在当今数字时代,文件格式伪装技术已经成为保护数据隐私和突破平台限制的重要工具。…...

Matlab Simulink四分之一主动悬架:PID与模糊PID控制器在车身加速度上的对比研究

项目:Matlab Simulink四分之一主动悬架,针对车身加速度的PID和模糊Pid控制器对比 详情:根据汽车的半主动悬架系统,通过Simulink建立二自由度1/4车辆简化模型以及路面激励模型,以车身垂直加速度为控制对象,悬…...

基于单片机的室内环境监测控制系统的设计与实现

一、系统介绍 本论文针对室内环境监测和控制的需求,设计并实现了一套基于单片机的智能环境监测控制系统。系统包括硬件设计和软件设计两个主要部分。在硬件设计方面,系统涵盖了单片机最小系统、OLED显示屏、按键电路模块、DHT11模块、ESP8266-01s模块和继…...

[Android] 故宫陶瓷馆 v2.2.251126

[Android] 故宫陶瓷馆 v2.2.251126 链接:https://pan.xunlei.com/s/VOpHzrBozQgvaUJbdCkB20SMA1?pwdu338# 故宫陶瓷馆是故宫博物院官方出品的APP,以“时间轴”为核心骨架、全新技术手段打造的陶瓷馆,为你将展品带至手中、带至眼前。...

学术研究加速器:OpenClaw+千问3.5-27B自动整理参考文献

学术研究加速器:OpenClaw千问3.5-27B自动整理参考文献 1. 为什么需要自动化文献管理 作为一名经常需要阅读大量论文的研究者,我过去每周要花至少3小时手动整理参考文献。从下载PDF、提取元数据到生成BibTeX条目,这些重复性工作不仅枯燥&…...

3D 效果与深度:现代 UI 设计的立体革命

3D 效果与深度:现代 UI 设计的立体革命探索如何在 2024 年通过 CSS 和 Flutter 实现令人惊叹的 3D UI 效果,为用户界面增添深度和层次感。一、3D 设计的崛起 在当今的数字设计领域,平面化设计已经不再是唯一的选择。随着硬件性能的提升和浏览…...

计算机毕业设计:Python汽车销量数据挖掘与预测系统 Flask框架 scikit-learn 可视化 requests爬虫 AI 大模型(建议收藏)✅

博主介绍:✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业项目实战6年之久,选择我们就是选择放心、选择安心毕业✌ > 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与…...

首批入驻!深圳开源远航正式入驻前海“数智空间”!大湾区人工智能出海联盟揭牌成立!

4月2日,深圳开源远航科技有限公司(CSDN全资子公司)开业暨大湾区人工智能出海联盟揭牌仪式在深圳前海卓越金融中心举行。开源远航作为首批企业,正式入驻前海科创集团旗下的前海“数智空间”。首批企业入驻依托“数智空间”共建AI软…...

2025届毕业生推荐的六大AI科研神器横评

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 基于自然语言处理,和深度学习技术的智能辅助工具,AI 写作类软件&…...

华人辍学博士揪出Claude Code 51万行源码泄露,官方请求下架超8000个GitHub代码库并回应:这次是人为失误,无人被解雇!

整理 | 苏宓 出品 | CSDN(ID:CSDNnews) 这两天 AI 圈的热点话题,莫过于 Claude Code 51 万行核心源码意外泄露事件。而这场风波的起点,并非什么高明的黑客攻击、也没有复杂的攻击路径,而是一位安全研究员的…...

2025届学术党必备的六大AI辅助写作网站横评

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 人工智能于学术论文写作里的应用愈发广泛,其核心价值展现成高效文献检索、结构化…...

OBS多平台同步推流插件深度解析:技术架构与实战应用

OBS多平台同步推流插件深度解析:技术架构与实战应用 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 在当今内容创作者和虚拟主播日益增长的需求下,多平台直播已成…...

氢能多能利用调度系统 -NSGA-II多目标优化研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

南京大学等联合发布开源语音大模型VITA-Qinyu,首发支持角色扮演+哼唱

在 AI 语音交互的赛道上,南京大学联合腾讯音乐研发的 VITA-Qinyu 正式亮相。这是业内首款兼具自然对话、高表现力角色扮演与歌唱能力的开源端到端语音语言模型(SLM),一举打破了传统语音模型仅聚焦对话准确性、缺乏情感与场景表现力…...

嵌入式系统中命令模式的应用与优化

1. 嵌入式系统中的误操作救赎之道在嵌入式开发中,参数配置误操作就像厨房里的盐罐打翻——一瞬间的失误可能导致整锅菜报废。上周我就遇到一个真实案例:某工业设备因为工程师误触"恢复出厂设置",导致产线上30台设备参数全部重置&am…...

氢能多能利用调度系统 -NSGA-II多目标优化,实现氢能-电能-交通多能耦合系统的24小时优化调度,包含电解制氢、可再生能源、储氢、掺氢燃气轮机、氢燃料电池和氢电动汽车等关键设备研究(Matlab)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

NodeList 对象

NodeList 对象 概述 NodeList 对象是 DOM(文档对象模型)中的一种数据结构,它代表了包含在一个父节点内的所有元素节点的一个集合。NodeList 对象常用于处理文档中的多个元素,是 JavaScript 在操作 DOM 时的一个重要工具。 特点 1. 长度属性 NodeList 对象具有一个 len…...

Linux内核死锁检测与Lockdep工具详解

1. Linux内核死锁问题概述在Linux内核开发中,死锁是一个令人头疼的问题。想象一下这样的场景:两个进程就像两个固执的人,各自握着对方想要的东西,却都不愿意先放手,结果就是双方都卡在那里动弹不得。这就是死锁的典型表…...

SQLite NULL 值

SQLite NULL 值 SQLite 是一种轻量级的数据库管理系统,广泛用于嵌入式系统和移动应用中。在 SQLite 中,NULL 值是一个非常重要的概念,它表示未知、缺失或不确定的数据。本文将详细介绍 SQLite 中的 NULL 值,包括其定义、处理方法以及优化技巧。 什么是 NULL 值 在 SQLit…...

STM32大棚花卉物联网护养系统设计与实现

1. 项目概述这个大棚花卉护养系统是我去年为一个花卉种植基地设计的物联网解决方案。当时客户反映传统人工管理方式效率低下,经常出现浇水不及时、温度控制不精准等问题。经过三个月的开发和调试,这套系统成功将花卉产量提升了30%,同时减少了…...

LPS331AP SPI嵌入式驱动库:Mbed平台高精度气压温度传感器底层控制

1. LPS331AP_SPI 库概述LPS331AP_SPI 是一个专为 Mbed OS 平台设计的轻量级 SPI 驱动库,面向意法半导体(STMicroelectronics)推出的高精度数字气压/温度传感器 LPS331AP。该器件采用 MEMS 技术,集成压力传感单元与温度传感单元&am…...

DAY4--SQL限制返回行数查询

SQL基础入门:电商用户数据限制返回行数查询实操 这一章能解决什么电商工作问题? 这一章要学的LIMIT,是我认为电商数据分析新人最应该刻进肌肉记忆的语法。因为它直接关系到两件事:你的工作效率,以及你的职场安全。 我先…...

STM32 OLED三级菜单框架设计与实现

1. STM32 OLED菜单界面框架设计概述在嵌入式设备开发中,人机交互界面是连接用户与硬件的重要桥梁。基于STM32微控制器和OLED显示屏构建的菜单系统,因其低成本、低功耗和高对比度显示特性,在工业控制、智能家居和便携设备等领域广泛应用。本文…...

DAY3--SQL单字段去重查询

SQL基础入门:电商用户数据单字段去重查询实操 这一章能解决什么电商工作问题? 前两章我们学了SELECT *(全量看数据)和SELECT 字段列表(精准取字段)。这一章讲的是另一个高频操作:去重。 我讲一个…...

基于单片机的温控风扇(有完整资料)

资料查找方式:特纳斯电子(电子校园网):搜索下面编号即可编号:T4272204C设计简介:本设计是基于单片机的语音控制温控风扇,主要实现以下功能:1、可通过LCD1602显示温度和档位&#xff…...

基于单片机的心率及跌倒检测系统设计(有完整资料)

资料查找方式:特纳斯电子(电子校园网):搜索下面编号即可编号:T4192205M设计简介:本设计是基于单片机的心率及跌倒检测系统,主要实现以下功能:1、可通过心率模块检测当前的心率 2、可…...