基于51单片机+DS1302+ LCD1602显示时间Proteus仿真

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于51单片机+DS1302+ LCD1602显示时间Proteus仿真相关的知识,希望对你有一定的参考价值。

基于51单片机+DS1302+ LCD1602显示时间Proteus仿真


  • AT89C52LCD1602DS1302
  • Proteus仿真器件

实例代码

#include <reg51.h>
#include <string.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP() {_nop_();_nop_();_nop_();_nop_();}
sbit SDA=P2^6;  // DS1302数据线
sbit CLK=P2^5;  //         DS1302时钟线
sbit RST=P2^4;  // DS1302复位线
//DS18B20数据端口定义
sbit DQ=P2^4;    //DS18B20数据端口
sbit LCD_RS=P2^0;   // LCD寄存器选择
sbit LCD_RW=P2^1;   //         LCD读写/写控制
sbit LCD_EN=P2^2;   //  LCD启用

uchar tCount=0;
//一年中每个月的天数,2月的天数由年份决定
uchar MonthsDays[]= {0,31,0,31,30,31,30,31,31,30,31,30,31};
//周日,每周一到周六(0,1-6)【读取DS1302时分别是1-7】
uchar *WEEK[]= {"SUN","MON","TUS","WEN","THU","FRI","SAT"};

//LCD显示缓冲
uchar LCD_DSY_BUFFER1[]= {"00-00-00        "};
uchar LCD_DSY_BUFFER2[]= {"00-00-00      "};
uchar DateTime[7];  //所读取的日期时间
uchar Adjust_flag=0; //当前调节的时间对像:秒,分,时,日,月,年(1,2,3,4,5,6)
uchar Change_Flag[]=" YMDHM";//(分,时,日,月,年)(不调节秒与周)


void DelayMS(uchar x)//延时
{   uchar i;
    while(x--)
        for(i=0; i<120; i++);
}


void Write_A_Byte_TO_DS1302(uchar x)//向DS1302写入一个字节
{   uchar i;
    for(i=0; i<8; i++)
    {   SDA=x&1;
        CLK=1;
        CLK=0;
        x>>=1;
    }
}


uchar Get_A_Byte_FROM_DS1302()//读取一个字节
{   uchar i,b,t;
    for(i=0; i<8; i++)
    {   b>>=1;
        t=SDA;
        b|=t<<7;
        CLK=1;
        CLK=0;
    }

    return b/16*10+b%16;//BCD码转换
}

uchar Read_Data(uchar addr)//指定位置读数据
{   uchar dat;
    RST=0;
    CLK=0;
    RST=1;
    Write_A_Byte_TO_DS1302(addr);
    dat=Get_A_Byte_FROM_DS1302();
    CLK=1;
    RST=0;
    return dat;
}

void Write_DS1302(uchar addr,uchar dat)//向某地址写入数据
{   CLK=0;
    RST=1;
    Write_A_Byte_TO_DS1302(addr);
    Write_A_Byte_TO_DS1302(dat);
    CLK=0;
    RST=0;
}

void SET_DS1302()//设置时间
{   uchar i;
    Write_DS1302(0x8e,0x00);

    for(i=0; i<7; i++)
    {

        Write_DS1302(0X80+2*i,(DateTime[i]/10<<4)|(DateTime[i]%10));//日,月,周,年,写入 地址每次增2
    }
    Write_DS1302(0x8e,0x80);//加保护
}


void GetTime()//读取本地的时间
{
    uchar i;
    for(i=0; i<7; i++)
    {
        DateTime[i]=Read_Data(0x81+2*i);
    }
}

//LCD驱动代码
bit LCD_Busy_Check()//LCD忙
{   bit result;
    LCD_RS=0;
    LCD_RW=1;
    LCD_EN=1;
    delayNOP();
    result=(bit)(P0&0x80);
    LCD_EN=0;
    return result;
}


void Write_LCD_Command(uchar cmd) //写指令
{   while(LCD_Busy_Check());
    LCD_RS=0;
    LCD_RW=0;
    LCD_EN=0;
    _nop_();
    _nop_();
    P0=cmd;
    delayNOP();
    LCD_EN=1;
    delayNOP();
    LCD_EN=0;
}

void Write_LCD_Data(uchar dat)//写数据
{   while(LCD_Busy_Check());
    LCD_RS=1;
    LCD_RW=0;
    LCD_EN=0;
    P0=dat;
    delayNOP();
    LCD_EN=1;
    delayNOP();
    LCD_EN=0;
}


void Init_LCD()//LCD初始化
{   Write_LCD_Command(0x01);
    DelayMS(5);
    Write_LCD_Command(0x38);
    DelayMS(5);
    Write_LCD_Command(0x0c);
    DelayMS(5);
    Write_LCD_Command(0x06);
    DelayMS(5);
}

void Set_LCD_POS(uchar pos)//设置显示位置
{   Write_LCD_Command(pos|0x80);
}


void Display_LCD_String(uchar p,uchar *s)//在LCD上显示字符串
{   uchar i;
    Set_LCD_POS(p);
    for(i=0; i<16; i++)
    {   Write_LCD_Data(s[i]);
        DelayMS(1);
    }
}


void Format_DateTime(uchar d,uchar *a)//日期与时间值转换为数字字符
{   a[0]=d/10+'0';
    a[1]=d%10+'0';
}


uchar isLeapYear(uint y)//判断是否为闰年
{   return (y%4==0&&y%100!=0)||(y%400==0);
}


void RefreshWeekDay()
{   uint i,d,w=5; //
    for(i=2021; i<2021+DateTime[6]; i++)
    {   d=isLeapYear(i)?366:365;
        w=(w+d)%7;
    }
    d=0;
    for(i=1; i<DateTime[4]; i++)
        d+=MonthsDays[i];
    d+=DateTime[3];
    DateTime[5]=(w+d)%7+1;
}


//定时器0每秒刷新LCD显示
void T0_INT() interrupt 1
{   uchar i;
    if(++tCount!=2) return;
    tCount=0;//刷新

    Format_DateTime(DateTime[6],LCD_DSY_BUFFER1);//年
    Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+3);//月
    Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+6);//日

    Format_DateTime(DateTime[2],LCD_DSY_BUFFER2);//时
    Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+3);//分
    Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+6);//秒

    Display_LCD_String(0x03,LCD_DSY_BUFFER1);//显示年月日,星期,时分秒
    Set_LCD_POS(0x43);
    for(i=0; i<14; i++)
    {
        Write_LCD_Data(LCD_DSY_BUFFER2[i]);
        DelayMS(1);
    }
}

//主程序
void main()
{
    Init_LCD();//液晶初始化
    IE=0X87;//允许INT0,T0中断
    TR0=1;
    while(1)
    {   GetTime();

    }
}

以上是关于基于51单片机+DS1302+ LCD1602显示时间Proteus仿真的主要内容,如果未能解决你的问题,请参考以下文章

基于51单片机+DS1302时钟模块+LCD1602显示

基于51单片机+DS1302时钟模块+LCD1602显示

51单片机 LCD1602+DS1302实时时钟+Proteus仿真

基于51单片机+DS1302万年历+LCD1602显示+按键播报时间+温控风扇+按键控灯

基于51单片机+DS1302万年历+LCD1602显示+按键播报时间+温控风扇+按键控灯

Proteus仿真51单片机+DS1302+lcd1602显示