3548938166 发表于 2025-12-9 14:32:24

EEPROM 读取异常,保存数据失败 | 地址错

型号:STC8H1K17T
频率:35MHz
问题:使用内部 Flash 做 EEPROM 保存数据。第一次读取出来的值为 0;执行擦除之后读取的值还是 0;执行写入之后,读取到的值是写入的值,但是复位或者重新上电之后,读取到的值还是 0,没有保存成功。
问题出在哪里。
程序:


#include "main.h"

void Uart1_Init(void);      //115200bps@35.000MHz

void IapIdle(void);
char IapRead(int addr);
void IapProgram(int addr, char dat);
void IapErase(int addr);

void Uart1_Init(void);      //115200bps@12.000MHz

void main(void)
{
      unsigned char byte = 0;

//////////////////////////////////      
      __enable_irq();

      Uart1_Init();      //115200bps@35.000MHz

      printf("EEPROM Test\n");
      
      byte = IapRead(0x0400);   
      printf("EEPROM 1 Read:%x\n", (int)byte);
      
      IapErase(0x0400);
      byte = IapRead(0x0400);   
      printf("EEPROM 2 Read:%x\n", (int)byte);
      
    IapProgram(0x0400, 0xAA);
    byte = IapRead(0x0400);
      printf("EEPROM 3 Read:%x\n", (int)byte);
      
      while (1)
      {
      }
}


void Uart1_Init(void)      //115200bps@35.000MHz
{
      SCON = 0x50;                //8位数据,可变波特率
      AUXR |= 0x01;                //串口1选择定时器2为波特率发生器
      AUXR |= 0x04;                //定时器时钟1T模式
      T2L = 0xB4;                        //设置定时初始值
      T2H = 0xFF;                        //设置定时初始值
      AUXR |= 0x10;                //定时器2开始计时
      ES = 1;                              //使能串口1中断
}


void Uart1_SendByte(unsigned char tx_byte)
{
      SBUF = tx_byte;   //写入发送缓冲寄存器
      while(!TI);    //等待发送完成,TI发送溢出标志位 置1
      TI = 0;      //对溢出标志位清零      
}


void Uart1_Isr(void) interrupt 4
{
      if (TI)                              //检测串口1发送中断
      {
                TI = 0;                        //清除串口1发送中断请求位
      }
      if (RI)                              //检测串口1接收中断
      {
                RI = 0;                        //清除串口1接收中断请求位
                if (SBUF == 0x7F)
                {
                        IAP_CONTR = 0x60;
                }
      }
}


char putchar(char c){
      //输出重定向到串口
      Uart1_SendByte(c);
      return c;//返回给函数的调用者printf
}


void IapIdle(void)
{
      IAP_CONTR = 0;                                                      //关闭IAP功能
      IAP_CMD = 0;                                                                //清除命令寄存器
      IAP_TRIG = 0;                                                                //清除触发寄存器
      IAP_ADDRH = 0x80;                                                      //将地址设置到非IAP区域
      IAP_ADDRL = 0;
}

char IapRead(int addr)
{
      char dat = 0xFF;

      EA = 0;                                                                        //关闭中断
      IAP_CONTR = 0x80;                                                      //使能IAP
      IAP_TPS = 35;                                                                //设置等待参数35MHz
      IAP_CMD = 1;                                                                //设置IAP读命令
      IAP_ADDRL = addr;                                                      //设置IAP低地址
      IAP_ADDRH = addr >> 8;                                                //设置IAP高地址
      IAP_TRIG = 0x5a;                                                      //写触发命令(0x5a)
      IAP_TRIG = 0xa5;                                                      //写触发命令(0xa5)
      _nop_(); _nop_(); _nop_(); _nop_();
      dat = IAP_DATA;                                                      //读IAP数据
      IapIdle();                                                                        //关闭IAP功能
      EA = 1;                                                                        //开启中断

      return dat;
}

void IapProgram(int addr, char dat)
{
      EA = 0;                                                                        //关闭中断
      IAP_CONTR = 0x80;                                                      //使能IAP
      IAP_TPS = 35;                                                                //设置等待参数35MHz
      IAP_CMD = 2;                                                                //设置IAP写命令
      IAP_ADDRL = addr;                                                      //设置IAP低地址
      IAP_ADDRH = addr >> 8;                                                //设置IAP高地址
      IAP_DATA = dat;                                                      //写IAP数据
      IAP_TRIG = 0x5a;                                                      //写触发命令(0x5a)
      IAP_TRIG = 0xa5;                                                      //写触发命令(0xa5)
      _nop_(); _nop_(); _nop_(); _nop_();
      IapIdle();                                                                        //关闭IAP功能
      EA = 1;                                                                        //开启中断
}

void IapErase(int addr)
{
      EA = 0;                                                                        //关闭中断
      IAP_CONTR = 0x80;                                                      //使能IAP
      IAP_TPS = 35;                                                                //设置等待参数35MHz
      IAP_CMD = 3;                                                                //设置IAP擦除命令
      IAP_ADDRL = addr;                                                      //设置IAP低地址
      IAP_ADDRH = addr >> 8;                                                //设置IAP高地址
      IAP_TRIG = 0x5a;                                                      //写触发命令(0x5a)
      IAP_TRIG = 0xa5;                                                      //写触发命令(0xa5)
      _nop_(); _nop_(); _nop_(); _nop_();
      IapIdle();                                                                        //关闭IAP功能
      EA = 1;                                                                        //开启中断
}


神农鼎 发表于 2025-12-9 14:52:56




EEPROM 空间 改大些

0x400, 已超过 1K 了

3548938166 发表于 2025-12-9 14:55:55

神农鼎 发表于 2025-12-9 14:52
EEPROM 空间 改大些

0x400, 已超过 1K 了

这个写入的地址,是相对于EEPROM的起始地址吗{:yiwen:}

3548938166 发表于 2025-12-9 15:01:48

神农鼎 发表于 2025-12-9 14:52
EEPROM 空间 改大些

0x400, 已超过 1K 了

谢谢,地址改成0,可以了。

3548938166 发表于 2025-12-9 15:03:33

读写
操作的地址改成0,可以了
页: [1]
查看完整版本: EEPROM 读取异常,保存数据失败 | 地址错