解: 取代的具体做法是,在第8章的源程序中,去掉与AT24C02有关的位寻址
定义和函数定义,把宏晶公司IAP技术资料加入到程序中来。然后,对源程序再作三处修改:
第一,把主函数中原对AT24C02的读操作,改为对片内EEPROM的读操作,并在前面增加一个指针变量的定义和赋值;
第二,把外中断INT1的中断服务函数中,对AT24C02的写操作,改为仅是对时间数组的赋值操作;
第三,在外中断INT0的中断服务函数中,增加对片内EEPROM的写入操作。 具体改动如下:
1 main()主函数中的增改:
(1) 增加指针变量的定义和赋值 unsigned char *p; p=0x2000;
(2) 把原来对AT24C02的循环读操作 AT24C0x_init(); for(i=0;i<121;i++)
mmhh[i]=AT24C0x_read(i);
改为如下对片内EEPROM的循环读操作 for(i=0;i<121;i++)
mmhh[i]=byte_read(p+i);//程序开始时读取EEPROM中数据 2 把INT1中断服务函数中的如下几行, AT24C0x_write(v,m); v++;
AT24C0x_write(v,u); v=v+1;
AT24C0x_write(0,ww); ww++;
改为如下几行,
mmhh[v++]=m; mmhh[v++]=u; mmhh[0]=ww++;
3 在INT0中断服务函数中增加以下几行, unsigned char *p; p=0x2000;
u=mmhh[0]*2;
SectorErase(0x2000);//擦除扇区 for(m=0;m<=u;m++)
byte_write(p+m,mmhh[m]);//重新写入数据
修改所得的源程序如下: 源程序
#include
#define uchar unsigned char
#define uint unsigned int
#define RdCommand 0x01 //定义ISP的操作命令 #define PrgCommand 0x02 #define EraseCommand 0x03 #define Error 1 #define Ok 0
#define WaitTime 0x01 //定义CPU的等待时间 sfr ISP_DATA=0xe2; //寄存器申明 sfr ISP_ADDRH=0xe3; sfr ISP_ADDRL=0xe4; sfr ISP_CMD=0xe5; sfr ISP_TRIG=0xe6; sfr ISP_CONTR=0xe7;
sbit SCLK=P2^4; /* 实时时钟的时钟线引脚*/ sbit DATA=P2^5; /* 实时时钟的数据线*/ sbit RST=P2^6; /* 实时时钟的复位线引脚*/ sbit gw=P2^3; //个位 sbit sw=P2^2; //十位 sbit bw=P2^1; //百位 sbit qw=P2^0; //千位 sbit s3=P1^0; sbit s4=P1^1; sbit s5=P1^2; sbit s6=P1^3; sbit jw=P1^7; sbit ds=P1^0;
sbit sda=P2^7; //IO口定义 sbit scl=P3^6; sbit led=P1^4; sbit SPEAK=P1^5;
uchar Utime[7]={01,48,21,8,01,05,10}; // 秒 分 时 日 月 星期 年 uchar idata mmhh[121];
uchar zz; //定义计数值,每过1秒,sec加1 uchar xsd=255; uchar xsdb=255; uchar jfb=0; uchar c1a=0; uchar c1b=255; uint temp;
delayx(uint z)//延时函数 {
uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); }
Delay() /*延时*/ {
uchar m,n;
int max,min,time; n=0;zz=mmhh[0]*2;
for(m=1;m<=12;m=m+4) {
min=mmhh[m]*100+mmhh[m+1]; max=mmhh[m+2]*100+mmhh[m+3]; time=Utime[2]*100+Utime[1]; if(time>=min&&time<=max) {led=0;break;} else
{led=1;} }
for(m=13;m<=zz;m=m+2)
if(mmhh[m+1]==Utime[1]&&mmhh[m]==Utime[2]) {SPEAK=0;break;} else
{SPEAK=1;} }
Disp_led( int m) {
uchar code num[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; int n; qw=1; bw=1; sw=1; gw=1;
//显示千位上的数 n=m/1000; //取得千位数上的数 P0 = num[n];//把数字的笔划码赋给P0口 P0=P0|c1a; P0=P0&c1b; qw=0;/*开通千位(左边第一位)上的数码管显示*/ Delay();//延时 qw=1;
//显示百位上的数 n=m/100;//取得百位上的数 P0 = num[n];//把数字笔划码赋给P0口 P0=P0&xsdb;
bw=0;/*开通百位(左起第二位)上的数码管显示*/ Delay();//延时 bw=1; //显示十位上的数 n=m/10;//取得十位上的数
P0 =num[n];//把数字笔划码赋给P0口 P0=P0&xsd; sw=0;/*开通十位(左起第三位)上的数码管显示*/ Delay();//延时 sw=1; //显示个位上的数 n=m; //取得个位上的数
P0 = num[n];//把数字笔划码赋给P0口
gw=0;/*开通个位(左起第四位)上的数码管显示*/ Delay();//延时 gw=1; }
Wbit1302(uchar dat) {
uchar i;
for(i=0;i<8;i++) //连续写8个二进制位数据 { SCLK=0; DATA=dat&0x01; //取出dat的第0位数据写入1302 SCLK=1; //上升沿写入数据 dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位 } }
Wbyte1302(uchar Cmd,uchar dat) {
RST=0;
SCLK=0; //只有在SCLK为低电平时,才能将RST置为高电平 RST=1; //启动数据传输 Wbit1302(Cmd); //写入命令字
Wbit1302(dat); //写数据 SCLK=1; //将时钟电平置于已知状态 RST=0; //终止数据传递 }
uchar Rbit1302() {
uchar i,dat;
for(i=0;i<8;i++) //连续读8个二进制位数据 { SCLK=0; //拉低SCLK,形成脉冲下降沿读出数据
dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位 if(DATA==1) //如果读出的数据是1 dat|=0x80; //dat的最高位被或上1 SCLK=1; //将SCLK置于高电平,为产生下降沿作准备 }
return dat; //将读出的数据返回 }
uchar Rbyte1302(uchar Cmd) {
uchar dat,k;
RST=0; //拉低RST
SCLK=0; //只有在SCLK为低电平时,才能将RST置为高电平 RST=1; //启动数据传输 Wbit1302(Cmd); //写入命令字 dat=Rbit1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态 RST=0; //终止数据传递 k=dat/16;
dat=dat+k*10;
return dat; //将读出的数据返回 }
Puts1302()// 把时间数组数据输出到1302 {
uchar i,j;
uchar ucAddr=0x80;
Wbyte1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/ for(i=0;i<7;i++) {
j=Utime[i];
Wbyte1302(ucAddr,j); /* 秒 分 时 日 月 星期 年 */ ucAddr +=2;