• STC单片机20——DS1302可调电子时钟1602显示proteus仿真


    #include
    #include
    #define uchar unsigned char
    #define uint  unsigned int

    sbit ACC0 = ACC^0;
    sbit ACC7 = ACC^7;
    sbit t=P1^0;//进入调时按键
    sbit jia=P1^1;//加一按键
    sbit jian=P1^2;//减一按键
    sbit m=P1^3;//退出调时按键
    sbit BEEP=P2^0;//蜂鸣器
    sbit jtod=P1^4;//矩阵按键转独立按键,该脚置0
    sbit T_CLK = P1^6; /*实时时钟时钟线引脚 */
    sbit T_IO = P3^5; /*实时时钟数据线引脚 */
    sbit T_RST = P1^7; /*实时时钟复位线引脚 */
    sbit E=P2^7;        //1602使能引脚
    sbit RW=P2^6;        //1602读写引脚    
    sbit RS=P2^5;        //1602数据/命令选择引脚
    uchar code hanzi[][8]={{0x04,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02},{0x0f,0x09,0x0f,0x09,0x0f,0x09,0x13,0x11},{0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00}};

    void v_W1302(uchar ucAddr, uchar ucDa);
    uchar uc_R1302(uchar);
    uchar dectobcd(uchar bcd);
    uchar bcdtodec(uchar);
    void beep();
    void delay(uchar x)
    {
      uchar i;
      while(x--)
      for(i=0;i<110;i++);
    }

    /********************************************************************
    * 名称 : enable(uchar del)
    * 功能 : 1602命令函数
    * 输入 : 输入的命令值
    * 输出 : 无
    ***********************************************************************/

    void enable(uchar del)
    {
        RS = 0;
        RW = 0;
        P0 = del;
        E = 1;
        delay(3);
        E=0;
    }

    /********************************************************************
    * 名称 : write(uchar del)
    * 功能 : 1602写数据函数
    * 输入 : 需要写入1602的数据
    * 输出 : 无
    ***********************************************************************/

    void write(uchar del)
    {
        RS = 1;
        RW = 0;
        P0 = del;
        E = 1;
        delay(3);
        E=0;
    }

    /********************************************************************
    * 名称 : L1602_init()
    * 功能 : 1602初始化,请参考1602的资料
    * 输入 : 无
    * 输出 : 无
    ***********************************************************************/
    void L1602_init(void)
    {
        enable(0x01);
        enable(0x38);
        enable(0x06);
        enable(0x0c);
        E=0;
    }

    //装入自定义字符(汉字)
    void writch()
    {
      uchar i,j;
      enable(0x40);
      for(i=0;i<8;i++)
        for(j=0;j<8;j++)
          write(hanzi[i][j]);
    }
    /********************************************************************
    * 名称 : L1602_char(uchar hang,uchar lie,char sign)
    * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
             L1602_char(1,5,'b')
    * 输入 : 行,列,需要输入1602的数据
    * 输出 : 无
    ***********************************************************************/
    void L1602_char(uchar hang,uchar lie,char sign)
    {
        uchar a;
        if(hang == 1) a = 0x80;
        if(hang == 2) a = 0xc0;
        a = a + lie - 1;
        enable(a);
        write(sign);
    }

    /********************************************************************
    * 名称 : L1602_string(uchar hang,uchar lie,uchar *p)
    * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
              L1602_string(1,5,"ab cd ef;")
    * 输入 : 行,列,需要输入1602的数据
    * 输出 : 无
    ***********************************************************************/
    void L1602_string(uchar hang,uchar lie,uchar *p)
    {
        uchar a;
        if(hang == 1) a = 0x80;
        if(hang == 2) a = 0xc0;
        a = a + lie - 1;
        enable(a);
        while(1)
        {
            if(*p == '\0') break;
            write(*p);
            p++;
        }
    }
    //时钟调节//
    void timechange()
    {
      uchar a,num=1;
      uchar year,mon,day,hour,min,sec;
    //进入调时循环
      while(num)
      {
       if(t==0)        //进入调时按键
       delay(5);
       if(t==0)
       {
         num++;
         beep();
         while(!t);
        }
    //退出调时按键m
        if(m==0)
         delay(5);
        if(m==0)
         num=0;
          enable(0x0f);
            a=uc_R1302(0x81)|0x80;
          v_W1302(0x8e,0);
          v_W1302(0x80,a);
    //调时到年以后退出调时
        if(num==7)
        num=0;
    //num=1调秒
        if(num==1)
        {
         enable(0xc0+12);
         if(jia==0)
         delay(5);
         if(jia==0)                  //秒加一
         {
           while(!jia);
           sec=bcdtodec(uc_R1302(0x81)&0x7f);
           sec++;       
           if(sec>59)
              sec=0;
           L1602_char(2, 12, sec/10%10+48);
           L1602_char(2, 13, sec%10 + 48);
           v_W1302(0x80,dectobcd(sec)|0x80);
          }
         if(jian==0)              //秒减一
         delay(5);
         if(jian==0)
         {
           while(!jian);
           sec=bcdtodec(uc_R1302(0x81));
           sec--;       
           if(sec==-1)
              sec=59;
           L1602_char(2, 12, sec/10%10+48);
           L1602_char(2, 13, sec%10 + 48);
           v_W1302(0x80,dectobcd(sec)|0x80);
          }
        }

         if(num==2)               //调分钟
         {
           enable(0xc0+9);
         if(jia==0)
         delay(5);
         if(jia==0)
         {
           min = bcdtodec(uc_R1302(0x83));
           min++;
           while(!jia);
           if(min>59)
              min=0;
          L1602_char(2, 9, min / 10 % 10 + 48);
          L1602_char(2, 10, min % 10 + 48);
          v_W1302(0x82,dectobcd(min));
         }
         if(jian==0)
         delay(5);
         if(jian==0)
         {
           min = bcdtodec(uc_R1302(0x83));
           min--;
           while(!jian);
           if(min==-1)
              min=59;
          L1602_char(2, 9, min / 10 % 10 + 48);
          L1602_char(2, 10, min % 10 + 48);
          v_W1302(0x82,dectobcd(min));
         }
           }
         if(num==3)              //调小时
         {
           enable(0xc0+6);
         if(jia==0)
         delay(5);
         if(jia==0)
          {
           hour = bcdtodec(uc_R1302(0x85));
           hour++;
           while(!jia);
           if(hour>23)
              hour=0;
           L1602_char(2, 6, hour / 10 % 10 + 48);
           L1602_char(2, 7, hour % 10 + 48);
           v_W1302(0x84,dectobcd(hour));
          }
          if(jian==0)
         delay(5);
         if(jian==0)
          {
           while(!jian);
           hour = bcdtodec(uc_R1302(0x85));
           hour--;       
           if(hour==-1)
              hour=23;
           L1602_char(2, 6, hour / 10 % 10 + 48);
           L1602_char(2, 7, hour % 10 + 48);
           v_W1302(0x84,dectobcd(hour));
          }
         }
         if(num==4)              //调日期
         {
           enable(0x80+13);
         if(jia==0)
         delay(5);
         if(jia==0)
         {
           hour = bcdtodec(uc_R1302(0x87));
           day++;
           while(!jia);
           if(day>31)
              day=0;
           L1602_char(1, 13, day / 10 % 10 + 48);
           L1602_char(1, 14, day % 10 + 48);
           v_W1302(0x86,dectobcd(day));
          }
         if(jian==0)
         delay(5);
         if(jian==0)
         {
           while(!jian);
           day=bcdtodec(uc_R1302(0x87));
           day--;       
           if(day==-1)
              day=31;
           L1602_char(1,13,day/10%10+48);
           L1602_char(1,14,day%10+48);
           v_W1302(0x86,dectobcd(day));
          }
         }
         if(num==5)                //调月份
         {
           enable(0x80+10);
         if(jia==0)
         delay(5);
         if(jia==0)
          {
          mon = bcdtodec(uc_R1302(0x89));
           mon++;
                 while(!jia);
               if(mon>12)
               mon=0;
          L1602_char(1, 10, mon / 10 % 10 + 48);
          L1602_char(1, 11, mon % 10 + 48);
             v_W1302(0x88,dectobcd(mon));
          }
          if(jian==0)
         delay(5);
         if(jian==0)
          {
            while(!jian);
            mon = bcdtodec(uc_R1302(0x89));
            mon--;             
               if(mon==-1)
               mon=12;
          L1602_char(1, 10, mon / 10 % 10 + 48);
          L1602_char(1, 11, mon % 10 + 48);
             v_W1302(0x88,dectobcd(mon));
          }
         }
         if(num==6)                //调年份
         {
           enable(0x80+7);
         if(jia==0)
         delay(5);
         if(jia==0)
         {
           year = bcdtodec(uc_R1302(0x8d));
           year++;
           while(!jia);
           if(year>20)
              year=0;
           L1602_char(1, 7, year / 10 % 10 + 48);
           L1602_char(1, 8, year % 10 + 48);
           v_W1302(0x8c,dectobcd(year));
         }
         if(jian==0)
         delay(5);
         if(jian==0)
         {
           while(!jian);
           year = bcdtodec(uc_R1302(0x8d));
           year--;       
           if(year==-1)
              year=20;
           L1602_char(1, 7, year / 10 % 10 + 48);
           L1602_char(1, 8, year % 10 + 48);
           v_W1302(0x8c,dectobcd(year));
         }
         }
        }
        if(num==0)                //关闭光标闪烁
        {
        enable(0x0c);
        }
        v_W1302(0x80,uc_R1302(0x81)&0x7f);    //开启1302记时
    }
    /********************************************************************
    * 名称 :  v_RTInputByte()
    * 功能 :  往DS1302写入1Byte数据
    * 输入 :  ucDa 写入的数据
    * 输出 :  无
    ***********************************************************************/
    void v_RTInputByte(uchar ucDa)
    {
        uchar i;
        ACC = ucDa;
        T_RST = 1;
        for(i=8; i>0; i--)
        {
            T_IO = ACC0;
            T_CLK = 1;
            T_CLK = 0;
            ACC = ACC >> 1;
        }
    }

    /********************************************************************
    * 名称  :   uc_RTOutputByte()
    * 功能  :   从DS1302读取1Byte数据
    * 输入  :    无
    * 返回值:   ACC
    ***********************************************************************/
    uchar uc_RTOutputByte(void)
    {
        uchar i;
        T_RST = 1;
        for(i=8; i>0; i--)
        {
            ACC = ACC >>1;
            ACC7 = T_IO;     /*实时时钟数据线引脚 */
            T_CLK = 1;
            T_CLK = 0;
        }
        return(ACC);
    }

    /********************************************************************
    * 名称   :   v_W1302(uchar ucAddr, uchar ucDa)
    * 功能   :   往DS1302写入数据
    * 输入   :   ucAddr: DS1302地址, ucDa: 要写的数据
    * 返回值 :   无
    ***********************************************************************/
    void v_W1302(uchar ucAddr, uchar ucDa)
    {
        T_RST = 0;
        T_CLK = 0;
        T_RST = 1;
        v_RTInputByte(ucAddr);   // 写地址
        _nop_();
        _nop_();
        v_RTInputByte(ucDa);     // 写1Byte数据
        T_CLK = 1;
        T_RST = 0;
    }
    /********************************************************************
    * 名称   :  uc_R1302(uchar ucAddr)
    * 功能   :  读取DS1302某地址的数据
    * 输入   :  ucAddr: DS1302地址
    * 返回值 :  ucDa :读取的数据
    ***********************************************************************/
    uchar uc_R1302(uchar ucAddr)
    {
        uchar ucDa;
        T_RST = 0;
        T_CLK = 0;
        T_RST = 1;
        v_RTInputByte(ucAddr);    //写地址,命令
        _nop_();
        _nop_();
        ucDa = uc_RTOutputByte(); //读1Byte数据
        T_CLK = 1;
        T_RST = 0;
        return(ucDa);
    }
    /********************************************************************
    * 名称 : bcdtodec(uchar bcd)
    * 功能 : BCD码转换为DEC码(DEC码为十进制数据:BCD:0x11->DEC为数值11(HEX:0x0b))
    * 输入 : bcd码
    * 输出 : dec码
    ***********************************************************************/
    uchar bcdtodec(uchar bcd)
    {
        uchar data1;
        data1=((bcd&0x70)>>4)*10+(bcd&0x0f);
        return data1;
    }

    uchar dectobcd(uchar dec)
    {
        uchar dat;
        dat=((dec/10)<<4|(dec%10));
        return dat;
    }
    /********************************************************************
    * 名称 : Write_DS1302Init()
    * 功能 : 往DS1302中写入数据。最开始显示的数据就是在这里设置的。
    * 输入 : 无
    * 输出 : 无
    ***********************************************************************/
    void Write_DS1302Init(void)
    {
        v_W1302(0x8e,0);
        v_W1302(0x80,0x00);    //写入秒
        v_W1302(0x8e,0);
        v_W1302(0x82,0x00);    //写入分
        v_W1302(0x8e,0);
        v_W1302(0x84,0x00);    //写入小时
        v_W1302(0x8e,0);
        v_W1302(0x86,0x00);    //写入日
        v_W1302(0x8e,0);
        v_W1302(0x88,0x00);    //写入月
        v_W1302(0x8e,0);
        v_W1302(0x8a,0x00);    //写入星期
        v_W1302(0x8e,0);
        v_W1302(0x8c,0x00);    //写入年
        v_W1302(0x90,0xa6);//单二极管,2K电阻充电    
    }

    /********************************************************************
    * 名称 : Run_DS1302(void)
    * 功能 : 读出DS1302中的数据,并在液晶1602上进行显示
    * 输入 : 无
    * 输出 : 无
    ***********************************************************************/
    void Run_DS1302(void)
    {
        uchar sec, min, hour, day, month, year;
            v_W1302(0x8f, 0);
            sec = bcdtodec(uc_R1302(0x81));       //读出DS1302中的秒
            v_W1302(0x8f, 0);
            min = bcdtodec(uc_R1302(0x83));       //读出DS1302中的分
            v_W1302(0x8f, 0);
            hour = bcdtodec(uc_R1302(0x85));   //读出DS1302中的小时
            v_W1302(0x8f, 0);
            day = bcdtodec(uc_R1302(0x87));       //读出DS1302中的日
            v_W1302(0x8f, 0);
            month = bcdtodec(uc_R1302(0x89));  //读出DS1302中的月
            v_W1302(0x8f, 0);
            year = bcdtodec(uc_R1302(0x8d));   //读出DS1302中的年

            L1602_char(2, 6, hour / 10 % 10 + 48);  //字符ASIIC码显示,0的ASIIC=48
            L1602_char(2, 7, hour % 10 + 48);
            L1602_char(2, 8, ':');
            L1602_char(2, 9, min / 10 % 10 + 48);
            L1602_char(2, 10, min % 10 + 48);
            L1602_char(2, 11, ':');
            L1602_char(2, 12, sec / 10 % 10 + 48);
            L1602_char(2, 13, sec % 10 + 48);
            L1602_char(1, 7, year / 10 % 10 + 48);
            L1602_char(1, 8, year % 10 + 48);
            L1602_char(1, 9, 0);
            L1602_char(1, 10, month / 10 % 10 + 48);
            L1602_char(1, 11, month % 10 + 48);
            L1602_char(1, 12, 1);
            L1602_char(1, 13, day / 10 % 10 + 48);
            L1602_char(1, 14, day % 10 + 48);
            L1602_char(1, 15, 2);

    }
    void beep()
    {
      uchar i;
      for(i=0;i<100;i++)
      {
         delay(1);
         BEEP=~BEEP;
       }
       BEEP=0;
    }
    void int0() interrupt 0
    {
        timechange();
    }
    /********************************************************************
    * 名称 : Main(void)
    * 功能 : 主函数
    * 输入 : 无
    * 输出 : 无
    ***********************************************************************/
    void Main(void)
    {
        L1602_init();
        writch();
        jtod=0;
        L1602_string(1,1,"DAY 20");
        L1602_string(2,1,"TIME");
        EA=1;
        EX0=1;
        IT0=1;
        while(1)
        {
          if((t==0)&&(m==0))
          {
            Write_DS1302Init();
          }
        Run_DS1302();
        }
    }

    完整资料打包(含仿真):

    STC51单片机20-DS1302可调电子时钟1602显示proteus仿真-单片机文档类资源-CSDN下载

  • 相关阅读:
    MySQL数据库基本操作
    5款免费的项目管理软件(推荐收藏)
    树莓派开机教程
    Day43:LeedCode 1049. 最后一块石头的重量 II 494. 目标和 474.一和零
    遗传算法(GA)优化的BP神经网络预测,GA-BP回归预测,多输入单输出模型。
    基于Matlab模拟用于海况海洋学研究的 X 波段雷达系统(附源码)
    Kibana Query Language (KQL)
    Excel打开第二个文件很慢的解决方法
    element el-table 设置fixed导致行错乱问题
    启航编程之海:那些引领我探索与成长的计算机书籍
  • 原文地址:https://blog.csdn.net/fengyuzhe13/article/details/127817070