找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1988|回复: 0
打印 上一主题 下一主题
收起左侧

Proteus软件c51单片机lcd\DS1302实现时钟功能

[复制链接]
跳转到指定楼层
楼主
时钟可以显示掉秒

#include"reg52.h"
#define uint unsigned int
#define uchar unsigned char
uchar a,miao,fen,shi,day,week,month,year,key1n,flag,temp;
#define yi 0x80
#define er 0x80+0x40
sbit rs=P2^0;//RS
sbit en=P2^2;//E
sbit rw=P2^1;//RW

sbit led=P2^6;
sbit IO=P2^5;//时钟
sbit RST=P2^3;//时钟
sbit SCLK=P2^4;//时钟
sbit ACC0=ACC^0;//累加器
sbit ACC7=ACC^7;//累加器
sbit key1=P3^2;//设置
sbit key2=P3^3;//加
sbit key3=P3^4;//减
sbit buzzer=P3^5;//喇叭
uchar code tab1[]={"20  -  -  "};//年月日1
uchar code tab2[]={"  :  :  "};
void delay(uint xms)
  {
  uint x,y;
  for (x=xms;x>0;x--)
    for (y=110;y>0;y--);
   }
  void write_1602com(uchar com) //1603液晶写入指令函数***
   {
   rs=0;//数据/指令选择置为指令
   rw=0;//读写选择置为写
   en=0;
   P0=com;//送入指令
   delay(1);
   en=1;
   delay(1);
   en=0;
   }
  void write_1602dat(uchar dat)//***液晶写入数据函数***
   {
    rs=1;//数据/指令选择置为数据
    rw=0;//读写选择置为写
    en=0;
    P0=dat;//送入数据
    delay(1);
    en=1;
    delay(1);
    en=0;
    }
  void lcd_clr()//***液晶初始化函数***
    {
     write_1602com(0x38);//设置16*2显示,5*7点阵,8位数据接口
  write_1602com(0x0c);//设置LCD显示开,光标显示关。
  write_1602com(0x06);//写一个数据后地址加1
  write_1602com(0x01);//显示清屏
  write_1602com(yi+1);//年月日在第一行
  for(a=0;a<14;a++)
    {
    write_1602dat(tab1[a]);
    delay(3);
    }
    write_1602com(er+2);
    for(a=0;a<8;a++)
     {
       write_1602dat(tab2[a]);
    delay(3);
    }
   }
  void write_byte(uchar dat)   //DS1302有关子函数  写一个字节8byte
    {
    ACC=dat;RST=1;
     for(a=8;a>0;a--)
   {
     IO=ACC0;
     SCLK=0;
     SCLK=1;
     ACC=ACC>>1;
          }
  }
   uchar read_byte()    //读一个字节
     {
    RST=1;
     for(a=8;a>0;a--)
      {
   ACC7=IO;
   SCLK=1;
   SCLK=0;
   ACC=ACC>>1;
   }
   return(ACC);
     }
  void write_1302(uchar add,uchar dat)//向1302芯片写数据,指定写入地址,数据
     {
     RST=0;
     SCLK=0;
     RST=1;
     write_byte(add);
            write_byte(dat);
     SCLK=1;
     RST=0;
     }
  uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址
    {
     uchar temp;
   RST=0;
   SCLK=0;
   RST=1;
   write_byte(add);
   temp=read_byte();
   SCLK=1;
   RST=0;
   return(temp);
    }
  uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制
     {
       uchar Decimal;
    Decimal=bcd>>4; //bcd码右移四位高四位(十位)—转到——低四位(个位)
    return(Decimal=Decimal*10+(bcd&=0x0F));//bcd=bcd&0x0f保留bcd低四位其他位清零
     }
  void ds1302_clr()//1302芯片初始化函数(2008-6-30,10:00,week1)
     {
        RST=0;SCLK=0;
              write_1302(0x8e,0x00);// 允许写,禁止写保护
     write_1302(0x80,0x00);// 秒写入秒寄存器0x80,写入初始秒数据00
     write_1302(0x82,0x00);// 分写入分寄存器0x82,写入初始分数据00
     write_1302(0x84,0x10);// 时写入时寄存器0x84,写入初始时数据10
     write_1302(0x8a,0x05);// 周写入周寄存器0x8a,写入初始时数据1
     write_1302(0x86,0x12);// 日写入日寄存器0x86,写入初始时数据30
     write_1302(0x88,0x0B);// 月写入时寄存器0x88,写入初始时数据06
     write_1302(0x8c,0x10);// 年写入时寄存器0x8c,写入初始时数据16
     write_1302(0x8e,0x80);// 打开写保护
     }

  void write_sfm(uchar add,uchar dat)//时 分 秒 可能为两位数
     {
       uchar gw,sw;
    gw=dat%10;//取得个位数字
    sw=dat/10;//区的十位数字
    write_1602com(er+add);//显示行数
    write_1602dat(0x30+sw);
    write_1602dat(0x30+gw);  
     }
  void write_nyr(uchar add,uchar dat)//年 月 日
      {
             uchar gw,sw;
    gw=dat%10;
    sw=dat/10;
    write_1602com(yi+add); // 设定显示位置为第一个位置+add
    write_1602dat(0x30+sw);//数字+30得到该数字的lcd1602显示码
    write_1602dat(0x30+gw);//同上
    }
     void write_week(uchar week)//写星期函数
      {
    write_1602com(yi+12);//星期字符的显示位置
   
     switch(week)
      {
        case 1:write_1602dat('M');//星期数为1时,显示
           write_1602dat('O');
        write_1602dat('N');
        break;
     case 2:write_1602dat('T');
           write_1602dat('U');
        write_1602dat('E');
        break;
     case 3:write_1602dat('W');
           write_1602dat('E');
        write_1602dat('D');
        break;
     case 4:write_1602dat('T');
           write_1602dat('H');
        write_1602dat('U');
        break;
     case 5:write_1602dat('F');
        write_1602dat('R');
        write_1602dat('I');
        break;
     case 6:write_1602dat('S');
           write_1602dat('T');
        write_1602dat('A');
        break;
     case 7:write_1602dat('S');
           write_1602dat('U');
        write_1602dat('N');
        break;
    }
   }
   void timealarm()
    {
     if(shi>7)//大于7点才启动报时
     {
       if(key1==1)//不按下设置按键时才有效
       {
      if(fen==0&&miao<30)
      {
      
      
        buzzer=0;//启动蜂鸣器
      
      }
      else buzzer=1;
       }
     }
    }
          void keyscan()//键盘扫描有关函数
      {
     if(key1==0)//key1为功能键(设置键)
      {
        delay(9); //延时消抖动
       if(key1==0)//判断按键是否按下,按下为0
         {
        buzzer=0;
        delay(20);
        buzzer=1;
         while(!key1);//按键释放
      key1n++;
       if(key1n==9)
        key1n=1;
        switch(key1n)
         {
           case 1:TR0=0;//关闭定时器
              TR1=0;
           write_1602com(er+0x09);//设置按键按动一次,秒位置显示光标
           write_1602com(0x0f); //全屏显示 光标显示 显示光标闪烁
           /*temp=(miao)/10*16+(miao)%10;//
           write_1302(0x8e,0x00);
           write_1302(0x80,0x80|temp);//miao
           write_1302(0x8e,0x80);*/
           break;
        case 2:write_1602com(er+0x06);  //按两次 分位置显示光标(可按key2 或 key3进行上调或下调)
              write_1602com(0x0f);
           break;
       case 3:write_1602com(er+0x03);//按三次 时
             write_1602com(0x0f);
          break;
       case 4:write_1602com(yi+0x0e);//按四次week
             write_1602com(0x0f);
          break;
          case 5:write_1602com(yi+0x0a);//按五次日
             write_1602com(0x0f);
          break;
          case 6:write_1602com(yi+0x07);//按六次月
             write_1602com(0x0f);
          break;
          case 7:write_1602com(yi+0x04);//按七次年
             write_1602com(0x0f);
          break;
       case 8:write_1602com(0x0c);
             TR0=1;
          temp=(miao)/10*16+(miao)%10;
          write_1302(0x8e,0x00);
          write_1302(0x80,0x00|temp);//miao数据写入1302
          write_1302(0x8e,0x80);
          break;
            
        }
        }
    }
     if(key1n!=0)
      {
       if(key2==0)
        {
       delay(10);
       if(key2==0);
       {
         buzzer=0;
      delay(20);
      buzzer=1;
      while(!key2);
      switch(key1n)
      {
       case 1:miao++;//设置键按动一次,调秒
         if(miao==60)
         miao=0;  //miao
         write_sfm(0x08,miao);
         temp=(miao)/10*16+(miao)%10;
         write_1302(0x8e,0x00);
         write_1302(0x80,temp);
         write_1302(0x8e,0x80);
         write_1602com(er+0x09);//lcd秒位置显示光标
        
         break;
        case 2:fen++;
          if(fen==60)
          fen=0;
        write_sfm(0x05,fen);//fen
        temp=(fen)/10*16+(fen)%10;
        write_1302(0x8e,0x00);
        write_1302(0x82,temp);
        write_1302(0x8e,0x80);
        write_1602com(er+6);
        break;
      case 3:shi++;
          if(shi==24)
          shi=0;
        write_sfm(0x02,shi);
        temp=(shi)/10*16+(shi)%10;
        write_1302(0x8e,0x00);
        write_1302(0x84,temp);
        write_1302(0x8e,0x80);
        write_1602com(er+3);
        break;
     case 4:week++;
          if(week==8)
          week=1;
        write_1602com(yi+0x0c);
        write_week(week);
        temp=(week)/10*16+(week)%10;
        write_1302(0x8e,0x00);
        write_1302(0x8a,temp);
        write_1302(0x8e,0x80);
        write_1602com(yi+0x0e);
        break;
     case 5:day++;
            if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
               {if(day==32)
                 day=1;}
         else if(month==4||month==6||month==9||month==11)
              {
              if(day==31)
             day=1;
             }
         else if(month==2)
            {
          if(year%4==0||year%100==0&&year%400==0)
             {
            if(day==30)
               day=1;
            }
           else if(day==29)
               day=1;
           }
         write_nyr(0x09,day);
         temp=(day)/10*16+(day)%10;
         write_1302(0x8e,0x00);
         write_1302(0x86,temp);
         write_1302(0x8e,0x80);
         write_1602com(yi+10);
         break;
     case 6:month++;
             if(month==13)
       month=1;
       write_nyr(0x06,month);
       temp=(month)/10*16+(month)%10;
       write_1302(0x8e,0x00);
       write_1302(0x88,temp);
       write_1302(0x8e,0x80);
       write_1602com(yi+7);
       break;
        case 7:year++;  
          if(year==100)
       year=0;
       write_nyr(3,year);
       temp=(year)/10*16+(year)%10;
       write_1302(0x8e,0x00);
       write_1302(0x8c,temp);
       write_1302(0x8e,0x80);
       write_1602com(yi+4);
       break;
                         }
        }
        }
    if(key3==0)
      {
        delay(10);
       if(key3==0)
       {
         buzzer=0;
      delay(20);
      buzzer=1;
       while(!key3);
       switch(key1n)
      {
       case 1:miao--;//设置键按动一次,调秒
         if(miao==-1)
         miao=59;  //miao
         write_sfm(0x08,miao);
         temp=(miao)/10*16+(miao)%10;
         write_1302(0x8e,0x00);
         write_1302(0x80,temp);
         write_1302(0x8e,0x80);
         write_1602com(er+0x09);//lcd秒位置显示光标
         break;
        case 2:fen--;
          if(fen==-1)
          fen=59;
        write_sfm(0x05,fen);//fen
        temp=(fen)/10*16+(fen)%10;
        write_1302(0x8e,0x00);
        write_1302(0x82,temp);
        write_1302(0x8e,0x80);
        write_1602com(er+6);
        break;
      case 3:shi--;
          if(shi==-1)
          shi=23;
        write_sfm(0x02,shi);
        temp=(shi)/10*16+(shi)%10;
        write_1302(0x8e,0x00);
        write_1302(0x84,temp);
        write_1302(0x8e,0x80);
        write_1602com(er+3);
        break;
     case 4:week--;
          if(week==0)
          week=7;
        write_1602com(yi+0x0c);
        write_week(week);
        temp=(week)/10*16+week%10;
        write_1302(0x8e,0x00);
        write_1302(0x8a,temp);
        write_1302(0x8e,0x80);
        write_1602com(yi+0x0e);
        break;
     case 5:day--;
            if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
               {if(day==-1)
                 day=31;}
         else if(month==4||month==6||month==9||month==11)
              {
              if(day==-1)
             day=30;
             }
         else if(month==2)
            {
          if(year%4==0||year%100==0&&year%400==0)
             {
            if(day==-1)
               day=29;
            }
          else if(day==-1)
             day=28;
           }
         write_nyr(0x09,day);
         temp=(day)/10*16+(day)%10;
         write_1302(0x8e,0x00);
         write_1302(0x86,temp);
         write_1302(0x8e,0x80);
         write_1602com(yi+10);
         break;
     case 6:month--;
             if(month==0)
       month=12;
       write_nyr(6,month);
       temp=(month)/10*16+(month)%10;
       write_1302(0x8e,0x00);
       write_1302(0x88,temp);
       write_1302(0x8e,0x80);
       write_1602com(yi+7);
       break;
        case 7:year--;  
          if(year==-1)
       year=99;
       write_nyr(3,year);
       temp=(year)/10*16+(year)%10;
       write_1302(0x8e,0x00);
       write_1302(0x8c,temp);
       write_1302(0x8e,0x80);
       write_1602com(yi+4);
       break;
                         }
      
      }
     }
     
     }
               }
      void init()
    {
      TMOD=0x11;//指定定时/计数的工作方式
    TH0=0;//定时器T0的高四位=0
    TL0=0;//定时器T0的低四位=0
    EA=1;// 系统允许有开放的中断
    ET0=1;//允许T0中断
    TR0=1;//开启中断,启动定时器
              }
    //**************主程序*************//
    void main()
    {
      lcd_clr();
  
            ds1302_clr();
   init();
   led=0;
   buzzer=0;
   delay(80);
   buzzer=1;
   while(1)
   {
     keyscan();//调用键盘扫描子函数
     }
    }
    void timer0()interrupt 1
     {
      
    miao=BCD_Decimal(read_1302(0x81));
    fen=BCD_Decimal(read_1302(0x83));
    shi=BCD_Decimal(read_1302(0x85));
    day=BCD_Decimal(read_1302(0x87));
    month=BCD_Decimal(read_1302(0x89));
    year=BCD_Decimal(read_1302(0x8d));
    week=BCD_Decimal(read_1302(0x8b));
    write_sfm(8,miao);
    write_sfm(5,fen);
    write_sfm(2,shi);
    write_nyr(9,day);
    write_nyr(6,month);
    write_nyr(3,year);
    write_week(week);
    timealarm();
    }
字符手册.pdf (1.29 MB, 下载次数: 5) 51hei1302.zip (119.95 KB, 下载次数: 17)





分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表