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

#include<reg52.h>
#include<intrins.h>
#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下载

  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fengyuzhe13

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值