zhaojingbo111 发表于 2025-2-18 23:34:10

eeprom程序不管用,高手指点一下

#include "stc8g.h"
#include <intrins.h>

#define uint8 unsigned char
#define uint16 unsigned int
#define STORAGE_SECTOR   0          // 使用第一个扇区存储数据
#define EEPROM_START_ADDR       0x0400    // 起始地址

#define DATA_ADDR_HIGH   (EEPROM_START_ADDR)   // 数据高字节地址
#define DATA_ADDR_LOW    (EEPROM_START_ADDR +1)// 数据低字节地址
/* 引脚定义 */
sbit TM1637_CLK = P1^1;
sbit TM1637_DIO = P1^0;
sbit KEY1 = P1^2;
sbit KEY2 = P1^3;
sbit KEY3 = P3^7;
sbit KEY4 = P3^6;
sbit KEY5 = P1^5;
/* 数码管编码表 */
static const uint8 digit_encode[] = {
    0x3F, 0x06, 0x5B, 0x4F,
    0x66, 0x6D, 0x7D, 0x07,
    0x7F, 0x6F/* 0-9 */
};

uint8 display_digits;      /* 显示缓冲区 */
uint8 selected_digit = 0;   /* 当前选中的数码管位 */
uint8 setting_mode = 0;       /* 设置模式标志 */
uint16 stored_value = 0;      /* 存储值 */
uint8 blink_state = 0;      /* 闪烁状态 */

/* 微秒级延时函数 */
void delay_us(uint8 us) {
    while(us--) {
      _nop_(); _nop_(); _nop_();

    }
}


void Delay(unsigned int xms)                //@11.0592MHz
{
        unsigned char i, j;
while(xms--)
{        _nop_();
        _nop_();
        _nop_();
        i = 11;
        j = 190;
        do
        {
                while (--j);
        } while (--i);
}
}


/* TM1637通信协议 */
void tm1637_start(void) {
    TM1637_CLK = 1;
    TM1637_DIO = 1;
    delay_us(2);
    TM1637_DIO = 0;

}
void tm1637_ask(void)
{
   TM1637_CLK = 0;
   delay_us(5);
   while (TM1637_DIO);
       TM1637_CLK = 1;
      delay_us(2);
           TM1637_CLK = 0;
}
void tm1637_stop(void) {
    TM1637_CLK = 0;
       delay_us(2);
    TM1637_DIO = 0;
   delay_us(2);
    TM1637_CLK = 1;
    delay_us(2);
    TM1637_DIO = 1;

}

void tm1637_write(uint8 Data) {
    uint8 i;
    for(i = 0; i < 8; i++)
        {
      TM1637_CLK = 0;
                if(Data&0x01)
                {
                        TM1637_DIO = 1;
                  
               
                }
      else{
               
                TM1637_DIO = 0;
               
                }
                delay_us(3);
                Data=Data>>1;
                TM1637_CLK = 1;
                delay_us(3);
    }
       

}

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

void IAP_Wait(void)
{
    IAP_CONTR = 0x80;   // 使能IAP
    IAP_TPS = 12;       // 时钟分频(主频11.0592MHz)
    _nop_();
}

/* 扇区擦除(所有扇区大小512字节) */
void EEPROM_EraseSector(uint16 addr)
{
    IAP_Wait();
    IAP_CMD = 0x03;   // 写命令:擦除
        IAP_ADDRL = addr ;
    IAP_ADDRH = addr >> 8;
    IAP_TRIG = 0x5A;
    IAP_TRIG = 0xA5;    // 触发操作
    _nop_();
    IapIdle();       // 清除命令
}

/* 写一个字节 */
void EEPROM_WriteByte(uint16 addr, uint8 dat)
{
    IAP_Wait();
    IAP_CMD = 2;         // 设置IAP写命令
    IAP_ADDRL = addr;      // 设置低地址位
    IAP_ADDRH = addr >> 8; // 设置高地址位
    IAP_DATA = dat;      // 写入数据
    IAP_TRIG = 0x5a;       // 触发命令第一步
    IAP_TRIG = 0xa5;       // 触发命令第二步
    _nop_();               // 空操作等待
    IapIdle();   
}

/* 读一个字节 */
uint8 EEPROM_ReadByte(uint16 addr)
{
    uint8 dat;
    IAP_Wait();
    IAP_CMD = 0x01;   // 读命令
        IAP_ADDRL = addr ;
    IAP_ADDRH = addr >> 8;
    IAP_TRIG = 0x5A;
    IAP_TRIG = 0xA5;    // 触发操作
    _nop_();
    dat = IAP_DATA;
   Iapldle();       // 清除命令
    return dat;
}
/* 安全存储数值 */
void Save_Stored_Value(uint16 val) {
    static uint16 last_saved = 0xFFFF;

    // 仅当数值变化时存储
    if(val != last_saved) {
      EEPROM_EraseSector(STORAGE_SECTOR); // 擦除整个扇区
      EEPROM_WriteByte(DATA_ADDR_HIGH, (val >> 8) & 0xFF); // 高字节
      EEPROM_WriteByte(DATA_ADDR_LOW,val & 0xFF);      // 低字节
      last_saved = val;                     // 更新最近保存值
    }
}
uint16 Load_Stored_Value(void) {
    uint8 high = EEPROM_ReadByte(DATA_ADDR_HIGH);
    uint8 low= EEPROM_ReadByte(DATA_ADDR_LOW);
    uint16 val = (high << 8) | low;

    // 首次运行检测(全FF则重置为0)
    if(val == 0xFFFF) {
      val = 0;
      Save_Stored_Value(val);
    }
    return val;
}



