内部 EEPROM 可以实现掉电保存数据,擦写次数大于 10 万次,可以有效解决数据丢失的问题,采用下面的程序可以读取单片机的上电次数:
eeprom.h:
#ifndef _EEPROM_H
#define _EEPROM_H
#include "reg52.h"
/****定义读写EEPROM所需的特殊功能寄存器****/
sfr ISP_DATA = 0XE2;
sfr ISP_ADDRH = 0XE3;
sfr ISP_DARRL = 0XE4;
sfr ISP_CMD = 0XE5;
sfr ISP_TRIG = 0XE6;
sfr ISP_CONTR = 0XE7;
/****定义命令字节****/
#define Read_CMD 0x01
#define Write_CMD 0x02
#define Erase_CMD 0x03
#define Enable_WaitTime 0x82; //定义操作的等待时间
void ISP_IAP_Disable(void);
void ISP_IAP_Trigger(void);
void ISP_IAP_ReadData( unsigned int BeginAddr , unsigned char* Buf , unsigned int DataSize );
void ISP_IAP_WriteData( unsigned int BeginAddr , unsigned char* Data , unsigned int DataSize );
void ISP_IAP_Erase( unsigned int Addr );
#endif
eeprom.c:
#include "eeprom.h"
//关闭ISP/IAP函数
void ISP_IAP_Disable(void)
{
EA = 1; //开中断
ISP_CONTR = 0;
ISP_CMD = 0;
ISP_TRIG = 0; //禁止ISP/IAP读、写、擦除操作
}
//触发ISP/IAP函数
void ISP_IAP_Trigger(void)
{
EA = 0; //先关闭总中断,防止中断响应打断下面两条语句
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9; //发送两条命令,使能ISP/IAP
}
//读数据函数
void ISP_IAP_ReadData( unsigned int BeginAddr , unsigned char* Buf , unsigned int DataSize )
{
ISP_DATA = 0; //清零数据寄存器
ISP_CMD = Read_CMD; //发送读取指令
ISP_CONTR = Enable_WaitTime; //开启ISP_IAP,并发送等待时间
while( DataSize -- )
{
ISP_ADDRH = ( unsigned char )( BeginAddr >> 8 ); //发送高8位
ISP_DARRL = ( unsigned char )( BeginAddr & 0x00FF );//发送低8位
ISP_IAP_Trigger();
BeginAddr ++; //地址+1
*Buf++=ISP_DATA; //将数据存储到接收缓冲区
}
ISP_IAP_Disable(); //关闭ISP_IAP功能
}
//写数据函数
void ISP_IAP_WriteData( unsigned int BeginAddr , unsigned char* Data , unsigned int DataSize )
{
ISP_CONTR = Enable_WaitTime; //开启ISP_IAP,并发送等待时间
ISP_CMD = Write_CMD; //发送写指令
while( DataSize -- )
{
ISP_ADDRH = ( unsigned char )( BeginAddr >> 8 ); //发送高8位
ISP_DARRL = ( unsigned char )( BeginAddr & 0x00FF );//发送低8位
ISP_DATA=*Data++; //发送数据
BeginAddr ++; //地址+1
ISP_IAP_Trigger();
}
ISP_IAP_Disable(); //关闭ISP_IAP功能
}
//擦除扇区函数
void ISP_IAP_Erase( unsigned int Addr )
{
ISP_CONTR = Enable_WaitTime; //开启ISP_IAP,并发送等待时间
ISP_CMD = Erase_CMD; //发送擦除指令
ISP_ADDRH = ( unsigned char )( Addr >> 8 ); //发送高8位
ISP_DARRL = ( unsigned char )( Addr & 0x00FF );//发送低8位
ISP_IAP_Trigger();
ISP_IAP_Disable(); //关闭ISP_IAP功能
}
main.c
#include "reg52.h"
#include "LCD1602.h"
#include "eeprom.h"
unsigned char Buf[5]; //数据缓冲区,类似串口中断的SBUF
unsigned char Str[8]; //存储字符变量
unsigned char Title[] = "Times of PowerOn";
void main(void)
{
LCD_Init(); //初始化LCD1602
ISP_IAP_ReadData( 0x21f0 , Buf , sizeof(Buf) ); //获取内部存储器中的数值
Buf[0]++;
Str[0] = Buf[0]/100 + '0'; //获取上电次数的百位
Str[1] = (Buf[0]%100)/10 + '0'; //获取上电次数的十位
Str[2] = Buf[0]%10 + '0'; //获取上电次数的个位
Str[4] = '0'; //结束
LCD_WriteString(1,1,Title);
LCD_WriteString(2,4,Str);
ISP_IAP_Erase( 0x2000 ); //擦除扇区
ISP_IAP_WriteData( 0x21f0 , Buf , sizeof(Buf) ); //写入数据
while(1);
}