找回密码
 立即注册
查看: 798|回复: 12

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

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:350
  • 最近打卡:2025-05-01 00:32:14
已绑定手机

130

主题

1520

回帖

1855

积分

金牌会员

积分
1855
发表于 2024-10-22 15:59:16 | 显示全部楼层 |阅读模式
关于我这个手电的换挡实现方法,之前我想复杂了,其实逻辑可以简单一点
首先定义一个sbit cap=P32;
P32 连接一个22uf电容,然后接地.,上电后 P32 0.5秒后,充满电应该是属于低电平,(P32=0)
在这0.5秒内,应该属于高电平(P32=1).
那我直接判断 if(P32==1) 那就eeprom(按字节写入), 如果P32==0 那就读取上一次写的eeprom
这不就实现我的需求了吗?  按照这个逻辑,我自己写了一个代码 .但是老是有问题.

  1. #include "stc8g.h"
  2. #include "intrins.h"
  3. #include <stdio.h>
  4. #define MAIN_Fosc 11059200UL
  5. #define BRT         (65536 - MAIN_Fosc / 115200 / 4)
  6. typedef unsigned char u8;
  7. typedef unsigned int u16;
  8. u8 dat;                                                //定义eeprom 储存数据,但实际好像没用上
  9. u16 EEPROMId = 0x0020;                                //定义eeprom的地址
  10. sbit cap = P3^2;                                        //p32引脚连电容,接地 做电平判定
  11. void sys_init();                                        //声明系统初始化配置
  12. void PWM_init(void);                                //声明pwm
  13. void main()
  14. {               
  15.         unsigned char x;                                 //定义变量x 用于读取eeprom
  16.         unsigned char y=5;                        //定义变量y用于保存pwm值
  17.         sys_init();                                  //调用系统配置
  18.           P3M0 = 0x00; P3M1 = 0x00;                //P32 输出对电容充电
  19.           P5M0 = 0x00; P5M1 = 0x00;                   //pwm 设置在p55口
  20.         x = IapRead(EEPROMId);                        //读取的当前eeprom 赋值给x       
  21.        
  22.           while(1)
  23.         {         
  24.                 if(cap)                                //如果p32引脚 充电中 p32==1
  25.                 {
  26.                 IapProgram(EEPROMId,y);                //写地址为0x0020 为 y(以后设置为switch或者数组)
  27.                 EEPROMId=EEPROMId+1;                //下次写eeprom +1  0x0021 ,在下次0x0022 以此类推
  28.                 y=y+1;                                //pwm亮度 数组+1   (1,15,55,255)
  29.          
  30.                 }
  31.                 CCAP2H=x;                                //把x写入的值 赋值给pwm
  32.                 if(EEPROMId >= 0X1FE)                                //如果当前字节到达EEPROM末尾,擦除扇区数据
  33.                 {       
  34.                           IapErase(0x0020);                                //擦除扇区
  35.                
  36.                         EEPROMId = 0x0020;                        //从头开始按字节写入
  37.                 }
  38.         }
  39. }
  40. void sys_init(void)
  41. {
  42.         P_SW2=0x80;
  43.       PWM_init();
  44.         EA=1;                        //打开总中断
  45. }
  46. //// 初始化PWM功能 P55 pwm
  47. void PWM_init(void)
  48. {
  49.     P_SW1=0x20;
  50.     CCON = 0x00;
  51.     CMOD = 0x08;
  52.     CL = 0x00;
  53.     CH = 0x00;
  54.     CCAPM2 = 0x42;
  55.     PCA_PWM2 = 0x00;
  56.     CCAP2L = 0x00;                  
  57.     CCAP2H = 0x00;
  58.     CR=1;       
  59. }
  60. void delayms(u16 ms)
  61. {
  62.         unsigned int i;
  63.         do{
  64.                 i = MAIN_Fosc /10000;
  65.                 while(--i);
  66.         }while(--ms);
  67. }
  68. void IapIdle()
  69. {
  70.         IAP_CONTR = 0;                                                 // 关闭 IAP 功能
  71.         IAP_CMD = 0;                                                         // 清除命令寄存器
  72.         IAP_TRIG = 0;                                                 // 清除触发寄存器
  73.         IAP_ADDRH = 0x00;                                        // 清零高地址寄存器
  74.         IAP_ADDRL = 0x00;                                        // 清零低地址寄存器
  75. }
  76. char IapRead(unsigned int addr)
  77. {
  78.        
  79.         char dat;
  80.         IAP_CONTR = 0x80;                                 // 使能 IAP
  81.         IAP_TPS = 12;                                                 // 设置等待参数 12MHz
  82.         IAP_CMD = 1;                                                         // 设置 IAP 读命令
  83.         IAP_ADDRL = addr;                                 // 设置 IAP 低地址
  84.         IAP_ADDRH = addr >> 8;                 // 设置 IAP 高地址
  85.         EA=0;
  86.         _nop_();
  87.         _nop_();       
  88.         IAP_TRIG = 0x5a;                                         // 写触发命令 (0x5a)
  89.         IAP_TRIG = 0xa5;                                         // 写触发命令 (0xa5)
  90.         EA=1;
  91.         _nop_();
  92.         _nop_();
  93.         _nop_();
  94.         _nop_();
  95.         dat = IAP_DATA;                                         // 读 IAP 数据
  96.         IapIdle();                                                                 // 关闭 IAP 功能
  97.         return dat;
  98. }
  99. void IapProgram(unsigned int addr, char dat)
  100. {
  101.         IAP_CONTR = 0x80;                                 // 使能 IAP
  102.         IAP_TPS = 12;                                                 // 设置等待参数 12MHz
  103.         IAP_CMD = 2;                                                        // 设置 IAP 写命令
  104.         IAP_ADDRL = addr;                                 // 设置 IAP 低地址
  105.         IAP_ADDRH = addr >> 8;                 // 设置 IAP 高地址
  106.         IAP_DATA = dat;                                         // 写 IAP 数据
  107.         EA=0;
  108.         _nop_();
  109.         _nop_();       
  110.         IAP_TRIG = 0x5a;                                         // 写触发命令 (0x5a)
  111.         IAP_TRIG = 0xa5;                                         // 写触发命令 (0xa5)
  112.         EA=1;       
  113.         _nop_();
  114.         _nop_();
  115.         _nop_();
  116.         _nop_();
  117.         IapIdle();                                                                // 关闭 IAP 功能
  118. }
  119. void IapErase(unsigned int addr)
  120. {
  121.         IAP_CONTR = 0x80;                                 // 使能 IAP
  122.         IAP_TPS = 12;                                                 // 设置等待参数 12MHz
  123.         IAP_CMD = 3;                                                         // 设置 IAP 擦除命令
  124.         IAP_ADDRL = addr;                                 // 设置 IAP 低地址
  125.         IAP_ADDRH = addr >> 8;                 // 设置 IAP 高地址
  126.         EA=0;
  127.         _nop_();
  128.         _nop_();       
  129.         IAP_TRIG = 0x5a;                                         // 写触发命令 (0x5a)
  130.         IAP_TRIG = 0xa5;                                         // 写触发命令 (0xa5)
  131.         EA=1;       
  132.         _nop_();
  133.         _nop_();
  134.         _nop_();
  135.         _nop_();
  136.         IapIdle();                                                                 // 关闭 IAP 功能
  137. }
  138.        
