LCD1602液晶显示屏的入门级应用(二)——万年历

这里用到的时钟是DS1302,先给大家介绍一下DS1302。下图分别是典型电路图和寄存器,这个程序要分三个.C文件,分别是ds1302.c,lcd.c,main.c。

)ds1302.c,这部分函数一般都是固定的,可以直接拿去用,分读命令、写命令、初始化、读时钟信息四个函数。

#include"ds1302.h"

//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

//---这里是根据上边的蓝色表格算出来的-------//

//---DS1302时钟初始化2013年1月1日星期二12点00分00秒,可以自行修改---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};

/*******************************************************************************
* 函 数 名       : Ds1302Write
* 函数功能     : 向DS1302命令(地址+数据)
* 输    入         : addr,dat
* 输    出         : 无
*******************************************************************************/

void Ds1302Write(uchar addr, uchar dat)
{
    uchar n;
    RST = 0;
    _nop_();

    SCLK = 0;//先将SCLK置低电平。
    _nop_();
    RST = 1; //然后将RST(CE)置高电平。
    _nop_();

    for (n=0; n<8; n++)//开始传送八位地址命令
    {
        DSIO = addr & 0x01;//数据从低位开始传送
        addr >>= 1;
        SCLK = 1;//数据在上升沿时,DS1302读取数据
        _nop_();
        SCLK = 0;
        _nop_();
    }
    for (n=0; n<8; n++)//写入8位数据
    {
        DSIO = dat & 0x01;
        dat >>= 1;
        SCLK = 1;//数据在上升沿时,DS1302读取数据
        _nop_();
        SCLK = 0;
        _nop_();    
    }    
         
    RST = 0;//传送数据结束
    _nop_();
}

/*******************************************************************************
* 函 数 名         : Ds1302Read
* 函数功能           : 读取一个地址的数据
* 输    入         : addr
* 输    出         : dat
*******************************************************************************/

uchar Ds1302Read(uchar addr)
{
    uchar n,dat,dat1;
    RST = 0;
    _nop_();

    SCLK = 0;//先将SCLK置低电平。
    _nop_();
    RST = 1;//然后将RST(CE)置高电平。
    _nop_();

    for(n=0; n<8; n++)//开始传送八位地址命令
    {
        DSIO = addr & 0x01;//数据从低位开始传送
        addr >>= 1;
        SCLK = 1;//数据在上升沿时,DS1302读取数据
        _nop_();
        SCLK = 0;//DS1302下降沿时,放置数据
        _nop_();
    }
    _nop_();
    for(n=0; n<8; n++)//读取8位数据
    {
        dat1 = DSIO;//从最低位开始接收
        dat = (dat>>1) | (dat1<<7);
        SCLK = 1;
        _nop_();
        SCLK = 0;//DS1302下降沿时,放置数据
        _nop_();
    }

    RST = 0;
    _nop_();    //以下为DS1302复位的稳定时间,必须的。
    SCLK = 1;
    _nop_();
    DSIO = 0;
    _nop_();
    DSIO = 1;
    _nop_();
    return dat;    
}

/*******************************************************************************
* 函 数 名         : Ds1302Init
* 函数功能           : 初始化DS1302.
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void Ds1302Init()
{
    uchar n;
    Ds1302Write(0x8E,0X00);         //禁止写保护,就是关闭写保护功能
    for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
    {
        Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);    
    }
    Ds1302Write(0x8E,0x80);         //打开写保护功能
}

/*******************************************************************************
* 函 数 名         : Ds1302ReadTime
* 函数功能           : 读取时钟信息
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void Ds1302ReadTime()
{
    uchar n;
    for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
    {
        TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
    }
        
}

)lcd.c,这部分函数可以参考之前的一篇博客,可以直接拿去用,分延时函数、写命令、写数据、初始化四个函数。

)main.c,这部分函数增加了调节时间的功能,按K3进入时钟设置,按K1选择设置的时分秒日月,按K2选择设置加1。

/*******************************************************************************
* 实验名             : 万年历实验
* 使用的IO         : 
* 实验效果       :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒日月,按K2选择
*选择设置加1。 
*    注意                     :
*******************************************************************************/

#include<reg51.h>
#include"lcd.h"
#include"ds1302.h"

sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3;

void Int0Configuration();
void LcdDisplay();
unsigned char SetState,SetPlace;
void Delay10ms(void);   //误差 0us
/*******************************************************************************
* 函数名         : main
* 函数功能           : 主函数
* 输入           : 无
* 输出              : 无
*******************************************************************************/

