打印

DS1302做时钟,怎么在调节按键的时候让其闪烁,闹钟怎么写

[复制链接]
6467|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
2583963198|  楼主 | 2012-12-24 20:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/******************************************************
           写头文件和相关参数声明
*******************************************************/
#include<reg52.h>                                //52系列单片机头文件
#include<intrins.h>
#define uchar unsigned char                //宏定义
#define uint unsigned int
sbit RST=P2^2;                                         //使能线
sbit IO=P2^1;                                         //数据线
sbit CLK=P2^0;                                        //时钟线
sbit Beep=P3^5;                        //设置蜂鸣器端口       
sbit s1=P2^4;                        //设定键          
sbit s2=P2^5;                        //增加键
sbit s3=P2^6;                        //减少键
sbit s4=P2^7;                        //设定闹钟键
uchar code duan[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};         //数码管段选
uchar code wei[]={
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};         //数码管位选
char hour_h,hour_l,min_h,min_l,sec_h,sec_l;         //分别表示高位和低位
uchar sec=0x00,min=0x00,hour=0x18;          //数码管上初始化的显示数字
uchar s1num;       //加减标志位
uchar Dis_Str[8];  //数码管段选显示位
uchar min2,hour2,min2_h,min2_l,hour2_h,hour2_l,sec2,sec2_h,sec2_l;    //写闹钟的时分秒
uchar flag;
/****************************************************
          写控制1302的地址和数据的函数
******************************************************/
//============1302读数据=============================//
uchar Read_DS1302(uchar address)        //读1302的一个字节数据
{                                                                                       
        uchar i,temp;
        RST=0;                                 //给使能低电平
        IO=1;                                 //数据线拉高
        CLK=0;                                 //时钟线拉低
        RST=1;                                 //使能高电平

        for (i=0;i<8;i++)             //循环8次 写入地址数据
        {
                   CLK=0;                                 //给时钟一个高脉冲
                IO=address&0x01;             //每次传输低字节
             address>>=1;                  //右移一位,移动8次就正好把address的一个字节送入了IO
             CLK=1;                               
        }                                                                                  
        if(IO)                                        //如果IO口的第1位为低即读状态
                temp|=0x80;                        //那么每次传输低字节,保留最高位
        CLK=0;
        temp>>=1;
        for (i=0;i<7;i++)                 //循环8次 读取数据
        {
                CLK=0;
                if(IO)
                        temp|=0x80;                        //每次传输低字节
                CLK=1;
                temp>>=1;                        //右移一位
        }

        CLK=1;
        RST=0;
        IO=0;
        return(temp);                       
}

//==========DS1302写一个字节的地址,写一个字节的数据======//
void  Write_DS1302(uchar address,uchar dat)          //送入地址和数据
{
       
    uchar i;
           RST=0;
        CLK=0;
        RST=1;       

        for (i=0;i<8;i++)             //循环8次 写入地址数据
        {
                   CLK=0;
        _nop_();                   //延时一个机器周期,写nop时一定要在头文件声明intrins.h
                IO=address&0x01;             //每次传输低字节
             address>>=1;                  //每一次右移一位,将一个字节的数据保留在IO里
             CLK=1;
        _nop_();
        }
        for (i=0;i<8;i++)             //循环8次 写入数据
        {
                   CLK=0;
        _nop_();
                IO=dat&0x01;             //每次传输低字节
             dat>>=1;                  //右移一位
                CLK=1;
        _nop_();
        }
        RST=0;
        _nop_();
}

//=============写DS1302的初始化==============//
void DS1302_initW()                               
{
        Write_DS1302(0x8e,0x00);                //写保护关
        Write_DS1302(0x90,0xaa);                   //充电寄存器命令
        Write_DS1302(0x80,sec);                        //秒
        Write_DS1302(0x82,min);                        //分
        Write_DS1302(0x84,hour);                //时
/*        Write_DS1302(0x86,date);                //日
        Write_DS1302(0x88,month);                //月
        Write_DS1302(0x8a,day);                   //周
        Write_DS1302(0x8c,year);                //年           */
        Write_DS1302(0x8e,0x80);                //写保护开
}

//==========读取DS1302中的数据================//
void DS1302_initR()
{
        sec=Read_DS1302(0x81);                        //读秒数据
        min=Read_DS1302(0x83);                        //读分钟数据
        hour=Read_DS1302(0x85);                        //读小时数据
/*        day=Read_DS1302(0x8b);                        //读星期数据
        date=Read_DS1302(0x87);                        //读日数据
        month=Read_DS1302(0x89);                //读月数据
        year=Read_DS1302(0x8d);                        //读年数据 */
}
//==========延时程序=================//
void delay1ms(uint ms)                        //延时1MS子函数
{
        uint i,j;
        for(i=ms;i>0;i--)
                for(j=110;j>0;j--);
}


