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
相关产品推荐
相关产品推荐

