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

ESP8266 SPIFFS中MAC地址字符串转十六进制数组错误求助

排查SPIFFS MAC地址转换错误的问题

我来帮你拆解这个问题——从你遇到的现象(写入AA:00:00:00:00:01却得到29:D5:23:40:00:00)来看,核心问题大概率出在字符串转十六进制数组的逻辑,或者SPIFFS读取环节的疏漏,咱们一步步排查:

1. 先确认SPIFFS读取的字符串是否正确

很多时候问题出在读取环节,比如字符串被截断、包含多余的换行/空格,或者编码异常。你可以在读取后立刻打印字符串内容验证:

String macStr = macFile.readStringUntil('\n');
macStr.trim(); // 去除首尾的换行、空格等空白字符
Serial.print("读取到的MAC字符串:");
Serial.println(macStr);

如果打印出来不是完整的AA:00:00:00:00:01,那先解决SPIFFS读取的问题(比如文件写入时有没有加多余字符,或者文件权限问题)。

2. 修正十六进制转换逻辑

这是最常见的错误点:很多人会误用十进制转换函数(比如atoi())来处理十六进制字符串,而atoi()默认只识别十进制,遇到AA这种十六进制字符会直接返回0,甚至导致后续解析混乱。

正确的做法是用strtoul()函数,指定基数为16来处理十六进制字符串:

uint8_t mac[6] = {0}; // 初始化数组为0,避免未赋值的字节出现随机值
char buffer[18]; // 足够容纳最长的MAC字符串(XX:XX:XX:XX:XX:XX共17个字符)
macStr.toCharArray(buffer, sizeof(buffer));

char* token = strtok(buffer, ":");
int i = 0;
while (token != NULL && i < 6) {
    // 把每个十六进制子串转成字节,基数16是关键
    mac[i] = (uint8_t)strtoul(token, NULL, 16);
    Serial.printf("解析后的第%d个字节:0x%02X\n", i, mac[i]);
    i++;
    token = strtok(NULL, ":");
}

// 验证是否解析了完整的6个字节
if (i != 6) {
    Serial.println("MAC字符串格式错误,无法解析出6个字节");
    return;
}

如果之前你用的是atoi(token),那这就是问题根源——atoi("AA")会返回0,后续解析也会因为错误的token处理出现乱码,最终生成错误的MAC数组。

3. 确认MAC地址的字节顺序

ESP8266的wifi_set_macaddr()函数要求MAC数组的顺序和字符串的顺序一致:比如字符串AA:00:00:00:00:01对应的数组应该是{0xAA, 0x00, 0x00, 0x00, 0x00, 0x01},不要把字节顺序倒过来(比如把第一个字节放在数组最后)。

你可以在设置后读取当前MAC地址验证:

uint8_t checkMac[6];
wifi_get_macaddr(STATION_IF, checkMac);
Serial.print("当前设置的MAC地址:");
for (int j = 0; j < 6; j++) {
    if (j > 0) Serial.print(":");
    Serial.printf("%02X", checkMac[j]);
}
Serial.println();

完整的验证代码示例

把上面的逻辑整合起来,你可以用这段代码测试:

#include <FS.h>

void setup() {
    Serial.begin(115200);
    delay(1000);

    // 挂载SPIFFS
    if (!SPIFFS.begin()) {
        Serial.println("SPIFFS挂载失败");
        return;
    }

    // 读取MAC文件
    File macFile = SPIFFS.open("/mac.txt", "r");
    if (!macFile) {
        Serial.println("无法打开MAC文件");
        return;
    }

    String macStr = macFile.readStringUntil('\n');
    macFile.close();
    macStr.trim();
    Serial.print("读取到的MAC字符串:");
    Serial.println(macStr);

    // 转换为十六进制数组
    uint8_t mac[6] = {0};
    char buffer[18];
    macStr.toCharArray(buffer, sizeof(buffer));

    char* token = strtok(buffer, ":");
    int i = 0;
    while (token != NULL && i < 6) {
        mac[i] = (uint8_t)strtoul(token, NULL, 16);
        Serial.printf("解析字节%d:0x%02X\n", i, mac[i]);
        i++;
        token = strtok(NULL, ":");
    }

    if (i != 6) {
        Serial.println("MAC格式错误");
        return;
    }

    // 设置并验证MAC地址
    if (!wifi_set_macaddr(STATION_IF, mac)) {
        Serial.println("设置MAC地址失败");
    } else {
        uint8_t checkMac[6];
        wifi_get_macaddr(STATION_IF, checkMac);
        Serial.print("最终设置的MAC地址:");
        for (int j = 0; j < 6; j++) {
            if (j > 0) Serial.print(":");
            Serial.printf("%02X", checkMac[j]);
        }
        Serial.println();
    }
}

void loop() {
}

常见坑总结

  • 误用十进制转换函数(atoi())处理十六进制字符串,导致解析错误
  • SPIFFS读取的字符串包含多余空白字符,导致解析中断
  • 未初始化MAC数组,未赋值的字节出现随机垃圾值
  • 设置MAC时颠倒了字节顺序

内容的提问来源于stack exchange,提问作者Dusan Krstic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:51:05