主函数:
#include<reg52.h>
#include"EEPROM.h"
#include"smg.h"
void main()
{
num=byte_read(DEBUG_Data_Memory_Begin_Sector_addr);//字节读(程序开始时读取EEPROM中数据)
if(num>=60)num=0;//防止首次上电时读取出错??
while(1)
{
if(num<60)
{
display(num);
num++;delay(5);
delay1(DELAY_CONST);
sector_erase(DEBUG_Data_Memory_Begin_Sector_addr);//擦出扇区
byte_program (DEBUG_Data_Memory_Begin_Sector_addr,num);//字节编程}
if(num==60)num=0;
}
}
EEPROM.h:
/*STC89C51RC,STC89LE51RC 0x2000 共八个扇区
STC89C52RC,STC89LE52RC 0x2000 共八个扇区
STC89C54RD+,STC89LE54RD+ 0x8000 共五十八个扇区
STC89C55RD+,STC89LE55RD+ 0x8000 共五十八个扇区
STC89C58RD+,STC89LE58RD+ 0x8000 共五十八个扇区*/
#include<reg52.h>
#include<intrins.h>
//sfr定义特殊功能寄存器
sfr ISP_DATA =0xe2;//ISP/IAP 操作时的数据寄存器,从Flash 读出的数据放在此处,向Flash 写的数据也需放在此处
sfr ISP_ADDRH =0xe3;//ISP/IAP 操作时的地址寄存器高八位
sfr ISP_ADDRL =0xe4;//ISP/IAP 操作时的地址寄存器低八位
sfr ISP_CMD =0xe5;//ISP/IAP 操作时的命令模式寄存器,须命令触发寄存器触发方可生效
sfr ISP_TRIG =0xe6;//ISP/IAP 操作时的命令触发寄存器
sfr ISP_CONTR =0xe7;//ISP/IAP 控制寄存器
/* 定义命令*/
#define uchar unsigned char /*8bit无符号整型*/
#define uint unsigned int /*16bit无符号整型*/
#define READ_AP_and_Data_Memory_Command 0x01 /*字节读数据存储区*/
#define PROGRAM_AP_and_Data_Memory_Command 0x02 /*字节编程数据存储区*/
#define SECTOR_ERASE_AP_and_Data_Memory_Command 0x03 /*扇区擦除数据存储*/
#define DEBUG_Data_Memory_Begin_Sector_addr 0x2000//扇区地址
#define DELAY_CONST 60000//延时
#define WAIT_TIME 0x01
uchar num;
/* 打开ISP,IAP 功能*/
void ISP_IAP_enable(void)
{
EA=0;/* 关中断*/
ISP_CONTR=ISP_CONTR & 0x18; /* 0001,1000 */
ISP_CONTR=ISP_CONTR|WAIT_TIME;
ISP_CONTR=ISP_CONTR|0x80; /* 1000,0000 */
}
/* 关闭ISP,IAP 功能*/
void ISP_IAP_disable(void)
{
ISP_CONTR=ISP_CONTR&0x7f;/* 0111,1111 */
ISP_TRIG=0x00;
EA=1;/* 开中断*/
}
/* 字节读*/
uchar byte_read(uint byte_addr)
{
ISP_ADDRH = (uchar)(byte_addr >> 8);
ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD&0xf8;/* 1111,1000 */
ISP_CMD = ISP_CMD|READ_AP_and_Data_Memory_Command;/* 0000,0001 */
ISP_IAP_enable();
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
ISP_IAP_disable();
return (ISP_DATA);
}
/* 扇区擦除*/
void sector_erase(uint sector_addr)
{
uint get_sector_addr=0;
get_sector_addr=(sector_addr & 0xfe00); /* 1111,1110,0000,0000; 取扇区地址*/ ISP_ADDRH = (uchar)(get_sector_addr >> 8);
ISP_ADDRL = 0x00;
ISP_CMD = ISP_CMD&0xf8;/* 1111,1000 */
ISP_CMD =
ISP_CMD|SECTOR_ERASE_AP_and_Data_Memory_Command;/* 0000,0011 */ ISP_IAP_enable();
ISP_TRIG = 0x46;/* 触发ISP_IAP命令*/
ISP_TRIG = 0xb9;/* 触发ISP_IAP命令*/
_nop_();
ISP_IAP_disable();
}
/* 字节编程*/
void byte_program(uint byte_addr, uchar original_data)
{
ISP_ADDRH = (uchar)(byte_addr >> 8);
ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 1111,1000 */
ISP_CMD = ISP_CMD |
PROGRAM_AP_and_Data_Memory_Command; /* 0000,0010 */
ISP_DATA = original_data;
ISP_IAP_enable();
ISP_TRIG = 0x46; /* 触发ISP_IAP命令*/
ISP_TRIG = 0xb9; /* 触发ISP_IAP命令*/
_nop_();
ISP_IAP_disable();
}
void delay1(uint counter)
{
uint temp=0;
for(temp=counter;temp>0;temp--)
{
_nop_();
_nop_();
_nop_();
}
}
Smg.h:
/****************************************************************************** ****
* 标题: 试验数码管上显示数字( 单片机直接实现位选共阴极) *
* 用573锁存器控制和单片机脚直接位选控制(非译码器控制)数码管*
******************************************************************************* ****/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code smg_duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //段码0-9.
uchar code smg_wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F}; //位选控制查表的方法控制
void delay(uint i)
{
uchar j;
for(i;i>0;i--)
for(j=200;j>0;j--);
}
void display(uint dat)//数码管显示函数
{
uint i;
uint LedOut[10];
LedOut[0]=smg_duan[dat%10000/1000];//(若要显示小数点,则|0x80)
LedOut[1]=smg_duan[dat%1000/100];
LedOut[2]=smg_duan[dat%100/10];
LedOut[3]=smg_duan[dat%10];
for( i=0; i<4; i++)
{
P0=LedOut[i];
P2=smg_wei[i];//使用查表法进行位选
delay(10);//扫描间隔时间,数码管每位显示的时间,太长会数码管会有闪烁感}
}。