//以下程序,是例用STC自带的EEPROM,掉线存储,计录开机次数,以STC89C52RC为例
//按下复位也可以,单片机断电也可以
#include "reg51.h"
#include "intrins.h"
typedef unsigned int u16;
typedef unsigned char u8;
typedef unsigned char BYTE;
typedef unsigned int WORD;
u8 code smg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
0x6f,0x77,0x7c,0x58,0x5e,0x79,0x71};
/*Declare SFR associated with the IAP */
sfr IAP_DATA = 0xE2; //Flash data register
sfr IAP_ADDRH = 0xE3; //Flash address HIGH
sfr IAP_ADDRL = 0xE4; //Flash address LOW
sfr IAP_CMD = 0xE5; //Flash command register
sfr IAP_TRIG = 0xE6; //Flash command trigger
sfr IAP_CONTR = 0xE7; //Flash control register
/*Define ISP/IAP/EEPROM command*/
#define CMD_IDLE 0 //Stand-By
#define CMD_READ 1 //Byte-Read
#define CMD_PROGRAM 2 //Byte-Program
#define CMD_ERASE 3 //Sector-Erase
/*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
//#define ENABLE_IAP 0x80 //if SYSCLK<40MHz
#define ENABLE_IAP 0x81 //if SYSCLK<20MHz
//#define ENABLE_IAP x82 //if SYSCLK<10MHz
//#define ENABLE_IAP 0x83 //if SYSCLK<5MHz
//Start address for STC89C58xx EEPROM
#define IAP_ADDRESS 0x02000 //自带EEPROM存储器地址
BYTE dat; //Data buffer
void Delay(BYTE n);
void delay_1ms(BYTE o);
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);
void main()
{
WORD i; //定义变量I为开机次数
P0=0;
Delay(2);
IapReadByte(IAP_ADDRESS); //开机先读一次地址的数据,以STC89C52RC为例,
i=dat;
i=i+1; //开机次数加1
if(i==100) //当开机次数大于100,从1开计
{i=0;}
IapEraseSector(IAP_ADDRESS); // 在写入数据前先要擦掉这个地址数据
IapProgramByte(IAP_ADDRESS, i); // 写入数据
//P2=i;
while (1)
{
P2=0; //以下是显示部分,根据自己的板改下就可以了
P0=smg[i%10/1]; //没了
delay_1ms(1);
P0=0;
P2=4;
P0=smg[i%100 / 10];
delay_1ms(1);
P0=0;
}
}
/*----------------------------
Software delay function
----------------------------*/
void Delay(BYTE n)
{
WORD x;
while (n--)
{
x = 0;
while (++x);
}
}
void delay_1ms(BYTE o)
{
while(o--);
}
/*----------------------------
Disable ISP/IAP/EEPROM function
Make MCU in a safe state 读写使能
----------------------------*/
void IapIdle()
{
IAP_CONTR = 0; //Close IAP function
IAP_CMD = 0; //Clear command to standby
IAP_TRIG = 0; //Clear trigger register
IAP_ADDRH = 0x80; //Data ptr point to non-EEPROM area
IAP_ADDRL = 0; //Clear IAP address to prevent misuse
}
/*----------------------------
Read one byte from ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
Output:Flash data
从一个字节读一个字节
输入:地址(ISP/IAP / EEPROM的地址)
输出:闪存数据
----------------------------*/
BYTE IapReadByte(WORD addr)
{
IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
IAP_CMD = CMD_READ; //Set ISP/IAP/EEPROM READ command
IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
IAP_TRIG = 0x46; //Send trigger command1 (0x46)
IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
_nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
dat = IAP_DATA; //Read ISP/IAP/EEPROM data
IapIdle(); //Close ISP/IAP/EEPROM function
return dat; //Return Flash data
}
/*----------------------------
Program one byte to ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
dat (ISP/IAP/EEPROM data)
Output:-
将一个字节编程到
输入:地址(ISP/IAP / EEPROM的地址)
数据(数据)
输出:—
----------------------------*/
void IapProgramByte(WORD addr, BYTE dat)
{
IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
IAP_CMD = CMD_PROGRAM; //Set ISP/IAP/EEPROM PROGRAM command
IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
IAP_DATA = dat; //Write ISP/IAP/EEPROM data
IAP_TRIG = 0x46; //Send trigger command1 (0x46)
IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
_nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
IapIdle();
}
/*----------------------------
Erase one sector area
Input: addr (ISP/IAP/EEPROM address)
Output:-
擦除一个扇区区域
输入:地址(ISP/IAP / EEPROM的地址)
输出:—
----------------------------*/
void IapEraseSector(WORD addr)
{
IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
IAP_CMD = CMD_ERASE; //Set ISP/IAP/EEPROM ERASE command
IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
IAP_TRIG = 0x46; //Send trigger command1 (0x46)
IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
_nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
IapIdle();
}
程序稍长,英文注释我没改,懒,,加了一点点中文注释