找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6944|回复: 9
收起左侧

DS1302 8位数码管时钟,调时可以连加连减

  [复制链接]
ID:140489 发表于 2017-4-25 14:59 | 显示全部楼层 |阅读模式
附件里有完整源码和仿真图
QQ截图20170425151550.png
/*********************************************************************************
描述: 8位共阴数码管时钟,显示88-88-88样式,正常走时的时候,两个“-”0.5秒闪烁一次;
       调时:按KEY1按键第1次分钟位闪烁,再按KEY2一次分钟加1,按KEY3一次分钟减1,长按连加连减;
                         按KEY1按键第2次小时位闪烁,再按KEY2一次小时加1,按KEY3一次小时减1,长按连加连减;
                         按KEY1按键第3次,秒从零开始累加,时钟回到正常走时;
                         对时的时候先调好时、分,分钟要比参考时间的分钟加1分,
                         再看参考时间的秒数到了59再按KEY1按键的第3次,这样对时可以很准的
仿真 实物都通过.  11.0592MHz晶振,STC89C52RC,两个74HC573锁存器做位选、段选
**********************************************************************************/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int

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

sbit KEY1=P3^0;                                                                        //按键 设置/确认
sbit KEY2=P3^1;                                                                        //按键 加
sbit KEY3=P3^2;                                                                        //按键 减

uchar snum,fnum;

char shi,fen,miao;

uchar ss;

char FunctionKeyNum=0;                                //功能键键值
char FuncTempNum=0;                                        //功能键临时键值
typedef enum KeyState{StateInit,StateAffirm,StateSingle,StateRepeat};        //键值状态值


/***********写时分秒地址************/
#define write_shi  0x84
#define write_fen  0x82
#define write_miao 0x80

/***********读时分秒地址************/
#define read_shi  0x85
#define read_fen  0x83
#define read_miao 0x81

                  // 0     1    2    3    4     5    6    7    8   9
uchar d[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共阴不带小数点
//uchar dd[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};  //        共阴带小数点


void delay(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=120;y>0;y--);
}


void t0_init()  //定时50ms一个中断
{

  TMOD |= 0X01;
  TH0 = (65536-46080)/256;
  TL0 = (65536-46080)%256;
  EA = 1;
  ET0 = 1;
  TR0 = 1;

}

void t1_init()
{
        TMOD |= 0x10;
        TH1 = 0xDC;
        TL1 = 0x00;
        TR1 = 1;        
}

void temer0() interrupt 1
{
  TH0=(65536-46080)/256;
  TL0=(65536-46080)%256;
  ss++;
  if(ss==20)
  ss=0;

}         