/******************************************
           数码管相关函数部分
*******************************************/
//==================LED数码管扫描==========//
void LED_saomiao()                                 //LED数码管扫描
{
        uchar i;
        for(i=0;i<8;i++)
        {
                P0=Dis_Str[i];      //数码管显示段选
                P1=wei[i];                        //数码管显示位选
                delay1ms(1);
        }       
}

//==============LED数码管显示=============//
void LED_Dis()                         //LED数码管显示
{
        LED_saomiao();
        DS1302_initR();                  //读取DS1302中的数据
        sec_l=sec%16;                  //将十进制转换成BCD码
        sec_h=sec/16;
        Dis_Str[6]=duan[sec_h];         //第7个数码管显示秒的高位(利用LED扫描的形式将段码的数据依次写入数码管中显示)
        Dis_Str[7]=duan[sec_l];         //第8个数码管显示秒的低位
       
        min_l=min%16;
        min_h=min/16;
        Dis_Str[3]=duan[min_h];         //第4个数码管显示分的高位
        Dis_Str[4]=duan[min_l];         //第5个数码管显示分的低位
        Dis_Str[5]=duan[10];                 //第6个数码管显示“-”
       
        hour_l=hour%16;
        hour_h=hour/16;
        Dis_Str[0]=duan[hour_h]; //第1个数码管显示时的高位
        Dis_Str[1]=duan[hour_l]; //第2个数码管显示时的低位
        Dis_Str[2]=duan[10];                 //第3个数码管显示“-”
}



/************************************************
               按键检测函数
*************************************************/
void keyscan()                                                          
{
        if(s1==0)
        {
                delay1ms(10);
                if(s1==0)
                {
                        s1num++;
                        while(!s1);
                        if(s1num==4)
                        {
                                s1num=0;       
                        }
                }
        }
        if(s1num!=0)
        {

                        if(s2==0)
                        {
                                if(flag==1)
                                {
                                        switch(s1num)
                                        {
                                                case 1:                                  
                                            sec_h=sec/16;          //把时间数据转换成压缩的BCD码
                                                        sec_l=sec%16;  
                        //也可以这样写        sec_l=sec&0x0f;          //保留低4位数据赋给sec的低位
                        //                     sec_h=sec>>4;          //右移4位保留高4位数据给sec的高位
                                                        sec_l++;
                                                        if(sec_l==10)          //如果低位秒等于10
                                                        {       
                                                                sec_l=0;          //低位秒清0
                                                                sec_h++;
                                                        }
                                                        if(sec_h==6)          //如果把高位秒等于6
                                                                sec_h=0;          //高位秒清0
                                                        sec=sec_h*16+sec_l;        //把BCD码转换成十进制码
                                                    DS1302_initW();          //将改变后的值写入1302
                                                        break;                          //然后在LED_Dis()中第一条DS1302_initR()中读出来显示在数码管上。
                                 
                                         case 2:        min_h=min/16;
                                                                 min_l=min%16;
                                                                min_l++;
                                                                if(min_l==10)
                                                                {
                                                                        min_l=0;
                                                                        min_h++;
                                                                }
                                                                if(min_h==6)
                                                                        min_h=0;
                                                                min=min_h*16+min_l;
                                                                DS1302_initW();
                                                                break;
                                       
                                          case 3:          hour_h=hour/16;           //写小时增加
                                                                hour_l=hour%16;                                               
                                                                hour_l++;
                                                                if(hour_l==10)
                                                                {
                                                                        hour_l=0;
                                                                        hour_h++;
                                                                }
                                                                if((hour_h==2)&&(hour_l>3))        //如果小时高位等于2
                                                                {                                                        //并且小时的低位大于3
                                                                        hour_h=0;                                //那么同时清0
                                                                        hour_l=0;
                                                                }
                                                                hour=hour_h*16+hour_l;
                                                                DS1302_initW();
                                                                break;                               
                                   }
                  }
                /*  else
                   {
                           flag==1;
                        Dis_Str[6]=duan[0];
                        Dis_Str[7]=duan[0];
                        Dis_Str[3]=duan[0];
                        Dis_Str[4]=duan[0];
                        Dis_Str[1]=duan[0];
                        Dis_Str[0]=duan[0];
                        Dis_Str[2]=Dis_Str[5]=duan[10];
                        DS1302_initW();
           }  */
           }
        }
        if(s1num!=0)
        {
                if(s3==0)                        //如果s3被按下               
                {
                        delay1ms(10);   //去抖动
                        if(s3==0)           //确定s3被按下
                        {
                                while(!s3);          //松手检测
                                switch(s1num)
                                {
                                        case 1:                sec_h=sec/16;          //写秒钟减少
                                                                sec_l=sec%16;
                                                                sec_l--;
                                                                if(sec_l==-1)
                                                                {       
                                                                        sec_l=9;
                                                                        sec_h--;
                                                                }
                                                                if(sec_h==-1)
                                                                        sec_h=5;
                                                                sec=sec_h*16+sec_l;
                                                                DS1302_initW();
                                                                break;

                                        case 2:                min_h=min/16;          //写分钟减少
                                                                min_l=min%16;
                                                                min_l--;
                                                                if(min_l==-1)
                                                                {       
                                                                        min_l=9;
                                                                        min_h--;
                                                                }
                                                                if(min_h==-1)
                                                                        min_h=5;
                                                                min=min_h*16+min_l;
                                                                DS1302_initW();
                                                                break;
                                                               
                                        case 3:                hour_h=hour/16;                 //写小时减少
                                                                hour_l=hour%16;
                                                                hour_l--;
                                                                if(hour_l==-1)
                                                                {       
                                                                        hour_l=9;
                                                                        hour_h--;
                                                                }
                                                                if(hour_h==-1)
                                                                {       
                                                                        hour_h=2;
                                                                        hour_l=3;
                                                                }
                                                                hour=hour_h*16+hour_l;
                                                                DS1302_initW();
                                                                break;
                                 }
                         }
                 }
         }
/*         if(s4==0)
         {
                 delay1ms(10);
                if(s4==0)
                {
                        clock_flag++;
                        while(!s4);
                        if(clock_flag==3)
                        {
                                clock_flag=0;
                        }       
                }
         }
         if(clock_flag==1)
         {
                 if(s2==0)
                {
                        delay1ms(10);
                        if(s2==0)
                        {
                                while(!s2);       
                        }
                        switch(clock_flag)
                        {
                                case 1:               
                        }                                                         
                }
         } */
}
//=========================主函数=========================//
void main()
{                                              
        DS1302_initW();           //写DS1302初始化部分                         
        DS1302_initR();           //DS1302读数据部分
        delay1ms(5);                       
        while(1)
        {
                LED_Dis();          //LED数码管显示
                keyscan();          //按键检测部分
        }                                                                 
}


相关帖子

沙发
jy01758633| | 2013-1-3 14:35 | 只看该作者
赞啊,正在学这个,真羡慕你能做出来

使用特权

评论回复
板凳
jerry_ls| | 2013-1-31 08:56 | 只看该作者
不错,正想做个这样的电子时钟

使用特权

评论回复
地板
善解人意| | 2013-2-1 15:19 | 只看该作者
这个有不难,我用的是数码管做的放在家里还有点用处,可以加上温度和闹钟会更好.

使用特权

评论回复
5
chenyu988| | 2013-2-1 16:04 | 只看该作者
送数据;
延时;
送0x00或者0xff;
延时;
送数据;
...
这样吗

使用特权

评论回复
6
原野风霜| | 2015-6-4 14:25 | 只看该作者
设置位闪烁-----体现在哪块程序了?

使用特权

评论回复
7
liulx14| | 2015-6-4 17:16 | 只看该作者
DS1302是做时钟的,可以选带RTC的单片机,这样更节约成本。

使用特权

评论回复
8
yhy630| | 2015-6-9 20:03 | 只看该作者
在这个函数中改:void LED_Dis()                         //LED数码管显示
改的方法:
void LEDDis()
{
     ''''
   if(flag==1&flash_flag==1)
   {  //灭灯信号
         Dis_Str[0]=0xff;
        Dis_Str[1]=0xff;
    ....
  }
  else
  {
     //正常关显示数据
  }
}
//说明:flash_flag为启动闪烁志位,在按键中设置
//flag为1时灭,为0正常显示 ,这个值的改变可以放到定时器去做.
//我看你的程序没用到定时器,不太好,建议好好使用定时器,可以提高程序运行效率.
//程序中不要用太多的延时,除非时序要求非常严格.

使用特权

评论回复
9
sunbajie123| | 2016-7-1 14:05 | 只看该作者
代码不能复制嘛

使用特权

评论回复
10
coody| | 2016-7-1 15:07 | 只看该作者
闪烁,就是显示一会消隐一会

使用特权

评论回复
11
sunbajie123| | 2016-7-1 20:01 | 只看该作者
请问各位大神这是一个显示时钟并和闹钟的完整代码吗,为什么我照代码弄得单片机一点反应没有

使用特权

评论回复
12
wlc824136| | 2016-7-5 11:30 | 只看该作者
弄个定时器定时扫描数码管,然后再数码管那里弄个分支语句第一次显示数据,第二次关闭显示,这样应该就可以了

使用特权

评论回复
13
NE5532| | 2016-7-5 16:03 | 只看该作者
闪烁是显示的事情,与RTC芯片无关,楼主需要把程序模块分开来考虑。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