基于24C08带掉电记忆功能的两路电子跑表

#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned int
uchar tent,tent1,secbf,secbf1;sec,min,sec1,min1;
 
bit write_secbf=0,write_secbf1=0;

sbit scl_24=P2^6;
sbit sda_24=P2^7;
sbit en=P1^2;
sbit rs=P1^0;
sbit rw=P1^1;
sbit gnd=P2^5;
sbit puss=P2^3;
sbit clear=P2^2;
sbit puss1=P2^1;
sbit start=P2^0;
 void delay(int i) 
{ uchar x,y;
for (x=i;x>0;x--)
 for(y=110;y>0;y--); 
}

/**********1602子程序****************************/

void write_com(uchar com)
{
  rs=0;
  P0=com;
  delay(5);
  en=1;
  delay(5);
  en=0;
}

void write_dat(uchar dat)
{
 rs=1;
 P0=dat;
 delay(5);
 en=1;
 delay(5);
 en=0;
 
}


void init_1602()
{
en=0;
rw=0;
write_com(0x38);
write_com(0x0c);//如果输入0X0F会是什么效果
write_com(0x06);
write_com(0x01);
write_com(0x80);
}


/**************************延时子程序***********************/


void usdelay() 
{
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_(); 
}

/***************以下开始为24CXX用子程序**********************/


void star24() //开始信号
{//时钟线在高电平时,数据线由高变低即为开始信号 由高变低即为开始信号
sda_24=1;
usdelay();
scl_24=1;
usdelay();
sda_24=0;//数据线由高变低即为开始信号
usdelay();
scl_24=0;
}

void stop24() //结束信号
{//时钟线在高电平时,数据线由低变高即为结束信号
sda_24=0;
usdelay();
scl_24=1;
usdelay();
sda_24=1;
usdelay();
sda_24=0; //这句可有可无
scl_24=0; //这句可有可无
}

void Ack24()  
{ uchar i;
scl_24=1;
usdelay(); 
    while((sda_24==1)&&(i<200))i++;
scl_24=0;
    usdelay();
}
/*
void NoAck24()  //不应答
{
sda_24=1; //时钟线高电平时,数据线高,即为不应答
usdelay();
    scl_24=1;
usdelay();
scl_24=0;
    usdelay(); 
} */

void init_24()
{
sda_24=1;
usdelay(); 
scl_24=1;
usdelay(); 
}


void write_byte(uchar dat)
{
uchar i,temp;
temp=dat;
//scl_24=0;//低电平可以变数据,为高时是读,且不能变
for(i=0;i<8;i++)
  {
   temp=temp<<1;
   scl_24=0;
   usdelay();
 sda_24=CY;//CY是PSW寄存器中的CY位,再把CY赋给SDA,再由SCL控制发出去
 //sda_24=(bit)(temp&0x80);//用这句也可以换掉上一句(bit)是强制转换命令,把数据转成非0即1
   usdelay();
   scl_24=1;
   usdelay();
  }
  scl_24=0;
  usdelay();
  sda_24=1;//释放总线
  usdelay();
}

uchar read_byte()
{

uchar i,k;
scl_24=0; //这句可有可无
usdelay(); //这句可有可无
sda_24=1; //释放总线
usdelay();
for(i=0;i<8;i++)
  {
   scl_24=1;
   usdelay();
   k=(k<<1)|sda_24;//判断8次,移位7次
   scl_24=0;
   usdelay();
   
  }
return k;
}

void write_add(uchar add,uchar dat)
{
 star24();
 write_byte(0xa0);//呼叫器件,高四位为定了的1010,即A,低四位三个接了地,所以为000,最后一个0是写标志
 Ack24();//写了后要马上应答
 write_byte(add);//写要往哪个地址写数据00-1023
 Ack24();//每写一次要给一个应答位
  write_byte(dat);//把数据写入
   Ack24();
  stop24();//给一个停止位,结束写数据
}


uchar read_add(uchar add)
{
 uchar dat;
 star24();
 write_byte(0xa0);//呼叫器件,高四位为定了的1010,即A,低四位三个接了地,所以为000,最后一个0是写标志
 Ack24();//写了后要马上应答
 write_byte(add);//写入要往哪个地址读数据00-1023
 Ack24();//每写一次要给一个应答位
 star24();
 write_byte(0xa1);//呼叫器件,高四位为定了的1010,即A,低四位三个接了地,所以为000,最后一个1是读标志
 Ack24();//写了后要马上应答
 dat=read_byte();
 stop24();//给一个停止位,结束读数据
 return dat;
}

void display_secbf(uchar dat)
{
 
 write_com(0x80+13);
 write_dat(0x30+dat);
 

}

