vb2002 发表于 2024-8-2 15:57:47

Lkck8210 发表于 2024-8-2 15:16
但不会每次开机都换档吧?
有换档才在关机时更新EEProm

现在就是每次关机开机,包括换挡都会写入eeprom,我有点懊恼,
还没完善好。

vb2002 发表于 2024-8-2 19:59:31

DebugLab 发表于 2024-8-2 14:35
没有,这段文字直接翻译成C语言就是代码了

这个是千问模型给出的答案,

我运行很多错误
麻烦您看看大体差不多吧!
#define EEPROM_SIZE 4096
#define SECTOR_SIZE 512
#define NUM_SECTORS 8
#define DATA_SECTORS (NUM_SECTORS - 1)
#define POINTER_SECTOR 0
#define DATA_SECTOR_START 1
#define POINTER_BIT_COUNT 3584
#define DATA_STATE_COUNT 128
#define DATA_STATE_BITS 7
#define DATA_FLAG_BIT 7

typedef struct {
    int sector;
    int byte;
} Pointer;

typedef struct {
    int valid;
    int state;
} Data;

// 声明实际的EEPROM读写函数
unsigned char eeprom_read_byte(unsigned char *addr);
void eeprom_write_byte(unsigned char *addr, unsigned char value);

// 假设的EEPROM读写函数
unsigned char readEEPROM(int address) {
    // 使用实际的EEPROM读取函数
    return eeprom_read_byte((unsigned char *)address);
}

void writeEEPROM(int address, unsigned char value) {
    // 使用实际的EEPROM写入函数
    eeprom_write_byte((unsigned char *)address, value);
}

// 读取指针
Pointer readPointer() {
    int pointerBitIndex = 0; // 从第0位开始
    unsigned char bitMask = 1;
    int byteIndex = pointerBitIndex / 8;
    int bitIndex = pointerBitIndex % 8;

    // 读取位计数器的指针位置
    unsigned char pointerByte = readEEPROM(POINTER_SECTOR * SECTOR_SIZE + byteIndex);
    while ((pointerByte & bitMask) == 0) { // 跳过已用的位
      bitMask <<= 1;
      if (bitMask > 0xFF) {
            bitMask = 1;
            byteIndex++;
            pointerByte = readEEPROM(POINTER_SECTOR * SECTOR_SIZE + byteIndex);
      }
      bitIndex++;
      pointerBitIndex++;
    }

    // 计算指针位置
    Pointer p = {DATA_SECTOR_START, pointerBitIndex / 8};
    return p;
}

// 写入指针
void writePointer(const Pointer* p) {
    int byteIndex = p->byte * 8;
    int bitIndex = byteIndex % 8;
    unsigned char byte = readEEPROM(POINTER_SECTOR * SECTOR_SIZE + byteIndex / 8);

    // 设置位
    byte &= ~(1 << bitIndex); // 清除位
    writeEEPROM(POINTER_SECTOR * SECTOR_SIZE + byteIndex / 8, byte);
}

// 读取数据
Data readData(const Pointer* p) {
    unsigned char dataByte = readEEPROM(p->sector * SECTOR_SIZE + p->byte);
    Data d = {
      .valid = !(dataByte & (1 << DATA_FLAG_BIT)),
      .state = dataByte & ((1 << DATA_STATE_BITS) - 1)
    };
    return d;
}

// 处理数据
void processData(Data* d) {
    if (!d->valid) {
      // 处理无效数据
      d->state++;
      if (d->state >= DATA_STATE_COUNT) {
            d->state = 0;
      }
      d->valid = 1;
    }
}

// 更新数据
void updateData(const Pointer* p, Data* d) {
    unsigned char dataByte = d->state | (d->valid ? 0 : (1 << DATA_FLAG_BIT));
    writeEEPROM(p->sector * SECTOR_SIZE + p->byte, dataByte);
}

// 主函数示例
int main() {
    Pointer p = readPointer();
    Data d = readData(&p);
    processData(&d);
    updateData(&p, &d);
    writePointer(&p);

    // 根据需要重复上述过程
    return 0;
}

DebugLab 发表于 2024-8-2 20:30:58

Lkck8210 发表于 2024-8-2 15:16
但不会每次开机都换档吧?
有换档才在关机时更新EEProm

那还要做掉电检测,需要使用比较器,还需要大电容储能

DebugLab 发表于 2024-8-2 20:31:54

vb2002 发表于 2024-8-2 19:59
这个是千问模型给出的答案,

我运行很多错误


AI写的不能信,cheat gpt
有空我写一个

vb2002 发表于 2024-8-2 21:00:36

DebugLab 发表于 2024-8-2 13:27
STC8H1K08,固定8K CODE,4K EEPROM,8个扇区,4096字节
可以第0扇区作为位计数器,bit有多少个0代表指针指 ...

哥,我想了一天..您说的是这个意思吗?
按您说的,好像是真的无敌哦...就是代码难倒我了!!!!






vb2002 发表于 2024-8-2 21:01:44

DebugLab 发表于 2024-8-2 20:31
AI写的不能信,cheat gpt
有空我写一个

好的,哥,,我现在指导您的思路了...真心牛逼!!!
大大延长eeprom的寿命啊

DebugLab 发表于 2024-8-2 21:33:41

vb2002 发表于 2024-8-2 21:00
哥,我想了一天..您说的是这个意思吗?
按您说的,好像是真的无敌哦...就是代码难倒我了!!!!



也行,最高位表示是否已使用,已使用就写成0,可以不用一个扇区当计数器了

vb2002 发表于 2024-8-2 21:42:51

wnagming 发表于 2024-8-2 21:19
这是我之前做的磨损均衡代码,做吊顶灯,每次关机记录当前状态,共3种状态:冷光,暖光,均衡。就是普通的 ...

这个是我想的思路. 把8个扇区全部写满再擦除.   你的那个功能就是 在扇区8进行读写写写写写写,,写满扇区8 ,然后擦除扇区8(算一次擦除.)

https://www.stcaimcu.com/data/attachment/forum/202408/02/210006ripiirvzqcq2zieq.jpg

vb2002 发表于 2024-8-3 00:14:37

DebugLab 发表于 2024-8-2 21:33
也行,最高位表示是否已使用,已使用就写成0,可以不用一个扇区当计数器了 ...

我试了一晚上了.
好像写之前必须要擦除
不能那样一个字节的写入,然后总体擦除
u16 add= 3584;
state=IapRead(add);
IapProgram(add, state);

DebugLab 发表于 2024-8-3 00:17:24

vb2002 发表于 2024-8-3 00:14
我试了一晚上了.
好像写之前必须要擦除
不能那样一个字节的写入,然后总体擦除


写只能把1变0,擦除是整个扇区变成1,一位一位写就可以一位一位的变0,一个扇区就可以当成4096bit的计数器
页: 1 [2] 3 4
查看完整版本: 请教下这位老哥说的,可以减少eeprom的磨损.