📄 eepdemo.lst
字号:
C51 COMPILER V8.08 EEPDEMO 03/08/2009 13:41:49 PAGE 1
C51 COMPILER V8.08, COMPILATION OF MODULE EEPDEMO
OBJECT MODULE PLACED IN eepDemo.OBJ
COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE eepDemo.c BROWSE DEBUG OBJECTEXTEND
line level source
1 /*========================================================================
2 IAP操作使用片内flash作为eeprom使用的驱动程序。参考来源:www.mcu-memory.com
3
4 本演示代码通过对用户数据的读写操作,具体实现数据存储的组织方法,最大限度的
5 利用eeprom的空间。这只是对eeprom进行分配轮换使用的一种方法。
6 实现分配的思路:用户数组(需要记忆的部分)应该在4,8,16,32,64等字节以内,将第
7 一字节留作索引头:如果读到该字节为0x55(也可以定义为其他数),则认为已经找到
8 了有效的最后纪录,将本小区域数据读出。如果不是则继续跳到下一个小区域继续上
9 述操作,直到找到上一次的纪录为止,如果超出了eeprom的有效范围还没有找到,则
10 认为这是一块新的芯片,将默认的数据写入。
11 保存的时候,首先将刚才读到的那个数组的对应eeprom中的第一字节清零,以便下次
12 跳过,然后再推后一个小区域(记录长度),将数据写入。如果出现写入失败,接着到
13 再下一个区域,直到写入正确为止。
14 这里有一个问题就是,写到下一个小区域的时候会遇到跨扇区,只要判断出跨区,就
15 将上一个扇区擦除,以备下一轮循环再使用。
16 程序利用stc提供的下载板上的LED显示当前读或者写的地址,你可以看到led的"递减"
17 过程,演示读写256次,从第一次的全亮,到演示完毕也全亮,刚好256次。如果中途
18 断电,即会出现不同的结果,但再进行完演示的话,会发现结束时的led状态与开始
19 时的一样,否则就说明你的芯片内部eeprom有损坏。
20
21 演示代码仅针对stc89c54rd+/51rc进行了调试,但可以给其他芯片编程时作为参考。
22 晓奇工作室 http://www.xiao-qi.com/
23 ---- xiaoqi 2005.12
24 ======================================================================= */
25 #include <STC12C5410AD.H>
26 #include <intrins.h>
27
28 #define uchar unsigned char
29 #define uint unsigned int
30
31 /* STC89C54RD+的flash空间从0x4000~0xf3ff 共90个扇区,每扇区512字节 */
32 // #define BaseAddr 0x1000 /* 51rc */
33 // #define EndSectoraddr 0x3d00 /* 51rc */
34 // #define EndAddr 0x3fff /* 51rc 12K eeprom */
35
36 #define BaseAddr 0x0400
37 #define EndSectoraddr 0x2F00
38 #define EndAddr 0x2FFF
39
40 /* ------------- 定义扇区大小 ------------- */
41 #define PerSector 512
42
43 /* 用户程序需要记忆的数组, 用户实际使用了n-1个数据,数组长度规整到
44 2 4 8 16 32 64 上 */
45 uchar Ttotal[16] =
46 {
47 0x55, /* 作为判别引导头使用,用户程序请不要修改它 */
48 /* 用户保存记忆的数据 */
49 0x01, /* 用途说明....*/
50 0x02,
51 0x03,
52 0x04,
53 0x05,
54 0x06,
55 0x07,
C51 COMPILER V8.08 EEPDEMO 03/08/2009 13:41:49 PAGE 2
56 0x08,
57 0x09,
58 0x0a,
59 0x0b,
60 0x0c,
61 0x0d,
62 0x0e,
63 0x0f,
64 };
65
66 uint timerForDelay, /* 专供延时用的变量 */
67 i, /* 循环变量 */
68 EepromPtr; /* eeprom读写指针 */
69
70 /* ======================= IAP外部函数列表 =======================*/
71 /* 扇区擦除 */
72 extern void SectorErase(uint sector_addr);
73 /* byte 读 */
74 extern uchar byte_read(uint byte_addr);
75 /* byte 写 */
76 extern void byte_write(uint byte_addr, uchar original_data);
77 /* byte写并校验 */
78 extern uchar byte_write_verify(uint byte_addr, uchar original_data);
79 /* byte数组写并校验 */
80 extern uchar ArrayWrite(uint begin_addr, uint len, uchar *array);
81 /* byte数组读, 存在Ttotal[] */
82 extern void ArrayRead(uint begin_addr, uchar len);
83
84 /* ============================ 延时 ========================= */
85 void delay(int counter)
86 {
87 1 timerForDelay = counter;
88 1 while(timerForDelay);
89 1 }
90
91 /* ==============================================================
92 初始化开启定时器2,定时周期设定为10mS(下载板上 18.432M 晶振)
93 ============================================================== */
94 void initCT1()
95 {
96 1
97 1 TMOD = 0x01;
98 1 TH0 = 0xdc; // 定时器初值
99 1 TL0 = 0x00;
100 1 EA = 1;
101 1 ET0 = 1; // 允许T2中断
102 1 TR0 = 1; // 启动
103 1 }
104
105 /* ==============================================================
106 定时器CT2中断服务程序
107 ============================================================== */
108 timer1Int(void) interrupt 1 using 1
109 {
110 1 TH1 = 0xdc; // 定时器初值
111 1 TL1 = 0x00;
112 1
113 1 if(timerForDelay)timerForDelay--; /* 定时变量处理 */
114 1 }
115
116 /* ==============================================================
117 从eeprom中读取数据
C51 COMPILER V8.08 EEPDEMO 03/08/2009 13:41:49 PAGE 3
118 ============================================================== */
119 void DataRestore()
120 {
121 1 EepromPtr = BaseAddr; /* 指向eeprom的起始点 */
122 1 while(EepromPtr < EndAddr) /* 在eeprom的可用区域内 */
123 1 {
124 2 if(byte_read(EepromPtr) == 0x55)/* 找到了上一次有效纪录 */
125 2 {
126 3 break; /* 寻找完成 */
127 3 }
128 2 EepromPtr += 0x10; /* 指向下一个小区 */
129 2 }
130 1 if(EepromPtr >= EndAddr) /* 如果照遍都没有,是新片*/
131 1 {
132 2 EepromPtr = BaseAddr; /* 指向eeprom的起始点 */
133 2 for(i=0;i<90;i++)
134 2 {
135 3 SectorErase(EepromPtr+0x200*i); /* 全部扇区擦除 */
136 3 }
137 2 while(ArrayWrite(EepromPtr, 0x10, Ttotal)) /* 写默认值 */
138 2 { /* 写入失败才运行的部分 */
139 3 byte_write(EepromPtr, 0); /* 该单元已经失效 */
140 3 if(EepromPtr < EndAddr)
141 3 {
142 4 EepromPtr += 0x10; /* 换一块新的小区 */
143 4 }
144 3 else
145 3 {
146 4 P1=0; /* 指示芯片内eeprom全坏 */
147 4 EA= 0; /* 不再做任何事 */
148 4 while(1); /* 死机 */
149 4 }
150 3 }
151 2 }
152 1 ArrayRead(EepromPtr, 16);
153 1 }
154
155 /* ==============================================================
156 将需要记忆的数据保存到eeprom
157 ============================================================== */
158 void DataSave()
159 {
160 1 uint wrPtr; /* 临时指针 */
161 1
162 1 NextArea:
163 1 byte_write_verify(EepromPtr, 0); /* 将原来的标记清除 */
164 1 wrPtr = EepromPtr & 0xfe00; /* 上一个扇区的起始地址 */
165 1 EepromPtr += 0x10; /* 目标存入地址 */
166 1
167 1 /* ------------------ 判断是否启用新的扇区 ---------------- */
168 1 if((EepromPtr & 0x1ff)==0)
169 1 {
170 2 SectorErase(wrPtr); /* 将上一个扇区擦除,备用 */
171 2 if(EepromPtr>=EndAddr) /* 已经用完了最后一个区域 */
172 2 {
173 3 EepromPtr = BaseAddr; /* 从头开始 */
174 3 }
175 2 }
176 1 /* -------------------- 数据存入前的准备 ------------------ */
177 1 /* 。。。。。。。。。。。。。。转移、处理 */
178 1 Ttotal[0] = 0x55; /* 重申启用标记 */
179 1 if(ArrayWrite(EepromPtr, 0x10, Ttotal))
C51 COMPILER V8.08 EEPDEMO 03/08/2009 13:41:49 PAGE 4
180 1 { /* 数据写入,如果有错换一块 */
181 2 goto NextArea;
182 2 }
183 1 }
184
185 /* ================================================================
186 储存于读取的反复测试,每个小区域16字节,每个扇区512字节,即每个
187 扇区分成32个小块,每次写入顺序往后移动一个小区域,进行256次读写操作
188 实际上跨越了8个扇区。
189 按照51rc 12K eeprom计算,可以反复纪录7680万次
190 按照52rc 8K eeprom计算,可以反复纪录3840万次
191 按照54rd+45K eeprom计算,可以反复纪录2.88亿次
192 足够系统对记忆体的要求。
193 ================================================================ */
194 void main()
195 {
196 1 P1 = 0xff; /* 所有LED熄灭 */
197 1 initCT1(); /* CT2初始化,用来做定时器 */
198 1 /* ------------------ 演示 256 次读写操作 ----------------- */
199 1 for(i=0;i<256;i++)
200 1 {
201 2 DataRestore(); /* 从eeprom中读取记忆数据 */
202 2 P1 = (uchar)((EepromPtr >> 4) & 0xff); /* 显示读取地址 */
203 2 delay(1); /* 延时保留显示状态1秒 */
204 2 DataSave(); /* 数据再次保存 */
205 2 P1 = (uchar)((EepromPtr >> 4) & 0xff); /* 显示写入地址 */
206 2 delay(1); /* 延时保留显示状态1秒 */
207 2 }
208 1
209 1 while(1); /* 演示完毕 */
210 1 }
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 356 ----
CONSTANT SIZE = ---- ----
XDATA SIZE = ---- ----
PDATA SIZE = ---- ----
DATA SIZE = 22 ----
IDATA SIZE = ---- ----
BIT SIZE = ---- ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -