找回密码
 立即注册

QQ登录

只需一步,快速开始

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

时钟程序

[复制链接]
跳转到指定楼层
楼主
ID:282022 发表于 2018-2-3 20:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*********************************************************************************
描述:
1、8位共阴数码管显示实时时钟88-88-88样式,两‘-’1秒闪烁1次
2、STC89C52 @ 11.0592MHz晶振,两片74HC573做段选、位选
3、调时的时候,key2键短按加1,长按连加;key3键短按减一,长按连减;按键消抖不用delay。
4、在调时状态超过3秒再没有按键按下,回到走时状态
5、加备用电池,掉电走时        ,仿真 实物都通过。
**********************************************************************************/
#include<reg52.h>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int

/***********写时分秒地址************/
#define write_shi  0x84
#define write_fen  0x82
#define write_miao 0x80
#define write_ram  0xc0
/***********读时分秒地址************/
#define read_shi  0x85
#define read_fen  0x83
#define read_miao 0x81
#define read_ram  0xc1

sbit sclk = P1^0;           //控制数据时钟
sbit dio = P1^1;           //数据口
sbit ce = P1^2;                   //使能端、复位端
sbit wela = P2^7;           //位选
sbit dula = P2^6;           //段选

sbit key1=P3^0;                        //按键 选择
sbit key2=P3^1;                        //按键 加
sbit key3=P3^2;                        //按键 减

uint ms;                                //调时自动走时计时变量
uchar knum=0,snum,fnum,ss;        //定义 key1按下次数变量,时分调时闪烁变量,两‘-’闪烁计时变量
char shi,fen,miao;                //定义时分秒变量

bit f1,f2,f3;                        //定义自动走时标志
                                  // 0     1    2    3    4     5    6    7    8   9        不显  -
uchar code d[]={ 0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40}; //共阴不带小数点段码

void delay(uint z)          //ms延时函数
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=120;y>0;y--);
}

void t0_init()  //定时器初始化函数
{

        TMOD |= 0X11;                         //定时器0、1都为模式1, 16位计数模式
        TH0=(65536-46080)/256;   //50ms初值  @11.0529MHz
        TL0=(65536-46080)%256;
        TH1=(65536-921)/256;         //1ms初值  @11.0529MHz
        TL1=(65536-921)%256;

        EA=1;                                         //开总中断
        ET0=1;                                         //开定时器T0中断
        TR0=1;                                         //启动T0
        ET1=1;                                         //开定时器T1中断
//  TR1=1;

}


void display(uchar shi,uchar fen,uchar miao) //显示函数
{
        if(knum==0)           //正常走时
        {
                snum=30;
                fnum=30;
        }

        if(knum==1)           //调时,分位闪烁
        {
                fnum++;
                snum=30;
        }

        if(knum==2)          //调时,时位闪烁
        {
                snum++;
                fnum=30;
        }


        if(snum>=30)
        {        
                if((shi/10)<1)         //如果小时十位小于1,
                {
                        wela=1;
                        P0=0xfe;                //第1位
                        wela=0;

                        dula = 1;
                        P0=d[10];           //共阴数码管段码送全0 小时十位就不显示
                        dula = 0;
                }

                else
                {
                        wela=1;
                        P0=0xfe;          //第1位
                        wela=0;

                        dula=1;
                        P0=d[shi/10];
                        dula=0;
                        P0=0xff;
                        delay(2);
                }

                wela=1;
                P0=0xfd;           //第2位
                wela=0;

                dula=1;
                P0=d[shi%10];                        
                dula=0;                                       
                P0=0xff;
                delay(2);

                if(snum==60)
                        snum=0;
        }               


        //        if(miao%2==0)         //if(miao%2==0) 1秒闪烁1次
        if(ss>=10)                 //        这里写为ss>=10,闪烁频率可调
        {                                 
            wela=1;
                P0=0xfb;                //第3位
                wela=0;

                dula=1;
                P0=d[11];          //第三位数码管显示“— ”
                dula=0;
                P0=0xff;
                delay(2);
        }

        else
        {
                wela=1;
                P0=0xfb;     //第3位
                wela=0;

                dula=1;
                P0=d[10];         //第三位数码管不显示
                dula=0;
                P0=0xff;
                delay(2);        
        }


        if(fnum>=30)
        {
                wela=1;
                P0=0xf7;         //第4位
                wela=0;

                dula=1;
                P0=d[fen/10];
                dula=0;
                P0=0xff;
                delay(2);


                wela=1;
                P0=0xef;         //第5位
                wela=0;

                dula=1;
                P0=d[fen%10];
                dula=0;
                P0=0xff;
                delay(2);


                if(fnum==60)
                        fnum=0;
        }

        //        if(miao%2==0)         //if(miao%2==0) 1秒闪烁1次
        if(ss>=10)                 //if(ss>=10)闪烁频率可调
        {
                wela=1;
                P0=0xdf;          //第6位
                wela=0;
                dula=1;
                P0=d[11];          //第六位数码管显示“— ”
                dula=0;
                P0=0xff;
                delay(2);
        }

        else
        {
                wela=1;
                P0=0xdf;                   //第6位
                wela=0;
                dula=1;
                P0=d[10];                  //第六位数码管不显示
                dula=0;
                P0=0xff;
                delay(2);
        }


        wela=1;
        P0=0xbf;                        //第7位
        wela=0;

        dula=1;
        P0=d[miao/10];                //秒十位
        dula=0;
        P0=0xff;
        delay(2);


        wela=1;
        P0=0x7f;                         //第8位
        wela=0;

        dula=1;
        P0=d[miao%10];                //秒个位
        dula=0;
        P0=0xff;
        delay(2);               
}  