复制代码


回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:294
  • 最近打卡:2025-03-06 09:25:41

8

主题

318

回帖

1835

积分

金牌会员

积分
1835
发表于 2024-10-22 16:30:49 | 显示全部楼层
1. P32刚上电是低电平,0.5秒后才是高电平
2. EEPROMId 是变量,无论加到多少,上电后都会初始化
3. 你这代码是疲劳化EEProm, 1秒已经擦写166次(6ms),上电10分钟这芯片的0x0020扇区就会可能会GG了
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-01 09:54:52
已绑定手机

19

主题

3190

回帖

4866

积分

论坛元老

积分
4866
发表于 2024-10-22 18:04:15 来自手机 | 显示全部楼层
如果p32开机是低电平会不会进入USB下载模式
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:417
  • 最近打卡:2025-04-30 21:39:09
已绑定手机

34

主题

2096

回帖

2206

积分

荣誉版主

积分
2206
发表于 2024-10-22 18:14:03 | 显示全部楼层
正常上电后,去读EEPROM,遍历定位写到哪里去了,然后记录当前地址,下次记录挨着往进写,这样满一页就写下一页,有两个页够倒腾了。
睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:350
  • 最近打卡:2025-05-01 00:32:14
已绑定手机

130

主题

1520

回帖

1855

