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

下面给出基于 ESP32-C3 AT 固件的完整方案,包括

下面给出基于 ESP32-C3 AT 固件的完整方案,包括:

  1. APP ↔ C3 之间的 BLE 协议设计

  2. ESP32-C3 AT 命令脚本(持久化 “UART-BLE SPP” 模式)

  3. MCU 端串口固件示例(按照 V1.5 协议升级 MCU)


1. BLE 协议设计

为了最简化中间转发,采用 BLE SPP(串口透传)模式,让 AT 固件把 BLE 收到的数据透传到串口,串口收到的数据透传回 BLE。

  • 设备名称OTA_C3

  • 服务/特征:使用 AT 固件自带的 GATT SPP 服务,无需自定义 UUID

  • 数据格式:直接透传二进制帧,每帧格式见 MCU 协议

APP 端(以 Android 为例)核心流程:

// 1. 扫描并连接到名称为 "OTA_C3" 的设备
BluetoothDevice dev = …;
BluetoothGatt gatt = dev.connectGatt(context, false, callback);// 2. 找到 SPP 服务后,使能通知
BluetoothGattCharacteristic txChar = …;   // server→client,NOTIFY
BluetoothGattCharacteristic rxChar = …;   // client→server,WRITE
gatt.setCharacteristicNotification(txChar, true);// 3. 发送升级帧
byte[] frame = buildUpgradeFrame(...);
rxChar.setValue(frame);
gatt.writeCharacteristic(rxChar);// 4. 接收 MCU ACK(onCharacteristicChanged 回调)

2. ESP32-C3 AT 固件配置脚本

说明:以下命令可通过串口 AT0 发送;执行完毕后再执行 AT+SAVETRANSLINK=1 可将 SPP 配置保存在 NVS,重启后自动进入透传模式,无需手动重新执行。

AT+BLEINIT=2                  // 角色:GATTS(server):contentReference[oaicite:0]{index=0}
AT+BLEGATTSSRVCRE             // 创建 GATT 服务(需 pre-flash ble_data.bin):contentReference[oaicite:1]{index=1}
AT+BLEGATTSSRVSTART           // 启动服务
AT+BLEADVSTART                // 开始广播
// 查询服务、特征索引(选做,用于校准后面 SPP 配置)
AT+BLEGATTSSRV?               
AT+BLEGATTSCHAR?              
// 配置 SPP(假设 tx 在服务1特征7,rx 在服务1特征5)
AT+BLESPPCFG=1,1,7,1,5        // SPP 参数配置:contentReference[oaicite:2]{index=2}
AT+BLESPP                     // 进入 SPP 模式,返回 “>” 即可透传
AT+SAVETRANSLINK=1            // 保存透传配置到 NVS(下次开机自动进入)

此后,AT 固件会在串口和 BLE 之间双向透传所有数据。


3. MCU 端升级固件示例

MCU 与 ESP32-C3 之间串口参数:115200 bps,8N1,无校验
以下示例基于裸机轮询 + 状态机,供参考。

