vb2002 发表于 2024-10-22 15:59:16

换了个思路,重新整理下eeprom按字节写入

关于我这个手电的换挡实现方法,之前我想复杂了,其实逻辑可以简单一点 首先定义一个sbit cap=P32;P32 连接一个22uf电容,然后接地.,上电后 P32在 0.5秒后,充满电应该是属于低电平,(P32=0)在这0.5秒内,应该属于高电平(P32=1).那我直接判断 if(P32==1) 那就写eeprom(按字节写入), 如果P32==0 那就读取上一次写的eeprom 这不就实现我的需求了吗?按照这个逻辑,我自己写了一个代码 .但是老是有问题.
#include "stc8g.h"
#include "intrins.h"
#include <stdio.h>

#define MAIN_Fosc 11059200UL
#define BRT         (65536 - MAIN_Fosc / 115200 / 4)

typedef unsigned char u8;
typedef unsigned int u16;

u8 dat;                                                //定义eeprom 储存数据,但实际好像没用上
u16 EEPROMId = 0x0020;                                //定义eeprom的地址

sbit cap = P3^2;                                        //p32引脚连电容,接地 做电平判定

void sys_init();                                        //声明系统初始化配置
void PWM_init(void);                                //声明pwm

void main()
{               
        unsigned char x;                                 //定义变量x 用于读取eeprom
        unsigned char y=5;                        //定义变量y用于保存pwm值
        sys_init();                                //调用系统配置

          P3M0 = 0x00; P3M1 = 0x00;              //P32 输出对电容充电
          P5M0 = 0x00; P5M1 = 0x00;               //pwm 设置在p55口

        x = IapRead(EEPROMId);                        //读取的当前eeprom 赋值给x       
       
        while(1)
        {       
                if(cap)                                //如果p32引脚 充电中 p32==1
                {
                IapProgram(EEPROMId,y);                //写地址为0x0020 为 y(以后设置为switch或者数组)

                EEPROMId=EEPROMId+1;                //下次写eeprom +10x0021 ,在下次0x0022 以此类推
                y=y+1;                                //pwm亮度 数组+1   (1,15,55,255)
       
                }
                CCAP2H=x;                                //把x写入的值 赋值给pwm

                if(EEPROMId >= 0X1FE)                                //如果当前字节到达EEPROM末尾,擦除扇区数据
                {       
                        IapErase(0x0020);                                //擦除扇区
               
                        EEPROMId = 0x0020;                        //从头开始按字节写入
                }
        }
}

void sys_init(void)
{
        P_SW2=0x80;
      PWM_init();
        EA=1;                        //打开总中断
}


//// 初始化PWM功能 P55 pwm
void PWM_init(void)
{
    P_SW1=0x20;
    CCON = 0x00;
    CMOD = 0x08;
    CL = 0x00;
    CH = 0x00;

    CCAPM2 = 0x42;
    PCA_PWM2 = 0x00;
    CCAP2L = 0x00;                  
    CCAP2H = 0x00;
    CR=1;       
}

void delayms(u16 ms)
{
        unsigned int i;
        do{
                i = MAIN_Fosc /10000;
                while(--i);
        }while(--ms);
}

void IapIdle()
{
        IAP_CONTR = 0;                                                 // 关闭 IAP 功能
        IAP_CMD = 0;                                                         // 清除命令寄存器
        IAP_TRIG = 0;                                                 // 清除触发寄存器

        IAP_ADDRH = 0x00;                                        // 清零高地址寄存器
        IAP_ADDRL = 0x00;                                        // 清零低地址寄存器
}

