Lkck8210 发表于 2024-8-6 16:57:02

本帖最后由 Lkck8210 于 2024-8-6 16:58 编辑

vb2002 发表于 2024-8-6 02:27
你这个代码上面我不会弄,,能否给出代码哦?


用的是STC8G1K08A
#include <STC8G.H>

#include <intrins.h>//_nop_, _cror_, _crol_
#include <stdio.h>//printf, sprintf
//#include <string.h>//strlen, strcmp, strcpy, strcat
typedef         unsigned char      u8;//0 to 255
typedef         unsigned int      u16;//0 to 65535
typedef         unsigned long      u32;//0 to 4294967295

void Timer0_Init(void)                //5毫秒@11.0592MHz
{
      AUXR &= 0x7F;                        //定时器时钟12T模式
      TMOD &= 0xF0;                        //设置定时器模式
      TL0 = 0x00;                              //设置定时初始值
      TH0 = 0xEE;                              //设置定时初始值
      TF0 = 0;                              //清除TF0标志
      TR0 = 1;                              //定时器0开始计时
}

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

char IapRead(int addr)
{
    char dat;

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

    return dat;
}

void IapProgram(int addr, char dat)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    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_();
    IapIdle();                                  //关闭IAP功能
}

void IapErase(int addr)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    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_();                                    //
    _nop_();                                    //
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}
void Delay50ms(void)      //@12.000MHz
{
      unsigned char data i, j, k;

      _nop_();
      _nop_();
      i = 4;
      j = 12;
      k = 50;
      do
      {
                do
                {
                        while (--k);
                } while (--j);
      } while (--i);
}

u8 bdata Byte;
sbit Bit0 = Byte^0;
sbit Bit1 = Byte^1;
sbit Bit2 = Byte^2;
sbit Bit3 = Byte^3;
sbit Bit4 = Byte^4;
sbit Bit5 = Byte^5;
void GPIO_W(u8 dat)
{
      Byte = dat;
      P30 = Bit0;
      P31 = Bit1;
      P32 = Bit2;
      P33 = Bit3;
      P54 = Bit4;
      P55 = Bit5;
}
#define EEPromAddrStr 0x0000
#define EEPromAddrEnd EEPromAddrStr+0x200

void main()
{
      u8 mode = 0, SwitchTime = 0, delay = 75;
      u16 i, TimEEPromAddr, ModeEEPromAddr;
      Delay50ms();
      Timer0_Init();
      P3M0=0;P3M1=0;
      P5M0=0;P5M1=0;
      for(i=EEPromAddrStr;i<EEPromAddrEnd;i+=2)
      {
                SwitchTime = IapRead(i);
                if(SwitchTime==0xFF)break;
      }
      if(i==EEPromAddrStr)
      {
                TimEEPromAddr = EEPromAddrStr;
      }
      else
      {
                SwitchTime = IapRead(i - 2);
                mode = IapRead(i - 2 + 1);
                if(i>=EEPromAddrEnd)
                {
                        TimEEPromAddr = EEPromAddrStr;
                        IapErase(EEPromAddrStr);
                }else{
                        TimEEPromAddr = i;
                }
      }
      ModeEEPromAddr = TimEEPromAddr+1;
      if((SwitchTime > 0) && (i!=EEPromAddrStr))
      {
                mode = ++mode % 5;
      }
      IapProgram(ModeEEPromAddr, mode);
      SwitchTime = 0xFF;
      GPIO_W(~(0x01<<mode));
    while (1)
      {
                if(TF0)//5ms
                {
                        TF0=0;
                        if(++delay>=75)//75 x 5ms = 375ms
                        {
                              delay=0;
                              if(SwitchTime)//8 x 375ms = 3000ms
                              {
                                        SwitchTime>>=1;
                                        IapProgram(TimEEPromAddr, SwitchTime);
                              }
                        }
                }
      }
}

vb2002 发表于 2024-8-6 18:06:05

Lkck8210 发表于 2024-8-6 16:57
用的是STC8G1K08A

我手电里也是用的 stc8g1k08a,,就这个体积小

vb2002 发表于 2024-8-6 18:43:22

wnagming 发表于 2024-8-6 13:34
要是没效果,就把PWM初始化放前面

是这个问题,,我把PWM放在eeprom后面就好了.
但是只解决了一半,,还是有点点闪,,不过可以接受了.
之前是超级闪,现在就是一丢丢闪

vb2002 发表于 2024-8-6 19:33:48

Lkck8210 发表于 2024-8-6 16:57
用的是STC8G1K08A

你这个代码,,我是不是直接就把这IO口改成PCA_PWM= 占空比数值就好了.!{:4_249:}



123 发表于 2024-8-6 20:44:31

磨损均衡算法,如你的程序EEPROM使用了32字节,分为16个区存储,每个区32字节(共1个扇区512字节),所有区用完了再擦再写。
一个区全部为0xFF表示无数据,任何一个字节不等于0xFF表示有数据
写:1区无数据则写进1区,有数据进入2区以此类推,16区有数据则擦除整个扇区写1区返回。
读:从16区读,有数据返回数据,无数据读15区以此类推,1区没有读到数据则没有数据。

Lkck8210 发表于 2024-8-6 20:58:34

vb2002 发表于 2024-8-6 19:33
你这个代码,,我是不是直接就把这IO口改成PCA_PWM= 占空比数值就好了.!

试试又不会逝世{:5_283:}

vb2002 发表于 2024-8-6 21:55:51

123 发表于 2024-8-6 20:44
磨损均衡算法,如你的程序EEPROM使用了32字节,分为16个区存储,每个区32字节(共1个扇区512字节),所有区用 ...

感谢你的解答,
已经有代码弄好了.
这个确实是大大延迟eeprom 寿命

vb2002 发表于 2024-8-6 21:56:31

Lkck8210 发表于 2024-8-6 20:58
试试又不会逝世

已经研究2小时了.
这几天估计都是捣鼓你的代码了.
非常整洁,调理清晰.{:4_250:}

vb2002 发表于 2024-8-6 23:23:03

Lkck8210 发表于 2024-8-6 20:58
试试又不会逝世

弄好了,参照你的代码我修改了两处,麻烦帮看看有没有问题可以吗?
还有一个,,我把

#define EEPromAddrStr 12
#define EEPromAddrEnd EEPromAddrStr+4000
这两句改了, eeprom 从12开始写,,写到4012 就擦除 1-8个扇区.这些写对吗?因为太长了.不好测试.
我的想法是从12开始写,写到4012后,就擦除前面扇区,然后从头开始写.









Lkck8210 发表于 2024-8-7 08:54:02

vb2002 发表于 2024-8-6 23:23
弄好了,参照你的代码我修改了两处,麻烦帮看看有没有问题可以吗?
还有一个,,我把



刷扇区要一个一个刷,没看到代码
页: 1 2 3 [4] 5
查看完整版本: 被这个代码卡脖子了..有大佬伸出援助之手吗?