#include "crc8.h"     // 计算校验码(异或累加)
#include <string.h>
#include <stdbool.h>
#include <stdint.h>// 串口接收缓冲
#define RX_BUF_SIZE 2048
static uint8_t rx_buf[RX_BUF_SIZE];
static size_t  rx_len = 0;// 1. 帧解析状态机
enum {ST_WAIT_SYNC,ST_READ_HDR,   // 读取 1B cmd + 2B lenST_READ_BODY,  // 读取 payloadST_READ_CRC,ST_WAIT_END
} state = ST_WAIT_SYNC;uint16_t cmd_word;
uint16_t data_len;
uint8_t  payload[2048];
uint8_t  crc_calc;// 串口读取(伪代码,视平台 API 而定)
void uart_rx_byte(uint8_t b) {switch (state) {case ST_WAIT_SYNC:if (b == 0xF0) {state = ST_READ_HDR;rx_len = 0;}break;case ST_READ_HDR:rx_buf[rx_len++] = b;if (rx_len == 3) {// cmd_word = buf[0]<<8 | buf[1]; data_len = buf[2]<<8 | buf[3];cmd_word = (rx_buf[0]<<8) | rx_buf[1];data_len = (rx_buf[2]<<8) | rx_buf[3];if (data_len > sizeof(payload)) {state = ST_WAIT_SYNC; // 丢帧} else {rx_len = 0;crc_calc = 0;state = (data_len ? ST_READ_BODY : ST_READ_CRC);}}break;case ST_READ_BODY:payload[rx_len++] = b;crc_calc ^= b;if (rx_len == data_len) state = ST_READ_CRC;break;case ST_READ_CRC:if (b == crc_calc) {state = ST_WAIT_END;} else {state = ST_WAIT_SYNC;}break;case ST_WAIT_END:if (b == 0xF0) {process_frame(cmd_word, payload, data_len);}state = ST_WAIT_SYNC;break;}
}// 2. 处理各命令(节选升级相关)
void process_frame(uint16_t cmd, uint8_t *data, uint16_t len) {switch (cmd) {case 0x4040: // CPU 发送“启动升级”// 应答通用 ACK:命令 0x4041,无数据send_frame(0x4041, NULL, 0);break;case 0x4041: // CPU 发送升级包数据(含包号+1024B)// TODO: 将 data[0](包号)及 data+1(1024B)写入 Flash// 应答包号send_frame(0x4041, &data[0], 1);break;case 0x4042: // CPU 发送升级完成指令(无数据)// MCU 完成后无需应答break;default:// 其他命令可参照协议文档实现……break;}
}// 3. 发送封装帧,含转义
void send_frame(uint16_t cmd, uint8_t *data, uint16_t len) {uint8_t  tmp[4096], *p = tmp;uint8_t  crc = 0;// 标识位*p++ = 0xF0;// 报文头*p++ = cmd>>8; *p++ = cmd&0xFF;*p++ = len>>8; *p++ = len&0xFF;// 消息体for (int i = 0; i < len; i++) {uint8_t b = data[i];crc ^= b;// 转义处理if (b == 0xF1) { *p++ = 0xF1; *p++ = 0x01; }else if (b == 0xF0) { *p++ = 0xF1; *p++ = 0x02; }else              { *p++ = b; }}// 校验码*p++ = crc;// 帧尾*p++ = 0xF0;// 串口发送uart_write(tmp, p - tmp);
}int main(void) {uart_init(115200);// 启动 UART Rx 中断/DMA,并让 uart_rx_byte 回调while (1) {// 可以在此做心跳、超时重发等逻辑}
}

小结

  1. BLE+AT:ESP32-C3 全部用 AT 命令配置 SPP 模式,无需二次开发。

  2. 双向透传:AT 固件负责 BLE↔UART 数据透传,MCU 只需专注协议处理。

  3. MCU 协议:严格按照附表 V1.5 格式封包/转义/XOR 校验并应答。

如此即可实现:APP → (BLE) → C3 → (UART) → MCU 升级,再从 MCU 应答 → C3 → APP 完整闭环。

相关文章:

  • 秘塔AI搜索:智能搜索,高效获取信息
  • AI书签管理工具开发全记录(十九):嵌入资源处理
  • 英语写作中“每一个”each individual、every individual、every single的用法
  • WEB3全栈开发——面试专业技能点P4数据库
  • uniapp 小程序 学习(一)
  • 【Fifty Project - D34】
  • 基于Flask,MySQL和MongoDB实现的在线阅读系统
  • WEB3全栈开发——面试专业技能点P6后端框架 / 微服务设计
  • DisplayPort 2.0协议介绍(2)
  • TJCTF 2025
  • 申请Let’s Encrypt 证书
  • 分布式增量爬虫实现方案
  • 【大模型:知识库管理】--Dify接入RAGFlow 知识库
  • Ray框架:分布式AI训练与调参实践
  • IP选择注意事项
  • QEMU源码全解析 —— 块设备虚拟化(26)
  • 渗透实战PortSwigger Labs指南:自定义标签XSS和SVG XSS利用
  • 37 C 语言字符串基础操作函数详解:strlen、strcpy、strncpy、strcat、strncat、strcmp、strncmp
  • 实现p2p的webrtc-srs版本
  • Coze工作流-语音故事创作-文本转语音的应用
  • 济南品质网站建设费用/厦门网站推广优化哪家好
  • 做网站后台维护的岗位叫什么/网络营销专业是干嘛的
  • 芜湖市人民政府疫情公告/seo云优化外包
  • 青岛哪家做网站的公司好/电商运营培训学费多少
  • 临沂网站设计/公司seo是什么意思
  • django做网站好吗/网络营销的五大特点