void main()
{
    unsigned char i;
    Int0Configuration();
    LcdInit();
    Ds1302Init();
    while(1)
    {    
        if(SetState==0)  //按键状态
        {
            Ds1302ReadTime();
        }
        else
        {
            if(K1==0)        //检测按键K1是否按下
            {
                Delay10ms();    //消除抖动
                if(K1==0)
                {
                    SetPlace++;  //TIME[7]一共7位,选择对哪一位进行修改设置
                    if(SetPlace>=7)
                    SetPlace=0;                    
                }

                while((i<50)&&(K1==0))     //检测按键是否松开
                {
                    Delay10ms();
                    i++;
                }
                i=0;
            }
            if(K2==0)        //检测按键K2是否按下
            {
                Delay10ms();    //消除抖动
                if(K2==0)
                {
                    TIME[SetPlace]++;
                    if((TIME[SetPlace]&0x0f)>9)                     //换成BCD码。
                    {
                        TIME[SetPlace]=TIME[SetPlace]+6;
                    }
                    if((TIME[SetPlace]>=0x60)&&(SetPlace<2))        //分秒只能到59
                    {
                        TIME[SetPlace]=0;
                    }
                    if((TIME[SetPlace]>=0x24)&&(SetPlace==2))        //小时只能到23
                    {
                        TIME[SetPlace]=0;
                    }
                    if((TIME[SetPlace]>=0x32)&&(SetPlace==3))        //日只能到31
                    {
                        TIME[SetPlace]=0;    
                    }
                    if((TIME[SetPlace]>=0x13)&&(SetPlace==4))        //月只能到12
                    {
                        TIME[SetPlace]=0;
                    }    
                    if((TIME[SetPlace]>=0x7)&&(SetPlace==5))        //周只能到7
                    {
                        TIME[SetPlace]=1;
                    }        
                }
                
                while((i<50)&&(K2==0))     //检测按键是否松开
                {
                    Delay10ms();
                    i++;
                }
                i=0;
                
            }                        
        }
        LcdDisplay();    
    }
    
}
/*******************************************************************************
* 函数名         : LcdDisplay()
* 函数功能           : 显示函数
* 输入           : 无
* 输出              : 无
*******************************************************************************/

void LcdDisplay()
{
    LcdWriteCom(0x80+0X40);
    LcdWriteData('0'+TIME[2]/16);                //时
    LcdWriteData('0'+(TIME[2]&0x0f));                 
    LcdWriteData('-');
    LcdWriteData('0'+TIME[1]/16);                //分
    LcdWriteData('0'+(TIME[1]&0x0f));    
    LcdWriteData('-');
    LcdWriteData('0'+TIME[0]/16);                //秒
    LcdWriteData('0'+(TIME[0]&0x0f));

    LcdWriteCom(0x80);
    LcdWriteData('2');
    LcdWriteData('0');
    LcdWriteData('0'+TIME[6]/16);            //年
    LcdWriteData('0'+(TIME[6]&0x0f));
    LcdWriteData('-');
    LcdWriteData('0'+TIME[4]/16);            //月
    LcdWriteData('0'+(TIME[4]&0x0f));
    LcdWriteData('-');
    LcdWriteData('0'+TIME[3]/16);            //日
    LcdWriteData('0'+(TIME[3]&0x0f));
    LcdWriteCom(0x8D);
    LcdWriteData('0'+(TIME[5]&0x07));    //星期             
}
/*******************************************************************************
* 函数名         : Int0Configuration()
* 函数功能           : 配置外部中断0
* 输入           : 无
* 输出              : 无
*******************************************************************************/

void Int0Configuration()
{
    //设置INT0
    IT0=1;//跳变沿出发方式(下降沿)
    EX0=1;//打开INT0的中断允许。
    EA=1;//打开总中断    
}
/*******************************************************************************
* 函数名         : Int0() 
* 函数功能           : 外部中断0 中断函数
* 输入           : 无
* 输出              : 无
*******************************************************************************/

void Int0() interrupt 0         
{
    Delay10ms();
    if(K3==0)
    {
        SetState=~SetState;
        SetPlace=0;
        Ds1302Init();    
    }
}
/*******************************************************************************
* 函数名         : Delay10ms
* 函数功能           : 延时函数,延时10ms
* 输入           : 无
* 输出              : 无
*******************************************************************************/
void Delay10ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}

猜你喜欢

转载自blog.csdn.net/weixin_42133183/article/details/81536624