Arduino IDE中serialEvent()内超255的String转精确Int/Long问题求助
解决Arduino Due串口字符串转整数及闪存存储溢出问题
你遇到的问题根本不是字符串转整数的bug——toInt()、atoi()这些方法都能正确转换255以上的数值,真正的问题出在闪存的存储和读取逻辑上!
问题根源拆解
Arduino Due的DueFlashStorage库中,默认的write(address, value)方法是按**单字节(uint8_t)**存储数据的,而你要存的threshold是int类型(在Due上是32位,占4个字节)。当你把超过255的int值传给write()时,它会被强制截断为单字节,只保留低8位数据(比如256会变成0,257变成1,以此类推)。同样,read(address)也只会返回单字节数据,所以读取出来的自然就是被截断后的错误值。
解决方案:多字节存储/读取整数
因为int类型占4个字节,我们需要把它拆分成4个字节分别存储到闪存的连续地址,读取时再拼接回完整的int值。
修改后的完整代码
#include <DueFlashStorage.h> DueFlashStorage memory; String inputStr = ""; int threshold; // 定义闪存存储的起始地址(选一个不占用程序空间的地址即可) const int FLASH_START_ADDR = 0; void setup(){ Serial.begin(115200); // 上电时自动读取闪存中存储的历史阈值 threshold = readIntFromFlash(FLASH_START_ADDR); } void loop(){ Serial.println(threshold); // 实时打印当前阈值 delay(1000); } void serialEvent(){ while(Serial.available()){ inputStr = Serial.readStringUntil('\n'); // 直接用toInt()转换字符串,简洁且支持大数值(只要在int范围内) threshold = inputStr.toInt(); // 将完整的int值写入闪存的连续地址 writeIntToFlash(FLASH_START_ADDR, threshold); } } // 自定义函数:将int拆分为4字节写入闪存 void writeIntToFlash(int addr, int value){ uint8_t* bytes = (uint8_t*)&value; for(int i=0; i<sizeof(int); i++){ memory.write(addr + i, bytes[i]); } } // 自定义函数:从闪存读取4字节并拼接为int int readIntFromFlash(int addr){ int value = 0; uint8_t* bytes = (uint8_t*)&value; for(int i=0; i<sizeof(int); i++){ bytes[i] = memory.read(addr + i); } return value; }
关键改进点
- 解决存储溢出:通过自定义的
writeIntToFlash和readIntFromFlash函数,实现完整int类型的多字节存储与读取,彻底避免单字节截断问题。 - 简化字符串转换:直接使用
inputStr.toInt()转换串口输入的字符串,省去了toCharArray和atoi的冗余步骤,代码更简洁。 - 保留历史值:上电时自动从闪存读取之前存储的阈值,保证设备重启后能恢复之前的设置。
额外说明
- 关于
serialEvent():其实Serial.parseInt()也可以在serialEvent()中使用,只是它会等待串口输入完成(直到超时或遇到非数字字符),如果你需要以换行符作为输入结束标志,用readStringUntil('\n')是更合适的选择。 - 闪存地址选择:确保你使用的闪存地址没有被Arduino程序占用,DueFlashStorage库会自动避开程序存储区域,若不确定可以选择更高的起始地址(比如100)。
内容的提问来源于stack exchange,提问作者Abstract123
相关产品推荐
相关产品推荐