void display(uchar shi,uchar fen,uchar miao)                          //显示函数
{
        if(FunctionKeyNum==0)
        {
                snum=30;
                fnum=30;
        }
        
        if(FunctionKeyNum==1)
        {
                fnum++;
                snum=30;
        }
        
        if(FunctionKeyNum==2)
        {
                snum++;
                fnum=30;
        }
        
        
        if(snum>=30)
        {        
                if((shi/10)<1)         //如果小时十位小于1,
                {
                wela=1;
                P0=0xfe;                //第1位
                wela=0;

                dula = 1;
                P0=0xff;           // 小时十位就不显示
                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];                        //时的个位,P0=d[shi%10]时的个位小数点闪烁
                        dula=0;                                        // 时的个位,P0=dd[shi%10]时的个位小数点不闪烁
                        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=0x40;          //第三位数码管显示“— ”
               
                dula=0;
                P0=0xff;
                delay(2);
        
                }

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

                dula=1;
                P0=0;          //第三位数码管不显示
                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=0x40;          //第六位数码管显示“— ”
                dula=0;
                P0=0xff;

                delay(2);
                }

                else
                {
                wela=1;
                P0=0xdf;   //第6位
                wela=0;
                dula=1;
                P0=0;          //第六位数码管不显示
                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()                                                        //初始化函数 设置时间
{        
        write_1302(0x8e,0x00);                                        //保护取消,可以进行写操作
        write_1302(write_miao,0x57);        
        write_1302(write_fen,0x55);
        write_1302(write_shi,0x15);
        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(void)
{
        static uchar KeyStateTemp1 = 0;                  //按键状态临时存储值1
        static uchar KeyStateTemp2 = 0;                  //按键状态临时存储值2
        static uchar KeyStateTemp3 = 0;                  //按键状态临时存储值3
        static uchar KeyTime = 0;                          //按键延时时间
        bit KeyPressTemp1;                                          //按键是否按下存储值1
        bit KeyPressTemp2;                                          //按键是否按下存储值2
        bit KeyPressTemp3;                                          //按键是否按下存储值3

        KeyPressTemp1 = KEY1;                                  //读取IO口的键值
        switch(KeyStateTemp1)
        {
                case StateInit:
                        if(!KeyPressTemp1)                                        //KEY1按下
                                KeyStateTemp1 = StateAffirm;        //按键状态切换到确认态
                break;
                case StateAffirm:                                                //确认状态
                        if(!KeyPressTemp1)                                        //按键还在按下
                        {
                                KeyTime = 0;
                                KeyStateTemp1 = StateSingle;        //按键状态切换到单击状态
                        }
                        else KeyStateTemp1 = StateInit;                //否则按键抬起,回到初始态
                break;
               
                case StateSingle:                                                //单击
                         if(KeyPressTemp1)
                         {
                                KeyStateTemp1 = StateInit;                 //按键释放
                                FuncTempNum++;                                         //键值加1
                                if(FuncTempNum>3)  FuncTempNum = 0;
                         }

                         else if(++KeyTime>100)
                         {
                                         KeyPressTemp1 = StateRepeat;
                                        KeyTime = 0;
                         }
                break;
        
                case StateRepeat:                                                 //连发
                        if(KeyPressTemp1)
                                KeyStateTemp1 = StateInit;
                        else
                        {
                                if(++KeyTime > 10)
                                {
                                        KeyTime = 0;
                                        FuncTempNum++;
                                        if(FuncTempNum>3)  FuncTempNum = 0;
                                }
                                break;
                        }
                break;
        
                default :KeyStateTemp1 = KeyStateTemp1 = StateInit; break;
                        
        }


if(FuncTempNum)                                                                //只有功能键被按下后,增加和减小键才有效
        {
                KeyPressTemp2 = KEY2;                                        //读取I/O口的键值
                switch(KeyStateTemp2)
                {        
                        case StateInit:                                                //按键初始状态
                                if(!KeyPressTemp2)                                //当按键按下,状态切换到确认态
                                        KeyStateTemp2 = StateAffirm;
                                break;
                        case StateAffirm:                                        //按键确认态
                                if(!KeyPressTemp2)
                                {
                                        KeyTime = 0;
                                        KeyStateTemp2 = StateSingle;//切换到单次触发态        
                                }
                                else KeyStateTemp2 = StateInit; //按键已抬起,切换到初始态
                                break;
                        case StateSingle:                                        //按键单发态
                                if(KeyPressTemp2)                                //按下时间小于1s
                                {
                                        KeyStateTemp2 = StateInit;  //按键释放,则回到初始态
                                        if(FunctionKeyNum == 1)                //若功能键第一次按下
                                        {
                                        fen++;
                                        fen=fen/10*16+fen%10;                //转为16进制
                                        if(fen==0x60)
                                            fen=0x00;
                                           write_1302(write_fen,fen);        //写入1302
                                        read_sf();                                        //读出时间,然后显示
                                        }
                                        if(FunctionKeyNum == 2)                //若功能键第二次按下
                                        {
                                                shi++;
                                                shi=shi/10*16+shi%10;                //转为16进制
                                                if(shi==0x24)
                                                        shi=0x00;
                                                write_1302(write_shi,shi);
                                                read_sf();

                                        }
                                        }
                                        else if(++KeyTime > 100)        //按下时间大于1s(100*10ms)
                                        {
                                                KeyStateTemp2 = StateRepeat;//状态切换到连发态
                                                KeyTime = 0;        
                                        }
                                break;
                        case StateRepeat:                                        //按键连发态               
                                if(KeyPressTemp2)
                                        KeyStateTemp2 = StateInit;        //按键释放,则进初始态
                                else                                                        //按键未释放
                                {
                                        if(++KeyTime > 10)                        //按键计时值大于100ms(10*10ms)
                                        {
                                                KeyTime = 0;        
                                                if(FunctionKeyNum == 1)        //若功能键第一次按下
                                                {
                                        fen++;
                                        fen=fen/10*16+fen%10;                //转为16进制
                                        if(fen==0x60)
                                            fen=0x00;
                                           write_1302(write_fen,fen);        //写入1302
                                        read_sf();                                        //读出时间,然后显示
                                                }
                                                
                                                if(FunctionKeyNum == 2)        //若功能键第二次按下
                                                {
                                                shi++;
                                                shi=shi/10*16+shi%10;                //转为16进制
                                                if(shi==0x24)
                                                        shi=0x00;
                                                write_1302(write_shi,shi);
                                                read_sf();
                                                }
                                        }
                                        break;
                                }
                                break;
                        default: KeyStateTemp2 = KeyStateTemp2 = StateInit; break;
                }


                KeyPressTemp3 = KEY3;                                                //读取I/O口的键值
                switch(KeyStateTemp3)
                {        
                        case StateInit:                                                        //按键初始状态
                                if(!KeyPressTemp3)                                        //当按键按下,状态切换到确认态
                                        KeyStateTemp3 = StateAffirm;
                                break;
                        case StateAffirm:                                                //按键确认态
                                if(!KeyPressTemp3)
                                {
                                        KeyTime = 0;
                                        KeyStateTemp3 = StateSingle;        //切换到单次触发态        
                                }
                                else KeyStateTemp3 = StateInit;         //按键已抬起,切换到初始态
                                break;
                        case StateSingle:                                                //按键单发态
                                if(KeyPressTemp3)                                        //按下时间小于1s
                                {
                                        KeyStateTemp3 = StateInit;          //按键释放,则回到初始态
                                        if(FunctionKeyNum == 1)                        //若功能键第一次按下
                                        {
                                                fen--;
                                                fen=fen/10*16+fen%10;                //转为16进制
                                                if(fen==-1)
                                                fen=0x59;
                                                write_1302(write_fen,fen);
                                                read_sf();
                                        }
                                        if(FunctionKeyNum == 2)                        //若功能键第二次按下
                                        {
                                                shi--;
                                                shi=shi/10*16+shi%10;                //转为16进制
                                                if(shi==-1)
                                                shi=0x23;
                                                write_1302(write_shi,shi);
                                                read_sf();
                                        }
                                }
                                else if(++KeyTime > 100)                        //按下时间大于1s(100*10ms)
                                {
                                        KeyStateTemp3 = StateRepeat;        //状态切换到连发态
                                        KeyTime = 0;        
                                }
                                break;
                        case StateRepeat:                                                //按键连发态               
                                if(KeyPressTemp3)
                                        KeyStateTemp3 = StateInit;                //按键释放,则进初始态
                                else                                                                //按键未释放
                                {
                                        if(++KeyTime > 10)                                //按键计时值大于100ms(10*10ms)
                                        {
                                                KeyTime = 0;        
                                                if(FunctionKeyNum == 1)                //若功能键第一次按下
                                                {
                                                        fen--;
                                                        fen=fen/10*16+fen%10;                //转为16进制
                                                        if(fen==-1)
                                                        fen=0x59;
                                                        write_1302(write_fen,fen);
                                                        read_sf();
                                                }
                                                if(FunctionKeyNum == 2)                //若功能键第二次按下
                                                {
                                                        shi--;
                                                        shi=shi/10*16+shi%10;                //转为16进制
                                                        if(shi==-1)
                                                        shi=0x23;
                                                        write_1302(write_shi,shi);
                                                        read_sf();
                                                }
                                        }
                                        break;
                                }
                                break;
                        default: KeyStateTemp3 = KeyStateTemp3 = StateInit; break;
                }
        }
}


void ExecuteKeyNum()
{
        if(TF1)
        {
                TF1 = 0;
                TH1 = 0xDC;
                TL1 = 0x00;
                KeyScan();
        }

以上是部分源码,完整的代码在附件里:
下载: 时钟.rar (26.29 KB, 下载次数: 185)

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:161033 发表于 2017-7-8 22:25 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:140489 发表于 2018-1-30 16:26 | 显示全部楼层
  1. /*********************************************************************************
  2. 8位数码管显示实时时钟
  3. 仿真 实物都通过.  11.0592MHz晶振,两片74HC573做段选、位选
  4. 调时的时候,key2键短按加1,长按连加;key3键短按减一,长按连减;按键消抖不用delay
  5. **********************************************************************************/
  6. #include<reg52.h>
  7. #include<intrins.h>
  8. #define uchar unsigned char
  9. #define uint unsigned int

  10. /***********写时分秒地址************/
  11. #define write_shi  0x84
  12. #define write_fen  0x82
  13. #define write_miao 0x80
  14. /***********读时分秒地址************/
  15. #define read_shi  0x85
  16. #define read_fen  0x83
  17. #define read_miao 0x81

  18. sbit sclk = P1^0;           //控制数据时钟
  19. sbit dio = P1^1;           //数据口
  20. sbit ce = P1^2;                   //使能端、复位端
  21. sbit wela = P2^7;           //位选
  22. sbit dula = P2^6;           //段选
  23. //sbit IO=P1^1;                                                                          //数据口
  24. //sbit SCLK=P1^0;                                                                 //控制数据时钟
  25. //sbit RST=P1^2;                                                                  //使能端、复位端

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

  29. uchar knum=0,snum,fnum,ss;
  30. char shi,fen,miao;
  31.                   // 0     1    2    3    4     5    6    7    8   9
  32. uchar code d[]={ 0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F}; //共阴不带小数点
  33. uchar code dd[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};//        共阴带小数点

  34. //uchar dd[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};                //共阳带小数点
  35. //uchar d[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xd8,0x80,0x90};                //共阳不带小数点

  36. void delay(uint z)
  37. {
  38.         uint x,y;
  39.         for(x=z;x>0;x--)
  40.                 for(y=120;y>0;y--);
  41. }


  42. void t0_init()  //定时50ms一个中断
  43. {
  44.    
  45.   TMOD=0X01;
  46.   TH0=(65536-46080)/256;
  47.   TL0=(65536-46080)%256;
  48. //  TH1=(65536-46080)/256;
  49. //  TL1=(65536-46080)%256;

  50.   EA=1;
  51.   ET0=1;
  52.   TR0=1;
  53. //  ET1=1;
  54. //  TR1=1;

  55. }


  56. void display(uchar shi,uchar fen,uchar miao)                          //显示函数
  57. {
  58.         if(knum==0)
  59.         {
  60.                 snum=30;
  61.                 fnum=30;
  62.         }
  63.        
  64.         if(knum==1)
  65.         {
  66.                 fnum++;
  67.                 snum=30;
  68.         }
  69.        
  70.         if(knum==2)
  71.         {
  72.                 snum++;
  73.                 fnum=30;
  74.         }
  75.        
  76.        
  77.         if(snum>=30)
  78.         {       
  79.                 if((shi/10)<1)         //如果小时十位小于1,
  80.                 {
  81.                         wela=1;
  82.                         P0=0xfe;                //第1位
  83.                         wela=0;
  84.        
  85.                         dula = 1;
  86.                         P0=0xff;           // 小时十位就不显示
  87.                         dula = 0;
  88.                 }
  89.                
  90.                 else
  91.                 {
  92.                         wela=1;
  93.                         P0=0xfe;          //第1位
  94.                         wela=0;
  95.        
  96.                         dula=1;
  97.                         P0=d[shi/10];
  98.                         dula=0;
  99.                         P0=0xff;
  100.                         delay(2);
  101.                 }

  102.                 wela=1;
  103.                 P0=0xfd;           //第2位
  104.                 wela=0;

  105.                 dula=1;
  106.                 P0=d[shi%10];                        //时的个位,P0=d[shi%10]时的个位小数点闪烁
  107.                 dula=0;                                        // 时的个位,P0=dd[shi%10]时的个位小数点不闪烁
  108.                 P0=0xff;
  109.                 delay(2);
  110.        
  111.                 if(snum==60)
  112.                         snum=0;
  113.         }               


  114.         //        if(miao%2==0)         //if(miao%2==0) 1秒闪烁1次
  115.                 if(ss>=10)                 //        这里写为ss>=10,闪烁频率可调
  116.                 {                                  
  117.                     wela=1;
  118.                         P0=0xfb;                //第3位
  119.                         wela=0;
  120.        
  121.                         dula=1;
  122.                         P0=0x40;          //第三位数码管显示“— ”
  123.                        
  124.                 //        P0=0x09;          //第三位数码管显示“= ”
  125.                         dula=0;
  126.                         P0=0xff;
  127.                         delay(2);
  128.                 }

  129.                 else
  130.                 {
  131.                         wela=1;
  132.                         P0=0xfb;   //第3位
  133.                         wela=0;
  134.        
  135.                         dula=1;
  136.                         P0=0;          //第三位数码管不显示
  137.                         dula=0;
  138.                         P0=0xff;
  139.                         delay(2);       
  140.                 }
  141.        
  142.        
  143.         if(fnum>=30)
  144.         {
  145.                 wela=1;
  146.                 P0=0xf7;         //第4位
  147.                 wela=0;

  148.                 dula=1;
  149.                 P0=d[fen/10];
  150.                 dula=0;
  151.                 P0=0xff;
  152.                 delay(2);
  153.                
  154.                
  155.                 wela=1;
  156.                 P0=0xef;         //第5位
  157.                 wela=0;

  158.                 dula=1;
  159.                 P0=d[fen%10];
  160.                 dula=0;
  161.                 P0=0xff;
  162.                 delay(2);
  163.        
  164.                
  165.                 if(fnum==60)
  166.                         fnum=0;
  167.         }
  168.                
  169.         //        if(miao%2==0)         //if(miao%2==0) 1秒闪烁1次
  170.                 if(ss>=10)                 //if(ss>=10)闪烁频率可调
  171.                 {
  172.                         wela=1;
  173.                         P0=0xdf;          //第6位
  174.                         wela=0;
  175.                         dula=1;
  176.                         P0=0x40;          //第六位数码管显示“— ”
  177.                         dula=0;
  178.                         P0=0xff;
  179.        
  180.                         delay(2);
  181.                 }

  182.                 else
  183.                 {
  184.                         wela=1;
  185.                         P0=0xdf;   //第6位
  186.                         wela=0;
  187.                         dula=1;
  188.                         P0=0;          //第六位数码管不显示
  189.                         dula=0;
  190.                         P0=0xff;
  191.        
  192.                         delay(2);
  193.                 }
  194.                
  195.                
  196.                 wela=1;
  197.                 P0=0xbf;                //第7位
  198.                 wela=0;

  199.             dula=1;
  200.                 P0=d[miao/10];                           //秒十位
  201.                 dula=0;
  202.                 P0=0xff;
  203.                 delay(2);
  204.        

  205.                 wela=1;
  206.                 P0=0x7f;                          //第8位
  207.                 wela=0;

  208.                 dula=1;
  209.                 P0=d[miao%10];                         //秒个位
  210.                 dula=0;
  211.                 P0=0xff;
  212.                 delay(2);               
  213. }  



  214. void write_1302(uchar add,dat)                 //写函数  qx
  215. {
  216.         uchar i,temp;
  217.         temp=add;
  218.         ce=0;
  219.         _nop_();
  220.         sclk=0;
  221.         _nop_();
  222.         ce=1;
  223.         _nop_();
  224.         for(i=0;i<8;i++)
  225.         {
  226.                 sclk=0;
  227.                 _nop_();
  228.                 if((temp&0x01)==0x01)
  229.                         dio=1;
  230.                         else
  231.                         dio=0;
  232.                 temp>>=1;
  233.                 sclk=1;
  234.                 _nop_();
  235.         }
  236.         temp=dat;
  237.         for(i=0;i<8;i++)
  238.         {
  239.                 sclk=0;
  240.                 _nop_();
  241.                 if((temp&0x01)==0x01)
  242.                         dio=1;
  243.                         else
  244.                         dio=0;
  245.                 temp>>=1;
  246.                 sclk=1;
  247.                 _nop_();
  248.         }
  249.         ce=0;
  250.         sclk=0;
  251. }
  252. uchar read_1302(uchar add)                                   //读函数                qx
  253. {
  254.         uchar dat,dat1,i,temp;
  255.         temp=add;
  256.         ce=0;
  257.         _nop_();
  258.         sclk=0;
  259.         _nop_();
  260.         ce=1;
  261.         for(i=0;i<8;i++)
  262.         {
  263.                 sclk=0;
  264.                 _nop_();
  265.                 if((temp&0x01)==0x01)
  266.                         dio=1;
  267.                         else
  268.                         dio=0;
  269.                 temp>>=1;
  270.                 sclk=1;
  271.                 _nop_();
  272.         }
  273.         for(i=0;i<8;i++)
  274.         {
  275.                 sclk=0;
  276.                 _nop_();
  277.                 if(dio)
  278.                     dat|=0x80;
  279.                 if(i<7)
  280.                         dat>>=1;
  281.                 sclk=1;
  282.         }
  283.         dat1=dat/16;
  284.         dat=dat%16;
  285.         dat=dat1*10+dat;  
  286.         ce=0;
  287.         sclk=0;
  288.         return dat;
  289. }                       

  290. /*
  291. uchar read_1302(uchar add)                                                //读函数
  292. {
  293.         uchar i,date;
  294.         RST=0;                                                                                 //禁止读写数据
  295.         for(i=0;i<8;i++)
  296.         {
  297.                 RST=1;
  298.                 SCLK=0;
  299.                 IO=add&0x01;
  300.                 add>>=1;
  301.                 SCLK=1;
  302.         }
  303.         for(i=0;i<8;i++)
  304.         {
  305.                 if(IO)
  306.                         date=date|0x80;
  307.                 else
  308.                         date=date|0x00;
  309.                 SCLK=1;       
  310.                 date>>=1;
  311.                 SCLK=0;
  312.         }
  313.         RST=0;
  314.         date=date/16*10+date%16;                  //进制转换 16转10进制
  315.         IO=0;                                                          //数据读完后,IO口必须为0,不然小时一直显示85
  316.         return date;
  317. }
  318. void write_1302(uchar add,uchar dat)                //写函数
  319. {
  320.         uchar i;
  321.         RST=0;                                                                        //禁止读写数据
  322.         SCLK=0;                         
  323.         for(i=0;i<8;i++)                                                 //写地址
  324.         {
  325.                 RST=1;                                                                 //允许读写数据
  326.                 SCLK=0;
  327.                 IO=add&0x01;        
  328.                 add>>=1;
  329.                 SCLK=1;
  330.         }
  331.         for(i=0;i<8;i++)                                                 //写数据
  332.         {
  333.                 RST=1;                                                                //允许读写数据
  334.                 SCLK=0;       
  335.                 IO=dat&0x01;
  336.                 dat>>=1;
  337.                 SCLK=1;
  338.         }
  339.         RST=0;
  340. }         */


  341. void init_1302()                                                        //初始化函数 设置第一次上电时显示的时间值
  342. {       
  343.         write_1302(0x8e,0x00);                                        //保护取消,可以进行写操作
  344.         write_1302(write_miao,0x57);                        //写秒57
  345.         write_1302(write_fen,0x55);                                //写分55
  346.         write_1302(write_shi,0x15);                                //写时15
  347.         write_1302(0x8e,0x80);                                        //保护启动,不能进行写操作
  348. }         

  349. void read_sf()                           //读时分秒并显示
  350. {
  351.         shi=read_1302(read_shi);
  352.         fen=read_1302(read_fen);
  353.         miao=read_1302(read_miao);
  354.         display(shi,fen,miao);
  355. }


  356. void keyscan()                        //按键扫描函数
  357. {       
  358.         static uchar count;          //这里要定义为静态变量
  359.         if(key1==0)                          //按键按下
  360.         {
  361.                 count++;                          //消抖,也是连加一次的间隔时间
  362.                 if(key1==0 && count>10)//按键按下,计数变量加到12,
  363.                 {

  364.                         while(!key1)           //这里不需要连加,就加一句松手检测
  365.                         display(shi,fen,miao);
  366.                         count=0;
  367.                         TR0=0;
  368.                         knum++;                          
  369.                         if(knum==1)                                                 
  370.                         {
  371.                                  write_1302(0x8e,0x00);                  //DS1302写保护取消
  372.                                  write_1302(write_miao,0x80); //写秒80,时钟停止走时;
  373.                         }
  374.                        
  375.                         if(knum==3)                                                   //调时完毕,时钟启动
  376.                         {
  377.                                 TR0=1;
  378.                                 knum=0;
  379.                                 write_1302(write_miao,0x00); //写秒0,时钟启动走时
  380.                                 write_1302(0x8e,0x80);                 //保护启动
  381.                         }
  382.                 }
  383.         }


  384.         if(knum==1)                                                                //分钟调节
  385.         {
  386.                 if(key2==0)                                                        //加
  387.                 {
  388.                         count++;
  389.                         if(key2==0 && count>12)//短按加1,长按连加
  390.                         {
  391.                                 count=0;
  392.                                 fen++;
  393.                                 fen=fen/10*16+fen%10;                //转为16进制
  394.                                 if(fen==0x60)
  395.                                         fen=0x00;
  396.                                 write_1302(write_fen,fen);        //写入1302
  397.                         }
  398.                 }
  399.                
  400.                 if(key3==0)                                                   //减
  401.                 {
  402.                         count++;
  403.                         if(key3==0 && count>12)//短按减1,长按连减
  404.                         {
  405.                                 count=0;
  406.                                 fen--;
  407.                                 fen=fen/10*16+fen%10;                //转为16进制
  408.                                 if(fen==-1)
  409.                                         fen=0x59;
  410.                                 write_1302(write_fen,fen);
  411.                         }
  412.                 }
  413.         }
  414.        
  415.        
  416.         if(knum==2)                                                          //小时调节
  417.         {
  418.                 if(key2==0)
  419.                 {
  420.                         count++;
  421.                         if(key2==0 && count>12 )//短按加1,长按连加
  422.                         {
  423.                                 count=0;
  424.                                 shi++;
  425.                                 shi=shi/10*16+shi%10;                //转为16进制
  426.                                 if(shi==0x24)
  427.                                         shi=0x00;
  428.                                 write_1302(write_shi,shi);
  429.                         }
  430.                 }
  431.                
  432.                
  433.                 if(key3==0)
  434.                 {
  435.                         count++;
  436.                         if(key3==0 && count>12 )//短按减1,长按连减
  437.                         {       
  438.                                 count=0;
  439.                                 shi--;
  440.                                 shi=shi/10*16+shi%10;                //转为16进制
  441.                                 if(shi==-1)
  442.                                         shi=0x23;
  443.                                 write_1302(write_shi,shi);
  444.                         }
  445.                 }
  446.         }
  447. }          


  448. void main()
  449. {//        uchar i;
  450.         t0_init();
  451.         init_1302();                          
  452.         while(1)
  453.         {
  454.            //        for(i=0;i<4;i++)       
  455.         //        display(shi,fen,miao);
  456.             read_sf();
  457.             keyscan();
  458.         }
  459. }

  460. void temer1() interrupt 1
  461. {
  462.         TH0=(65536-46080)/256;
  463.         TL0=(65536-46080)%256;
  464.         ss++;
  465.         if(ss==20)
  466.                 ss=0;
  467. }        

  468. //void temer2() interrupt 3
  469. //{
  470. //        TH1=(65536-46080)/256;
  471. //        TL1=(65536-46080)%256;
  472. //        ss1++;
  473. //        if(ss1==20) //1秒
  474. //        {       
  475. //                ss1=0;
  476. ////                zs++;
  477. //                zs1--;
  478. //        }
  479. //}



复制代码
回复

使用道具 举报

ID:111376 发表于 2018-1-31 10:43 | 显示全部楼层
不错不错,感谢分享!
回复

使用道具 举报

ID:231936 发表于 2018-4-21 09:22 | 显示全部楼层
很好,可是掉电后就变了。
回复

使用道具 举报

ID:74370 发表于 2018-4-30 14:25 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:404878 发表于 2018-11-17 15:30 | 显示全部楼层
挺好的,正需要这样的程序,谢谢楼主
回复

使用道具 举报

ID:404878 发表于 2018-11-17 15:45 | 显示全部楼层
很可以想学习一下
回复

使用道具 举报

ID:127977 发表于 2018-11-17 16:47 | 显示全部楼层
学习了 啊 啊
回复

使用道具 举报

ID:658790 发表于 2019-12-8 14:25 | 显示全部楼层
仿真为啥打不开。。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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