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的计数器