void write_1302(uchar add,dat)//写1302函数  
{
        uchar i,temp;
        temp=add;
        ce=0;
        _nop_();
        sclk=0;
        _nop_();
        ce=1;
        _nop_();
        for(i=0;i<8;i++)
        {
                sclk=0;
                _nop_();
                if((temp&0x01)==0x01)
                        dio=1;
                        else
                        dio=0;
                temp>>=1;
                sclk=1;
                _nop_();
        }
        temp=dat;
        for(i=0;i<8;i++)
        {
                sclk=0;
                _nop_();
                if((temp&0x01)==0x01)
                        dio=1;
                        else
                        dio=0;
                temp>>=1;
                sclk=1;
                _nop_();
        }
        ce=0;
        sclk=0;
}

uchar read_1302(uchar add)        //读1302函数
{
        uchar dat,dat1,i,temp;
        temp=add;
        ce=0;
        _nop_();
        sclk=0;
        _nop_();
        ce=1;
        for(i=0;i<8;i++)
        {
                sclk=0;
                _nop_();
                if((temp&0x01)==0x01)
                        dio=1;
                        else
                        dio=0;
                temp>>=1;
                sclk=1;
                _nop_();
        }
        for(i=0;i<8;i++)
        {
                sclk=0;
                _nop_();
                if(dio)
                    dat|=0x80;
                if(i<7)
                        dat>>=1;
                sclk=1;
        }
        dat1=dat/16;
        dat=dat%16;
        dat=dat1*10+dat;  
        ce=0;
        sclk=0;
        return dat;
}                        


void init_1302()                                                        //自动初始化函数
{        
        if(read_1302(read_ram) != 0xaa)                        //如果初始化标志RAM的值不是0xaa,才初始化
        {
                write_1302(0x8e,0x00);                                //保护取消,可以进行写操作
                write_1302(write_miao,0x57);                //写秒57
                write_1302(write_fen,0x55);                        //写分55
                write_1302(write_shi,0x15);                        //写时15
                write_1302(write_ram,0xaa);                        //写入初始化标志RAM(第00个RAM位置)
                write_1302(0x8e,0x80);                                //保护启动,不能进行写操作
        }
}         

void read_sf()        //读时分秒并显示
{
        shi=read_1302(read_shi);
        fen=read_1302(read_fen);
        miao=read_1302(read_miao);
        display(shi,fen,miao);
}