/* 显示更新函数 */
void update_display(void) {
       
       
    uint8 i;

    tm1637_start();
    tm1637_write(0x40);/* 自动地址增加模式 */
        tm1637_ask();
    tm1637_stop();

    tm1637_start();
    tm1637_write(0xC0);/* 起始地址 */
    tm1637_ask();
    for(i = 0; i < 4; i++) {
      if(setting_mode && (i == selected_digit) && blink_state) {
            tm1637_write(0x00);/* 闪烁显示 */
                        tm1637_ask();
      } else {
            tm1637_write(digit_encode]);
                        tm1637_ask();
      }
    }
    tm1637_stop();

    tm1637_start();
    tm1637_write(0x8F);/* 显示开,最大亮度 */
        tm1637_ask();
    tm1637_stop();
}

/* 改进的按键处理函数 */
void process_keys(void) {
    static uint16 key1_timer = 0;
    static uint8 key1_last = 1;
    static uint8 key2_state = 0;
    static uint8 key3_cnt = 0;

    // KEY1: 长按/短按
    uint8 key_current = KEY1;
    if (key_current != key1_last) {
      if (!key_current) { // 按下
            key1_timer = 0;
      } else { // 释放
            if (key1_timer >1000) { // 约1秒长按
                setting_mode = !setting_mode;
                if (setting_mode) {
                  // 进入设置模式,加载存储值
                  display_digits = (stored_value / 1000) % 10;
                  display_digits = (stored_value / 100) % 10;
                  display_digits = (stored_value / 10) % 10;
                  display_digits = stored_value % 10;
//                                        EEPROM_WriteByte(0x00, (uint8)(stored_value & 0xFF));       // 低字节
//            EEPROM_WriteByte(0x01, (uint8)(stored_value >> 8));
                } else {
                  stored_value = display_digits*1000 + display_digits*100
                                 + display_digits*10 + display_digits;
                }
            } else if (key1_timer > 10) { // 约0.1秒短按
                if (setting_mode) {
                  selected_digit = (selected_digit + 1) % 4;
                }
            }
      }
      key1_last = key_current;
    }
    if (!key_current) key1_timer++;

    // KEY2: 数值增加
    switch (key2_state) {
      case 0:
            if (!KEY2) {
                Delay(10);
                key2_state = 1;
            }
            break;
      case 1:
            if (!KEY2) {
                if (setting_mode) {
                  display_digits = (display_digits + 1) % 10;
                }
                key2_state = 2;
            } else {
                key2_state = 0;
            }
            break;
      case 2:
            if (KEY2) key2_state = 0;
            break;
    }

    /* 按键3检测(带防抖) */

    if(!KEY3) {
      if(++key3_cnt > 3) { // 30ms防抖
            key3_cnt = 0;
            while(!KEY3); // 等待释放
            if(KEY4) {
                stored_value++;
            } else {
                        if (stored_value > 0)       
                        {
                stored_value--;}
                        if (!KEY4&& (stored_value == 1)) {
         KEY5 = 0; // 设置P1.5为高电平
      }

            }
                       Save_Stored_Value(stored_value);
            // 更新显示
            display_digits = (stored_value / 1000) % 10;
            display_digits = (stored_value / 100) % 10;
            display_digits = (stored_value / 10) % 10;
            display_digits = stored_value % 10;
        //                EEPROM_EraseSector(0X000) ;
        //                EEPROM_WriteByte(0x0200, stored_value);       // 低字节
//            EEPROM_WriteByte(0x0200, (stored_value >> 8));      // 高字节
      }
    } else {
      key3_cnt = 0;
    }
}



/* 主函数 */
void main(void) {
      P1M0 = 0x00; P1M1 = 0x00;
      P3M0 = 0x00; P3M1 = 0x00;


    /* 初始化显示 */
    display_digits = 0;
    display_digits = 1;
    display_digits = 2;
    display_digits = 3;

    while(1) {
      static uint16 blink_counter = 0;

      process_keys();
      update_display();

      /* 闪烁控制(约500ms周期) */
      if(++blink_counter >= 300)
{
            blink_counter = 0;
            blink_state = !blink_state;
      }

         Delay        (1);/* 主循环延时 */
    }设置eeprom 的那一项也不见 ,不知是不是那设置错误了,放在一运行就复位了

soma 发表于 2025-2-18 23:52:05

型号选错或者该型号没eeprom吧,或者eeprom固定的

DebugLab 发表于 2025-2-19 09:09:34

MCU什么型号

496649247 发表于 2025-2-19 09:22:50

{:4_167:}
页: [1]
查看完整版本: eeprom程序不管用,高手指点一下