void display_secbf1(uchar dat)
{
 
 write_com(0x80+0x40+13);
 write_dat(0x30+dat);
 
}


void display_sec(uchar add,uchar dat)
{
 uchar a,b;
 a=dat/10;
 b=dat%10;
 write_com(0x80+add);
 write_dat(0x30+a);
 write_dat(0x30+b);
  write_dat('.');
}

void display_sec1(uchar add,uchar dat)
{
 uchar a,b;
 a=dat/10;
 b=dat%10;
 write_com(0x80+0x40+add);
 write_dat(0x30+a);
 write_dat(0x30+b);
  write_dat('.');
}

void display_min(uchar add,uchar dat)
{
 uchar a,b;
 a=dat/10;
 b=dat%10;
 write_com(0x80+add);
 write_dat(0x30+a);
 write_dat(0x30+b);
  write_dat(':');
}

void display_min1(uchar add,uchar dat)
{
 uchar a,b;
 a=dat/10;
 b=dat%10;
 write_com(0x80+0x40+add);
 write_dat(0x30+a);
 write_dat(0x30+b);
  write_dat(':');

void keyscan()
{  
   if (start==0)
   {
    TR0=~TR0;
TR1=~TR1;
   }
  if(puss==0)
    {
delay(30);
while(!puss);
TR0=~TR0;
}

  if(puss1==0)
    {
delay(30);
while(!puss1);
TR1=~TR1;
}


 if(clear==0)
    {

delay(30);
while(!clear);
secbf=0;
write_add(0,0);
write_add(0,0);
sec=0;
write_add(1,0);
write_add(1,0);
min=0;
write_add(2,0);
write_add(2,0);
display_secbf(secbf);
display_sec(10,sec);
display_min(7,min);
TR0=0;

secbf1=0;
write_add(10,0);
 write_add(10,0);
sec1=0;
write_add(11,0);
write_add(11,0);
min1=0;
write_add(12,0);
write_add(12,0);

display_secbf1(secbf);
display_sec1(10,sec);
display_min1(7,min);
TR1=0;
}
}


void N01()
{
display_secbf(secbf);
display_sec(10,sec);
display_min(7,min);
if(secbf==10) 
{
secbf=0;   //定时10秒,如果满了,从0重新开始
sec++;  
   if(sec==60)
    {
 sec=0;
 min++;  
 if(min==60)
 min=0; 
 write_add(2,min);
 }
write_add(1,sec);  
}
  if(write_secbf==1)
    {
 write_secbf=0;
 write_add(0,secbf);
 
}
 
}

 

void N02()
{
display_secbf1(secbf1);
display_sec1(10,sec1);
display_min1(7,min1);
if(secbf1==10) 
{
secbf1=0;   //定时10秒,如果满了,从0重新开始
sec1++;  
   if(sec1==60)
    {
 sec1=0;
 min1++;  
 if(min1==60)
  min1=0;   
  write_add(12,min1);
 }
 
 write_add(11,sec1);
}
  if(write_secbf1==1)
    {
 write_secbf1=0;
 write_add(10,secbf1);  
}
 
}


void main()
{
 gnd=0;
 init_1602();
 init_24();
 secbf=read_add(0);//从地址2中读出以前保存的数据 
 if(secbf==10)    secbf=0; //防止首次读出错误数据
 sec=read_add(1);
 min=read_add(2);

 secbf1=read_add(10);//从地址2中读出以前保存的数据 
 if(secbf1==10)    secbf1=0; //防止首次读出错误数据
 sec1=read_add(11);
 min1=read_add(12);


 TMOD=0x11;//定时器工作方式1
 ET0=1; // 开启 定时器中断使能
 EA=1; // 总中断打开
 TH0=(65536-5000)/256;
 TL0=(65536-5000)%256;
 TR0=0;//计时开始

 ET1=1; // 开启 定时器中断使能
 
 TH1=(65536-5000)/256;
 TL1=(65536-5000)%256;
 TR1=0;//计时开始
 while(1)
   {
     keyscan();
    N01();
N02();
   }

}


void t0()interrupt 1
{
 TH0=(65536-5000)/256;
 TL0=(65536-5000)%256;
 tent++;//每中断一次自加1,每次中断约50MS
 if(tent==20)
    {
tent=0;
secbf++;
write_secbf=1;//数据更新标志位,1/10秒写一次24C08
}
}

void t1()interrupt 3
{
 TH1=(65536-5000)/256;
 TL1=(65536-5000)%256;
 tent1++;//每中断一次自加1,每次中断约50MS
 if(tent1==20)
    {
tent1=0;
secbf1++;
write_secbf1=1;//数据更新标志位,1/10秒写一次24C08
}
}

永不止步步 发表于12-16 10:55 浏览65240次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67410个|学分:305067个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号