微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 时钟—ds1302+数码管显示

时钟—ds1302+数码管显示

时间:10-02 整理:3721RD 点击:
搞了好久,终于写好了,
//**** 功能说明:时钟+数码管显示*************************************//
//***  key1功能按键,按一次,进入调分模式(key2加,key3减,**********//
//***  按二次key1,进入调时模式(key2加,key3减,)******************//
//***  按三次key1,进入正常模式**************************************//
//***  同时开机蜂鸣器响一声,按键按下都响一声************************//
#include<reg51.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char

sbit SCK=P3^6;  
sbit SDA=P3^5;  
sbit RST=P3^7;
sbit key1=P3^0; // 功能按键
sbit key2=P3^1;//key2加,
sbit key3=P3^2;//key3减,
sbit SPK=P3^3; // 蜂鸣器
/*复位脚*/
#define RST_CLR RST=0/*电平置低*/
#define RST_SET RST=1/*电平置高*/
/*双向数据*/
#define IO_CLR SDA=0/*电平置低*/
#define IO_SET SDA=1/*电平置高*/
#define IO_R SDA/*电平读取*/
/*时钟信号*/
#define SCK_CLR SCK=0/*时钟信号*/
#define SCK_SET SCK=1/*电平置高*/
#define ds1302_sec_add   0x80  //秒数据地址
#define ds1302_min_add   0x82  //分数据地址
#define ds1302_hr_add   0x84  //时数据地址
#define ds1302_date_add   0x86  //日数据地址
#define ds1302_month_add  0x88  //月数据地址
#define ds1302_day_add   0x8a  //星期数据地址
#define ds1302_year_add   0x8c  //年数据地址
#define ds1302_control_add  0x8e  //控制数据地址
#define ds1302_charger_add  0x90      
#define ds1302_clkburst_add  0xbe
bit flng=0; //anjian标志位
uchar wei[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar code tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xbf};// 显示段码值0-9和-
uchar time_buf1[8] = {20,9,3,13,18,51,00,6};//空年月日时分秒周
uchar time_buf[8] ;//空年月日时分秒周
uchar disp[8];
uchar com=0;
void adjust();                   //调整后写入函数
void keyscan();                  //按键函数
uchar spe_ak(uchar y,uchar x) ;  //蜂鸣器函数
void  delayus(uchar a)            //延迟                        
{
    uchar i,j;
     for(i=0;i<a;i++)
      for(j=0;j<110;j++);
}

/*向DS1302写入一字节数据*/
void ds1302_write_byte( uchar addr, uchar d) {
unsigned char i;
RST_SET;     /*启动DS1302总线*/

/*写入目标地址:addr*/
addr = addr & 0xFE;/*最低位置零*/
for (i = 0; i < 8; i ++) {
     
  if (addr & 0x01) {
   IO_SET;
   }
  else {
   IO_CLR;
   }
  SCK_SET;
  SCK_CLR;
  addr = addr >> 1;
  }

/*写入数据:d*/
for (i = 0; i < 8; i ++) {
     
  if (d & 0x01) {
   IO_SET;
   }
  else {
   IO_CLR;
   }
  SCK_SET;
  SCK_CLR;
  d = d >> 1;
  }
RST_CLR;     /*停止DS1302总线*/
}
/*从DS1302读出一字节数据*/
uchar ds1302_read_byte(uchar addr) {
unsigned char i;
unsigned char temp;
RST_SET;     /*启动DS1302总线*/
/*写入目标地址:addr*/
addr = addr | 0x01;/*最低位置高*/
for (i = 0; i < 8; i ++) {
      
  if (addr & 0x01) {
   IO_SET;
   }
  else {
   IO_CLR;
   }
  SCK_SET;
  SCK_CLR;
  addr = addr >> 1;
  }

/*输出数据:temp*/
for (i = 0; i < 8; i ++) {
  temp = temp >> 1;
  if (IO_R) {
   temp |= 0x80;
   }
  else {
   temp &= 0x7F;
   }
  SCK_SET;
  SCK_CLR;
  }

RST_CLR;     /*停止DS1302总线*/
return temp;
}
/*向DS302写入时钟数据*/
void ds1302_write_time(void) {
     
    unsigned char i,tmp;
for(i=0;i<8;i++){           //BCD处理
  tmp=time_buf1[i]/10;
  time_buf[i]=time_buf1[i]%10;
  time_buf[i]=time_buf[i]+tmp*16;
}
ds1302_write_byte(ds1302_control_add,0x00);   //关闭写保护
ds1302_write_byte(ds1302_sec_add,0x80);    //暂停
//ds1302_write_byte(ds1302_charger_add,0xa9);   //涓流充电
ds1302_write_byte(ds1302_year_add,time_buf[1]);  //年
ds1302_write_byte(ds1302_month_add,time_buf[2]); //月
ds1302_write_byte(ds1302_date_add,time_buf[3]);  //日
ds1302_write_byte(ds1302_day_add,time_buf[7]);  //周
ds1302_write_byte(ds1302_hr_add,time_buf[4]);  //时
ds1302_write_byte(ds1302_min_add,time_buf[5]);  //分
ds1302_write_byte(ds1302_sec_add,time_buf[6]);  //秒
ds1302_write_byte(ds1302_day_add,time_buf[7]);  //周
ds1302_write_byte(ds1302_control_add,0x80);   //打开写保护
   
}
/*从DS302读出时钟数据*/
void ds1302_read_time()
{
     unsigned char i,tmp;
time_buf[1]=ds1302_read_byte(ds1302_year_add);  //年
time_buf[2]=ds1302_read_byte(ds1302_month_add);  //月
time_buf[3]=ds1302_read_byte(ds1302_date_add);  //日
time_buf[4]=ds1302_read_byte(ds1302_hr_add);  //时
time_buf[5]=ds1302_read_byte(ds1302_min_add);  //分
time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7F;//秒
time_buf[7]=ds1302_read_byte(ds1302_day_add);  //周
     
   
for(i=0;i<8;i++)
      {           //BCD处理
  tmp=time_buf[i]/16;
  time_buf1[i]=time_buf[i]%16;
  time_buf1[i]=time_buf1[i]+tmp*10;
}
     
   
}
/*DS302初始化函数*/
void ds1302_init(void) {

RST_CLR;   /*RST脚置低*/
SCK_CLR;   /*SCK脚置低*/
    ds1302_write_byte(ds1302_sec_add,0x00);     
}
uchar spe_ak(uchar y,uchar x)         //y声音持续时间 ,x 发声的频率
{  uint i;
       for(i=0;i<y;i++)//喇叭发声的时间循环,改变大小可以改变发声时间长短
             {
             delayus(x);     //参数决定发声的频率,估算值,可以自行更改参数并
             SPK=!SPK;
             }
             SPK=1;            //喇叭停止工作,间歇的时间,可更改
             delayus(x);
     return 0 ;
}
  