void keyscan()                        //按键扫描函数
{        
        static uchar count;          //这里要定义为静态变量

        if(key1==0)                          //按键按下
        {        
                TR1=1;
                count++;                          //消抖,也是连加一次的间隔时间
                f1=1;
                if(key1==0 && count>10)//按键按下,计数变量加到12,
                {
                        ms=0;                           //自启动计时变量清零
                        while(!key1)           //这里不需要连加,就加一句松手检测
                        display(shi,fen,miao);
                        count=0;
                        TR0=0;                           //关闭T0定时器,数码管两‘-’停止闪烁
                        knum++;                           
                        if(knum==1)                                                  
                        {
                                 write_1302(0x8e,0x00);                  //DS1302写保护取消
                                 write_1302(write_miao,0x80); //写秒80,时钟停止走时;
                        }

                        if(knum==3)                                                   //调时完毕,时钟启动
                        {
                                TR0=1;                                                //启动T0定时器,数码管两‘-’开始闪烁
                                knum=0;
                                write_1302(write_miao,0x00); //写秒0,时钟启动走时
                                write_1302(0x8e,0x80);                 //保护启动
                        }
                }
        }


        if(knum==1)                                                                //分钟调节
        {
                if(key2==0)                                                        //加
                {
                        f2=1;
                        count++;
                        if(key2==0 && count>12)//短按加1,长按连加
                        {
                                ms=0;                           //自启动计时变量清零
                                count=0;
                                fen++;
                                fen=fen/10*16+fen%10;                //转为16进制
                                if(fen==0x60)
                                        fen=0x00;
                                write_1302(write_fen,fen);        //写入1302
                        }
                }

                if(key3==0)                                                   //减
                {
                        f3=1;
                        count++;
                        if(key3==0 && count>12)//短按减1,长按连减
                        {
                                ms=0;                           //自启动计时变量清零
                                count=0;
                                fen--;
                                fen=fen/10*16+fen%10;                //转为16进制
                                if(fen==-1)
                                        fen=0x59;
                                write_1302(write_fen,fen);
                        }
                }
        }


        if(knum==2)                                                          //小时调节
        {
                if(key2==0)
                {        
                        f2=1;
                        count++;
                        if(key2==0 && count>12 )//短按加1,长按连加
                        {
                                ms=0;                                //自启动计时变量清零
                                count=0;
                                shi++;
                                shi=shi/10*16+shi%10;//转为16进制
                                if(shi==0x24)
                                        shi=0x00;
                                write_1302(write_shi,shi);
                        }
                }


                if(key3==0)
                {
                        f3=1;
                        count++;
                        if(key3==0 && count>12 )//短按减1,长按连减
                        {        
                                ms=0;                                //自启动计时变量清零
                                count=0;
                                shi--;
                                shi=shi/10*16+shi%10;//转为16进制
                                if(shi==-1)
                                        shi=0x23;
                                write_1302(write_shi,shi);
                        }
                }
        }

        /*按键超过3秒没有动作,时钟回到走时状态*/

        if(f1==1 || f2==1 || f3==1)
        {
                if(ms>3000)          //时间超过3秒
                {
                        TR1=0;          //关闭T1
                        ms=0;          //自启动计时变量清零
                        knum=0;          //key1按键次数清零
                        TR0=1;          //启动T0,数码管两‘-’开始闪烁
                        write_1302(write_miao,0x00); //写秒0,时钟启动走时
                        write_1302(0x8e,0x80);                 //保护启动
                }

        }
}           

/*主函数*/
void main()
{//        uchar i;
        t0_init();
        init_1302();                          
        while(1)
        {
           //        for(i=0;i<4;i++)        
        //        display(shi,fen,miao);
            read_sf();
            keyscan();
        }
}

/*中断函数*/
void temer1() interrupt 1
{
        TH0=(65536-46080)/256;
        TL0=(65536-46080)%256;
        ss++;
        if(ss==20)
                ss=0;
}         

void temer2() interrupt 3
{
        TH1=(65536-921)/256;
        TL1=(65536-921)%256;
        ms++;
}




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

使用道具 举报

沙发
ID:508869 发表于 2019-4-18 09:21 来自手机 | 只看该作者
时钟芯片的函数可以直接拿来用吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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