2

我正在尝试将 C 中定义的数据结构写入我的 Arduino Uno 板的非易失性存储器,因此结构的值将在电源关闭或重置后保留。据我了解,执行此操作的唯一方法(在草图运行时)是写入 arduino 的 EEPROM。虽然我可以写单个字节(在地址 0 处设置一个值为 1 的字节):

eeprom_write_byte(0,1);

我被困在试图写一个完整的结构:

typedef struct NewProject_Sequence {
    NewProject_SequenceId sequenceId;
    NewProject_SequenceLength maxRange;
    NewProject_SequenceLength minRange;
    NewProject_SequenceLength seqLength;
    NewProject_SceneId sceneList[5];
} NewProject_Sequence;

由于 EEPROM 的写入限制为 100,000 次,我不想在循环中通过每个字节写入 Arduino,因为这可能会很快用完它。有谁知道这样做的更有效方法,无论是使用 EEPROM,还是在草图运行时有办法写入 PROGMEM?(不使用 Arduino 库,只使用 C)。

已解决 我最终编写了两个自定义函数——eepromWrite 和 eepromRead 它们在下面列出:

void eepromRead(uint16_t addr, void* output, uint16_t length) {
    uint8_t* src; 
    uint8_t* dst;
    src = (uint8_t*)addr;
    dst = (uint8_t*)output;
    for (uint16_t i = 0; i < length; i++) {
        *dst++ = eeprom_read_byte(src++);
    }
}

void eepromWrite(uint16_t addr, void* input, uint16_t length) {
    uint8_t* src; 
    uint8_t* dst;
    src = (uint8_t*)input;
    dst = (uint8_t*)addr;
    for (uint16_t i = 0; i < length; i++) {
        eeprom_write_byte(dst++, *src++);
    }
}

将像这样实现:

uint16_t currentAddress;
struct {
    uint16_t x;
    uint16_t y;
} data;

struct {

} output;
uint16_t input

eepromWrite(currentAddress, data, sizeof(data);
eepromRead(currentAddress, output, sizeof(data));
4

2 回答 2

2

几种解决方案和/或组合。

  1. 设置一个计时器事件来定期存储值,而不是背靠背。
  2. 写入时使用校验和,然后增加初始偏移量。在读取时尝试每个增量,直到您有一个有效的校验和。这会将您的数据分布在整个范围内,从而延长您的寿命。现代闪存驱动器可以做到这一点。
  3. 通过使用外部欠压检测器触发 INT,然后快速写入 EEPROM,捕捉设备关闭。然后,您还可以使用内部 BOD 在低于安全写入电压之前防止损坏。通过使外部阈值显着高于内部阈值。可以通过增加 VCC 电容来增加完全关断之前的写入时间。在 VCC 之前比较外部 BOD,而不是直接比较 VCC 本身。

ATmega 上的粗外部 BOD 电路

这是一个视频,解释了如何为 ATtiny 启用内部 BOD,其他 ATmega 几乎相同。视频

于 2014-01-03T15:37:14.013 回答
1

Arduino EEPROM 库提供了能够读取和写入结构的 get/put 函数...

链接到 EEPROM.put(...)

仅当字节发生更改时才进行写入。

因此,使用 put/get 可以解决您的问题。

我在一个广泛的(25k)项目中使用这些没有任何问题。

正如已经说过的那样,我不是每次都使用计时器来写,而是有时会写。

关闭检测也是一个非常好的方法。

于 2017-05-15T16:13:47.420 回答