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

Atmega2560搭配SIM800L:循环缓冲区实现100KB数据SD卡存储求助

分块获取数据并存储到SD卡的实现方案

核心思路

利用HTTP的Range请求头,将100KB数据拆分为多个小片段(比如每段4KB,适配你的5KB RAM余量),逐段请求并写入SD卡,直到所有数据获取完成。这种方式无需一次性加载全部数据到RAM,完美解决内存受限问题。

具体步骤与代码实现

1. 依赖库准备

确保已安装:

  • SIM800L库(用于模块通信)
  • SD库(用于SD卡操作)

2. 关键实现代码

#include <SoftwareSerial.h>
#include <SD.h>

// SIM800L引脚定义(根据你的硬件连接调整)
SoftwareSerial sim800(10, 11); // RX, TX
const int chipSelect = 4;

// 配置参数
const char* server = "你的服务器地址";
const char* filePath = "/目标文件路径";
const int chunkSize = 4096; // 每次请求4KB,预留RAM冗余
unsigned long totalFileSize = 0;
File dataFile;

void setup() {
  Serial.begin(9600);
  sim800.begin(9600);
  delay(1000);

  // 初始化SD卡
  if (!SD.begin(chipSelect)) {
    Serial.println("SD卡初始化失败");
    while (1);
  }

  // 先获取文件总大小,确定分块次数
  getFileSize();
  
  // 打开SD卡文件准备写入(若文件已存在会追加,可根据需求调整)
  dataFile = SD.open("downloaded_data.bin", FILE_WRITE);
  if (!dataFile) {
    Serial.println("无法打开SD卡文件");
    while (1);
  }

  // 分块下载并写入SD卡
  downloadInChunks();

  // 完成后关闭文件,确保数据写入
  dataFile.close();
  Serial.println("数据下载完成");
}

void getFileSize() {
  // 初始化SIM800L HTTP服务
  sim800.println("AT+HTTPINIT");
  waitForResponse("OK");
  
  // 设置请求URL
  sim800.print("AT+HTTPPARA=\"URL\",\"http://");
  sim800.print(server);
  sim800.print(filePath);
  sim800.println("\"");
  waitForResponse("OK");

  // 发送HEAD请求获取文件大小(不下载内容)
  sim800.println("AT+HTTPHEAD");
  waitForResponse("+HTTPHEAD:");
  
  // 解析Content-Length字段
  while (sim800.available()) {
    String line = sim800.readStringUntil('\n');
    if (line.startsWith("Content-Length:")) {
      totalFileSize = line.substring(16).toInt();
      break;
    }
  }
  waitForResponse("OK");
  
  // 关闭HTTP连接
  sim800.println("AT+HTTPTERM");
  waitForResponse("OK");
}

void downloadInChunks() {
  unsigned long startByte = 0;
  while (startByte < totalFileSize) {
    // 计算当前块的结束字节,处理最后一块不足chunkSize的情况
    unsigned long endByte = startByte + chunkSize - 1;
    if (endByte >= totalFileSize) {
      endByte = totalFileSize - 1;
    }

    // 重新初始化HTTP连接
    sim800.println("AT+HTTPINIT");
    waitForResponse("OK");
    
    // 设置请求URL
    sim800.print("AT+HTTPPARA=\"URL\",\"http://");
    sim800.print(server);
    sim800.print(filePath);
    sim800.println("\"");
    waitForResponse("OK");

    // 设置Range头,指定当前要获取的字节范围
    sim800.print("AT+HTTPPARA=\"RANGE\",\"bytes=");
    sim800.print(startByte);
    sim800.print("-");
    sim800.print(endByte);
    sim800.println("\"");
    waitForResponse("OK");

    // 发送GET请求获取当前块数据
    sim800.println("AT+HTTPGET");
    waitForResponse("+HTTPGET:");
    
    // 用小缓冲区逐段读取数据并写入SD卡,避免占用过多RAM
    char buffer[128];
    int bytesRead;
    while (sim800.available()) {
      bytesRead = sim800.readBytes(buffer, sizeof(buffer));
      if (bytesRead > 0) {
        dataFile.write(buffer, bytesRead);
      }
    }
    waitForResponse("OK");
    
    // 关闭当前HTTP连接
    sim800.println("AT+HTTPTERM");
    waitForResponse("OK");

    // 更新起始字节,准备下一块下载
    startByte = endByte + 1;
    Serial.printf("已下载 %lu/%lu 字节\n", startByte, totalFileSize);
  }
}

// 等待SIM800L返回指定响应,带超时处理
void waitForResponse(const char* target) {
  unsigned long timeout = millis() + 10000; // 10秒超时
  while (millis() < timeout) {
    if (sim800.available()) {
      String response = sim800.readStringUntil('\n');
      if (response.indexOf(target) != -1) {
        return;
      }
    }
  }
  Serial.println("等待响应超时");
  while (1); // 超时后挂起,方便排查问题
}

3. 关键细节说明

  • Range头使用:通过Range: bytes=start-end指定每次请求的字节范围,服务器会返回对应片段的数据,而非全部内容(大部分HTTP服务器都支持该特性)。
  • 小缓冲区读取:内部使用128字节的小缓冲区逐段读取SIM800L返回的数据,写完即释放内存,避免一次性占用过多RAM。
  • 文件总大小获取:先发送HEAD请求获取Content-Length,准确计算分块次数,避免无效请求。
  • SD卡操作优化:保持文件全程打开,完成所有块后再关闭,减少SD卡挂载/卸载的开销。

4. 常见问题排查

  • SIM800L返回ERROR:检查AT指令格式、服务器地址/文件路径是否正确,或确认服务器支持Range请求。
  • SD卡写入失败:检查卡的格式(建议FAT32)、引脚连接是否正确,确保卡有足够存储空间。
  • 数据丢失:必要时在每次写入后调用dataFile.flush()强制将数据写入SD卡(会增加耗时,按需使用)。

内容的提问来源于stack exchange,提问作者Robotics info

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 01:12:12