积分

金牌会员

积分
1855
发表于 2024-10-22 18:27:25 来自手机 | 显示全部楼层
Lkck8210 发表于 2024-10-22 16:30
1. P32刚上电是低电平,0.5秒后才是高电平
2. EEPROMId 是变量,无论加到多少,上电后都会初始化
3. 你这代 ...

是的,现在就是这样,每次上电都是重新读 eeprom了
我在printf查看的
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:350
  • 最近打卡:2025-05-01 00:32:14
已绑定手机

130

主题

1520

回帖

1855

积分

金牌会员

积分
1855
发表于 2024-10-22 18:28:37 来自手机 | 显示全部楼层
晓飛飛 发表于 2024-10-22 18:14
正常上电后,去读EEPROM,遍历定位写到哪里去了,然后记录当前地址,下次记录挨着往进写,这样满一页就写下 ...

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

点评

EEPROM读是很快的,每次上电后先从头读EEPROM,看最后一条记录写到了哪里,然后接着那个地址往下写,直到写满一页再擦除或者写下一页。  详情 回复 发表于 2024-10-22 19:26
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:350
  • 最近打卡:2025-05-01 00:32:14
已绑定手机

130

主题

1520

回帖

1855

积分

金牌会员

积分
1855
发表于 2024-10-22 18:31:19 来自手机 | 显示全部楼层
Lkck8210 发表于 2024-10-22 16:30
1. P32刚上电是低电平,0.5秒后才是高电平
2. EEPROMId 是变量,无论加到多少,上电后都会初始化
3. 你这代 ...

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:417
  • 最近打卡:2025-04-30 21:39:09
已绑定手机

34

主题

2096

回帖

2206

积分

荣誉版主

积分
2206
发表于 2024-10-22 19:26:17 | 显示全部楼层
vb2*** 发表于 2024-10-22 18:28
现在是一个页,每次上电eepromid都重置,不能跟上上一条eeprom的数据

EEPROM读是很快的,每次上电后先从头读EEPROM,看最后一条记录写到了哪里,然后接着那个地址往下写,直到写满一页再擦除或者写下一页。
睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:294
  • 最近打卡:2025-03-06 09:25:41

8

主题

318

回帖

1835

积分

金牌会员

积分
1835
发表于 2024-10-23 09:12:50 | 显示全部楼层
vb2*** 发表于 2024-10-22 18:31
应该也不会,,因为我没有擦除的,,只是写入而已,现在就是每次都重置eeprom
...

44行IapErase(0x0020);  就是擦除啊
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:350
  • 最近打卡:2025-05-01 00:32:14
已绑定手机

130

主题

1520

回帖

1855

积分

金牌会员

积分
1855
发表于 2024-10-23 11:05:08 | 显示全部楼层
Lkck*** 发表于 2024-10-23 09:12
44行IapErase(0x0020);  就是擦除啊

前面有个条件, 写到 字节0x1fe才擦除.
我用了delayms (1000)

关键是每次printf看到他1秒自增.. 断电后,马上有还原了..{:5_312:}
不会弄.还是不会弄
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 00:12 , Processed in 0.147770 second(s), 107 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表