You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求ESP32通过HTTP下载.bin文件实现OTA自动升级的Arduino示例代码

ESP32 HTTP OTA 升级实现方案

下面是基于ESP-IDF框架的实现代码,分为HTTP文件下载和OTA升级两个核心部分:


1. HTTP 下载.bin 文件(客户端模式)

这个模块负责从指定HTTP服务器下载固件文件,核心使用ESP-IDF的esp_http_client组件实现:

#include <stdio.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_http_client.h"
#include "esp_ota_ops.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

// WiFi配置信息,按需修改
#define WIFI_SSID "your_wifi_ssid"
#define WIFI_PASS "your_wifi_password"

// HTTP固件地址,按需修改
#define FIRMWARE_URL "http://your-server.com/firmware.bin"

// WiFi连接函数
static void wifi_connect(void) {
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);
    esp_wifi_set_mode(WIFI_MODE_STA);
    
    wifi_config_t wifi_cfg = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASS,
        },
    };
    esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
    esp_wifi_start();
    esp_wifi_connect();
    
    // 等待连接成功
    while (1) {
        wifi_ap_record_t ap_info;
        esp_wifi_sta_get_ap_info(&ap_info);
        if (ap_info.rssi != 0) break;
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

// HTTP下载固件的回调函数,边下载边写入OTA分区
static esp_err_t http_event_handler(esp_http_client_event_t *evt) {
    static esp_ota_handle_t ota_handle = 0;
    switch(evt->event_id) {
        case HTTP_EVENT_ON_CONNECTED:
            printf("Connected to HTTP server\n");
            // 初始化OTA升级
            const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
            esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &ota_handle);
            break;
        case HTTP_EVENT_ON_DATA:
            if (evt->data_len > 0 && ota_handle != 0) {
                esp_ota_write(ota_handle, evt->data, evt->data_len);
                printf("Written %d bytes to OTA partition\n", evt->data_len);
            }
            break;
        case HTTP_EVENT_ON_FINISH:
            printf("HTTP download finished\n");
            // 完成OTA升级并重启
            esp_ota_end(ota_handle);
            esp_ota_set_boot_partition(esp_ota_get_next_update_partition(NULL));
            printf("OTA upgrade done, rebooting...\n");
            esp_restart();
            break;
        case HTTP_EVENT_ON_DISCONNECTED:
            printf("Disconnected from HTTP server\n");
            break;
        default:
            break;
    }
    return ESP_OK;
}

// 启动OTA升级任务
void ota_upgrade_task(void *pvParameter) {
    wifi_connect();
    
    esp_http_client_config_t config = {
        .url = FIRMWARE_URL,
        .event_handler = http_event_handler,
        .timeout_ms = 5000,
    };
    
    esp_http_client_handle_t client = esp_http_client_init(&config);
    esp_err_t err = esp_http_client_perform(client);
    
    if (err == ESP_OK) {
        printf("HTTP status code: %d\n", esp_http_client_get_status_code(client));
    } else {
        printf("HTTP request failed: %s\n", esp_err_to_name(err));
    }
    
    esp_http_client_cleanup(client);
    vTaskDelete(NULL);
}

2. 解析.bin 文件并完成OTA升级

上面的代码已将下载与OTA升级整合,核心逻辑可拆分单独实现,比如先将固件存到SPIFFS再升级:

// 从SPIFFS读取.bin文件执行OTA升级
esp_err_t ota_upgrade_from_spiffs(const char *file_path) {
    FILE *f = fopen(file_path, "rb");
    if (!f) {
        printf("Failed to open firmware file\n");
        return ESP_FAIL;
    }
    
    const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
    esp_ota_handle_t ota_handle;
    esp_err_t err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &ota_handle);
    if (err != ESP_OK) {
        fclose(f);
        return err;
    }
    
    uint8_t buffer[1024];
    size_t bytes_read;
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), f)) > 0) {
        err = esp_ota_write(ota_handle, buffer, bytes_read);
        if (err != ESP_OK) {
            fclose(f);
            esp_ota_abort(ota_handle);
            return err;
        }
    }
    
    fclose(f);
    err = esp_ota_end(ota_handle);
    if (err != ESP_OK) return err;
    
    err = esp_ota_set_boot_partition(update_partition);
    if (err != ESP_OK) return err;
    
    printf("OTA upgrade completed, rebooting...\n");
    esp_restart();
    return ESP_OK;
}

关键配置与说明

  • 分区表要求:项目partitions.csv必须包含OTA分区,示例片段:
    # Name,   Type, SubType, Offset,  Size, Flags
    nvs,      data, nvs,     0x9000,  0x6000,
    otadata,  data, ota,     0xf000,  0x2000,
    app0,     app,  ota_0,   0x10000, 0x140000,
    app1,     app,  ota_1,   0x150000,0x140000,
    
  • 核心OTA API:
    • esp_ota_get_next_update_partition:获取可用OTA分区
    • esp_ota_begin:初始化升级流程
    • esp_ota_write:写入固件数据
    • esp_ota_end:验证固件并结束写入
    • esp_ota_set_boot_partition:设置下次启动分区

注意事项

  • 确保WiFi连接稳定,避免下载中断导致升级失败
  • 固件必须是适配ESP32的正确.bin格式,与分区表大小匹配
  • 若开启固件签名验证,需确保服务器固件已签名并配置密钥

内容的提问来源于stack exchange,提问作者Joe Ijam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:05:31