找回密码
 立即注册

QQ登录

只需一步,快速开始

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

电子1302时钟的困惑

[复制链接]
跳转到指定楼层
楼主
#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 write_ram  0xc0
/***********读时分秒地址************/
#define read_shi  0x85
#define read_fen  0x83
#define read_miao 0x81
#define read_ram  0xc1
                  // 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;          // 这样第2~8bit原来是什么还是什么,不影响,第1bit赋值为1; TMOD=0x01 这样是给2~8bit赋值为0,第1bit赋值为1。//
  TH0 = (65536-46080)/256;                //        11.0592MHz除12为921600Hz,就是一秒921600次机器周期,50ms=46080次机器周期。 //
  TL0 = (65536-46080)%256;                //           256(D)=0100(H),这里01就是高8位的数据,00就是低8位的数据,        //
  EA = 1;                                                //         15536(D)里有多少个256,就相当于高8位有多少数值,就是除,商存入高8位寄存器后余下的数存入低8位即可//
  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];                       
                        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=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;                        //把字节存储在dio中
                        else
                        dio=0;
                temp>>=1; //右移
                sclk=1;         //数据在上升沿时,DS1302读取数据
                _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

if(KEY1==0)
   {
   delay(10);
   if(KEY1==0)
         FuncTempNum++;
         if(FuncTempNum>3)  FuncTempNum = 0;
   }


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();
        }

        switch (FuncTempNum)
        {
                case 1:        FunctionKeyNum = 1;
                                write_1302(0x8e,0x00);                //写保护取消
                                write_1302(write_miao,0x80); //  写秒80,时钟停止走时;
                break;
               
                case 2: FunctionKeyNum = 2;

                break;
               
                case 3:
                                FunctionKeyNum = 0;
                                write_1302(write_miao,0x00);
                                write_1302(0x8e,0x60);                //保护启动
                                FuncTempNum =0;
                break;


        }
}


void main()
{
        t0_init();
        t1_init();
        init_1302();                          
        while(1)
        {
           read_sf();
           ExecuteKeyNum();
        }
       
}

红字的地方是不太懂得地方,请教各位大神


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

使用道具 举报

沙发
ID:231633 发表于 2017-9-7 17:51 | 只看该作者

解答一下你这个问题吧。
       第一个  if(dio) ,就是如果接收数据的IO口是1,那么表示接收到的数据就是1,需要给dat的最高位“加上”1,因为下面紧接着的右移,就会把这个1带走到她应该待的地方。dio 为低电平,那么就是0了,dat的最高位就默认是一个0,那么右移过去的就是0。循环8次后,进行8位数据的接收。
      下面那三句话,是把一个BCD码转换为十进制的过程。你可以那一个笔手工算一下, 0X34 ,经过三句程序后,会变为十进制数字  34 。再深入解释一下有点多, dat/16 是右移4位的意思, dat%16 就保留了低四位 ,最后的是组合了一下。
      欢迎加我QQ号,一起交流更多的技术问题。 1827702167

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:111634 发表于 2017-9-9 11:16 | 只看该作者
本帖最后由 zl2168 于 2017-9-9 16:52 编辑

具有校正功能的时钟1302(LCD1602显示)
Proteus仿真,确认有效。
实例91 带校正时钟1302(LCD1602显示).rar (52.68 KB, 下载次数: 7)

以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1书中电路和程序设计有详细说明,程序语句条条有注解。仿真电路和Hex文件能在清华出版社网站免费下载,程序源代码只能到书上看了。到图书馆借,或到新华书店翻阅,或到网上书店打折购买。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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