void display()                         //显示函数
{   
     uchar i;
    //  P1=0x01;
     disp[0]=time_buf1[4]/10;
     disp[1]=time_buf1[4]%10;
     disp[2]=10;
     disp[3]=time_buf1[5]/10;
     disp[4]=time_buf1[5]%10;
     disp[5]=10;
     disp[6]=time_buf1[6]/10;
     disp[7]=time_buf1[6]%10;
                                    
     for(i=0;i<8;i++)
      {  
         P1=wei[i];
         P2=tab[disp[i]];
         delayus(5);
      }
      delayus(1);
}     
void timer0() interrupt 1               //定时器0
{  
   TH0=(65635-50000)/256;
   TL0=(65635-50000)%256;
   if(key1==0)
     {
      delayus(20);
       if(key1==0)         
          {   TR0=0;
              spe_ak(250,1);
              flng=1;
            com++;
           if(com==3)
           com=0;
          }
       while(!key1) ; //等待 按起
      TR0=1;
    }
   
}
void keyscan()                       //按键函数
  {
     switch(com)
    {  
       case 0: { // adjust();
                    flng=0;
                 }
         break;
       case 1:{
                ds1302_write_byte(ds1302_sec_add,0x80);    //暂停
                if(key2==0)
                 { delayus(20);
                  if(key2==0)
                    {  spe_ak(250,1);
                    time_buf[5]=(++time_buf1[5])%60;  //加分  
                   if(time_buf1[5]==60)
                      { time_buf1[5]=0;  }
                     
                    }
                   while(!key2); //等待 按起                  
                 }
                 if(key3==0)
                 { delayus(20);
                  if(key3==0)
                    {  spe_ak(250,1);
                    time_buf1[5]=(--time_buf1[5])%60;  //减分
                   if(time_buf1[5]==0)
                     { time_buf1[5]=59;  }
                     
                    }
                   while(!key3); //等待 按起                  
                 }
               ds1302_write_byte(ds1302_sec_add,0x00);    //结束暂停
              }
        break;
       case 2:{    ds1302_write_byte(ds1302_sec_add,0x80);    //暂停
                 if(key2==0)
                 { delayus(20);
                  if(key2==0)
                    { spe_ak(250,1);
                    time_buf1[4]=(++time_buf1[4])%24;  //加时  
                     if(time_buf1[4]==23)
                      { time_buf1[4]=0;  }
                    }
                   while(!key2); //等待 按起                  
                 }
                 if(key3==0)
                 { delayus(20);
                  if(key3==0)
                    {  spe_ak(250,1);
                    time_buf[4]=(--time_buf1[4])%24;  //减时  
                      if(time_buf1[4]==0)
                      { time_buf1[4]=23;  }
                    }
                   while(!key3); //等待 按起                  
                 }
                  ds1302_write_byte(ds1302_sec_add,0x00);    //结束暂停
              }
          break;
         
    }
     adjust();
}
void adjust()//时钟调节
{
   ds1302_write_byte(ds1302_control_add,0x00);   //关闭写保护
   ds1302_write_byte(ds1302_hr_add,(time_buf1[4]/10<<4)|(time_buf1[4]%10));  //时
   ds1302_write_byte(ds1302_min_add,(time_buf1[5]/10<<4)|(time_buf1[5]%10));  //分
  ds1302_write_byte(ds1302_control_add,0x80);   //打开写保护
}
void timer_init()   //定时器初始化
{
  IE=0X82;
   TMOD=0X01;
   TH0=(65635-50000)/256;
   TL0=(65635-50000)%256;
   TR0=1;
}
main()
{
    P0=0XFF;
    spe_ak(250,1);
    timer_init();//定时器初始化
    ds1302_init();

      
     ds1302_write_time();
      
   
   while(1)
    { if(flng==1)
        {
          keyscan();
           delayus(2);  
           ds1302_read_time();
          display();
         }  
    else           
        { ds1302_read_time();
             delayus(2);   
          display();  }
         
    }
}
说明:只显示时、分、秒,其他(年,月...)的已读出,自己修改,
仿真已通过


鼓励鼓励,                                       

谢谢
         

。。

图片中间那块,,,让新手很尴尬,..

下载学习

也在学习1302 ,支持小编

截图时没注意,不好意思,段选接P2口,开关是p3.0 p3.1.p3.2

在图片中间弄个东西挡住,不懂啊······

                  好东西

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top