char IapRead(unsigned 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 高地址
        EA=0;
        _nop_();
        _nop_();       
        IAP_TRIG = 0x5a;                                         // 写触发命令 (0x5a)
        IAP_TRIG = 0xa5;                                         // 写触发命令 (0xa5)
        EA=1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        dat = IAP_DATA;                                         // 读 IAP 数据
        IapIdle();                                                                 // 关闭 IAP 功能
        return dat;

}
void IapProgram(unsigned 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 数据
        EA=0;
        _nop_();
        _nop_();       
        IAP_TRIG = 0x5a;                                         // 写触发命令 (0x5a)
        IAP_TRIG = 0xa5;                                         // 写触发命令 (0xa5)
        EA=1;       
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        IapIdle();                                                                // 关闭 IAP 功能

}
void IapErase(unsigned int addr)
{

        IAP_CONTR = 0x80;                                 // 使能 IAP
        IAP_TPS = 12;                                                 // 设置等待参数 12MHz
        IAP_CMD = 3;                                                         // 设置 IAP 擦除命令
        IAP_ADDRL = addr;                                 // 设置 IAP 低地址
        IAP_ADDRH = addr >> 8;                 // 设置 IAP 高地址

        EA=0;
        _nop_();
        _nop_();       
        IAP_TRIG = 0x5a;                                         // 写触发命令 (0x5a)
        IAP_TRIG = 0xa5;                                         // 写触发命令 (0xa5)
        EA=1;       
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        IapIdle();                                                                 // 关闭 IAP 功能

}
       


Lkck8210 发表于 2024-10-22 16:30:49

1. P32刚上电是低电平,0.5秒后才是高电平
2. EEPROMId 是变量,无论加到多少,上电后都会初始化
3. 你这代码是疲劳化EEProm, 1秒已经擦写166次(6ms),上电10分钟这芯片的0x0020扇区就会可能会GG了

soma 发表于 2024-10-22 18:04:15

如果p32开机是低电平会不会进入USB下载模式

晓飛飛 发表于 2024-10-22 18:14:03

正常上电后,去读EEPROM,遍历定位写到哪里去了,然后记录当前地址,下次记录挨着往进写,这样满一页就写下一页,有两个页够倒腾了。

vb2002 发表于 2024-10-22 18:27:25

Lkck8210 发表于 2024-10-22 16:30
1. P32刚上电是低电平,0.5秒后才是高电平
2. EEPROMId 是变量,无论加到多少,上电后都会初始化
3. 你这代 ...

是的,现在就是这样,每次上电都是重新读 eeprom了
我在printf查看的

vb2002 发表于 2024-10-22 18:28:37

晓飛飛 发表于 2024-10-22 18:14
正常上电后,去读EEPROM,遍历定位写到哪里去了,然后记录当前地址,下次记录挨着往进写,这样满一页就写下 ...

现在是一个页,每次上电eepromid都重置,不能跟上上一条eeprom的数据

vb2002 发表于 2024-10-22 18:31:19

Lkck8210 发表于 2024-10-22 16:30
1. P32刚上电是低电平,0.5秒后才是高电平
2. EEPROMId 是变量,无论加到多少,上电后都会初始化
3. 你这代 ...

应该也不会,,因为我没有擦除的,,只是写入而已,现在就是每次都重置eeprom

晓飛飛 发表于 2024-10-22 19:26:17

vb2002 发表于 2024-10-22 18:28
现在是一个页,每次上电eepromid都重置,不能跟上上一条eeprom的数据

EEPROM读是很快的,每次上电后先从头读EEPROM,看最后一条记录写到了哪里,然后接着那个地址往下写,直到写满一页再擦除或者写下一页。

Lkck8210 发表于 2024-10-23 09:12:50

vb2002 发表于 2024-10-22 18:31
应该也不会,,因为我没有擦除的,,只是写入而已,现在就是每次都重置eeprom
...

44行IapErase(0x0020);就是擦除啊

vb2002 发表于 2024-10-23 11:05:08

Lkck8210 发表于 2024-10-23 09:12
44行IapErase(0x0020);就是擦除啊
前面有个条件, 写到 字节0x1fe才擦除.
我用了delayms (1000)

关键是每次printf看到他1秒自增.. 断电后,马上有还原了..{:5_312:}
不会弄.还是不会弄
页: [1] 2
查看完整版本: 换了个思路,重新整理下eeprom按字节写入