DS1302时钟C语言编程完整实例.docx
- 文档编号:12231993
- 上传时间:2023-04-17
- 格式:DOCX
- 页数:28
- 大小:82.10KB
DS1302时钟C语言编程完整实例.docx
《DS1302时钟C语言编程完整实例.docx》由会员分享,可在线阅读,更多相关《DS1302时钟C语言编程完整实例.docx(28页珍藏版)》请在冰豆网上搜索。
DS1302时钟C语言编程完整实例
1DS1302简介:
DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行
同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM
数据。
实时时钟可提供秒、分、时、日、星期、月和年,一个月小与
31天时可以自动调整,且具有闰年补偿功能。
工作电压宽达2.5~
5.5V。
采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。
DS1302的外部
引脚分配如图1所示及内部结构如图2所示。
DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该
数据的时间同时记录,因此广泛应用于测量系统中。
图1DS1302的外部引脚分配
图2DS1302的内部结构
各引脚的功能为:
Vcc1:
主电源;Vcc2:
备份电源。
当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2 SCLK: 串行时钟,输入,控制数据的输入与输出; I/O: 三线接口时的双向数据线; CE: 输入信号,在读、写数据期间,必须为高。 该引脚有两个功能: 第一,CE开始控制字访问移位寄存器的控制逻辑;其次, CE提供结束单字节或多字节数据传输的方法。 DS1302有下列几组寄存器: ①DS1302有关日历、时间的寄存器共有12个,其中有7个寄存器 (读时81h~8Dh,写时80h~8Ch),存放的数据格式为BCD码形式,如图3所示。 图3DS1302有关日历、时间的寄存器小时寄存器(85h、84h)的位7用于定义DS1302是运行于12小时模式还是24小时模式。 当为高时,选择12小时模式。 在12小时模式时, 位5是,当为1时,表示PM。 在24小时模式时,位5是第二个10小时 位。 秒寄存器(81h、80h)的位7定义为时钟暂停标志(CH)。 当该位置为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位置为 0时,时钟开始运行。 控制寄存器(8Fh、8Eh)的位7是写保护位(WP),其它7位均置 为0。 在任何的对时钟和RAM的写操作之前,WP位必须为0。 当 WP位为1时,写保护位防止对任一寄存器的写操作。 ②DS1302有关RAM的地址 DS1302中附加31字节静态RAM的地址如图4所示。 图4 ③DS1302的工作模式寄存器 所谓突发模式是指一次传送多个字节的时钟信号和RAM数据。 突发模式寄存器如图5所示。 图5 ④此外,DS1302还有充电寄存器等。 2读写时序说明 DS1302是SPI总线驱动方式。 它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。 要想与DS1302通信,首先要先了解DS1302的控制字。 DS1302 的控制字如图6。 图6控制字(即地址及命令字节) 控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。 位6: 如果为0,则表示存取日历时钟数据,为1表示存取RAM数据; 位5至位1(A4~A0): 指示操作单元的地址; 位0(最低有效位): 如为0,表示要进行写操作,为1表示进行读操作。 控制字总是从最低位开始输出。 在控制字指令输入后的下一个 SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。 同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。 数据读写时序如图7。 图7数据读写时序 具体操作见驱动程序。 3电路原理图: 电路原理图如图8,DS1302与单片机的连接也仅需要3条线: CE引脚、 SCLK串行时钟引脚、I/O串行数据引脚,Vcc2为备用电源,外接 32.768kHz晶振,为芯片提供计时脉冲。 图8 以上部分是我拷贝别人的,在此我要感谢他,后面的部分全部是我自己写的,经过调试,系统运行稳定。 本来是不准备拷贝的,但考虑读者可能会读不懂程序,所以我才将核心器件的通信协议拿来给大家看看,当初老师叫我随便用C语言编写个单片机程序,于是我就找了个DS1302时钟的程序,写的有点长,可能是我第一次经验不够吧。 #include #include #defineucharunsignedchar #defineuintunsignedint ucharcodetable[]= {0xc0,0xf9,0xa4,0xb0, 0x99,0x92,0x82,0xf8, 0x80,0x90,0x7f};//0123456789. sbitsclk=P3^6; sbitdata_io=P3^7; sbitrst=P3^5; sbitk1=P1^4;//mod功能选择键 sbitk2=P1^5;//--(待机时按此键显示当前日期) sbitk3=P1^6;//++(待机时,按此键显示闹钟时间及状态,进入闹钟设定时此键是闹铃开关键) sbitk4=P1^7;//退出设定 sbitdidi=P3^0;//闹钟铃音 ucharmod; ucharkaiguan; bitkeys(void);//函数申明 voidshow(x,y,z);//函数申明 voidalarmshow(a_shi,a_fen);//函数申明 voiddelay(uintms)//1ms延时子程序 { uinti,j; for(i=ms;i>0;i--) for(j=244;j>0;j--); } voidalarmdisplay(ucharshu,ucharwei)//闹钟显示子程序 { P2=0x00; P0=table[shu]; P2=(1< delay (1); P2=0x00; if(kaiguan%2)//显示ON12-23,闹钟时间显示格式 { P0=0xc0; P2=0x01; delay (1); P2=0x00; P0=0xc8; P2=0x02; delay (1); P2=0x00; P0=0xf7; P0=0x08; delay (1); P2=0x00; } else//显示OFF12-23,闹钟时间显示格式 { P2=0x00; P0=0xc0; P2=0x01; delay (1); P2=0x00; P0=0x8e; P2=0x02; delay (1); P2=0x00; P0=0x8e; P2=0x04; delay (1); P2=0x00; } } voiddisplay(ucharshu,ucharwei)//显示函数 { P2=0x00; P0=table[shu]; P2=(1< delay (1); P2=0x00;//显示该位数字 P0=0xbf; P2=0x04; delay (1);//显示横杠 P2=0x00; P0=0xbf; P2=0x20; delay (1);//显示横杠 P2=0x00; } voidweidisplay(void)//调时间时显示调整哪一个位 { ucharwei; P2=0x00; P0=0x7f; if(mod==1||mod==4||mod==7) wei=3; if(mod==2||mod==5) wei=0; if(mod==3||mod==6) wei=6; P2=(3< delay(3); P2=0x00; } voidalarm()//闹钟铃音子程序 { uinti; for(i=59;i>0;i--) { didi=1; delay (1); didi=0; delay (1); if(k1==0) { delay(5); if(k1==0) { while(~k1); break; } } } } voidwrite(ucharaddr,ucharshu)//写两个字节 { uchartemp,t; rst=0; sclk=0; rst=1; temp=addr; for(t=0;t<8;t++) { if(temp&0x01) data_io=1; elsedata_io=0; sclk=1; delay (1); sclk=0; temp>>=1; } temp=shu; for(t=0;t<8;t++) { if(temp&0x01) data_io=1; elsedata_io=0; sclk=1; delay (1); sclk=0; temp>>=1; } rst=0; } ucharread(ucharaddr)//读一个字节 { uchartemp,t; rst=0; sclk=0; rst=1; temp=addr; for(t=0;t<8;t++) { if(temp&0x01) data_io=1; elsedata_io=0; sclk=1; sclk=0; temp>>=1; } temp=0; for(t=0;t<7;t++) { if(data_io==1) temp=temp|0x80; elsetemp=temp&0x7f; sclk=1; sclk=0; temp>>=1; } returntemp; } //************************************************8888 //************************************************8888 voidmain()//主函数 { bitflag; ucharshi,fen,miao,nian,yue,ri,a_shi,a_fen;//当前时间10: 06: 5310-12-20 write(0x80,0x53); write(0x82,0x06);//秒寄存器(初始化年月日,时分秒,闹铃) write(0x84,0x10);//时寄存器 write(0x86,0x20);//日寄存器 write(0x88,0x12);//月寄存器 write(0x8c,0x10);//年寄存器 a_shi=0x07;//初始化闹钟时间7: 30 a_fen=0x30; while (1) { shi=read(0x85);//读小时 fen=read(0x83);//读分钟 miao=read(0x81);//读秒钟 if(kaiguan%2)//判断闹钟 { if(a_shi==shi&&a_fen==fen) alarm(); } if(k3==0&&mod==0)//待机情况下按k3显示闹铃时间 { delay(5); if(k3==0&&mod==0) { while(~k3) alarmshow(a_shi,a_fen); } } if(k2==0&&mod==0)//待机情况下按k2显示日期 { delay(5); if(k2==0&&mod==0) { while(~k2) show(nian,yue,ri); } } flag=keys();//按键标识位,有按键按下时flag=1; if (1)//程序出现个小错误,原本这里是写flag,但没有办法,只能写1了,感兴趣的话自己分析 { if(mod==1) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k2==0) { delay(5); if(k2==0) { while(~k2); fen=(fen>>4)*10+(fen&0x0f); fen++; if(fen==60) fen=0; fen=((fen/10)<<4)+((fen%10)&0x0f); write(0x82,fen); } } } if(mod==2) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k2==0) { delay(5); if(k2==0) { while(~k2); shi=(shi>>4)*10+(shi&0x0f); shi++; if(shi==24) shi=0; shi=((shi/10)<<4)+((shi%10)&0x0f); write(0x84,shi); } } } if(mod==1) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k3==0) { delay(5); if(k3==0) { while(~k3); fen=(fen>>4)*10+(fen&0x0f); if(fen==0) fen=60; fen--; fen=((fen/10)<<4)+((fen%10)&0x0f); write(0x82,fen); } } } if(mod==2) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k3==0) { delay(5); if(k3==0) { while(~k3); shi=(shi>>4)*10+(shi&0x0f); if(shi==0) shi=24; shi--; shi=((shi/10)<<4)+((shi%10)&0x0f); write(0x84,shi); } } } if(mod==3) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k2==0) { delay(5); if(k2==0) { while(~k2); ri=(ri>>4)*10+(ri&0x0f); ri++; if(ri==32) ri=0; ri=((ri/10)<<4)+((ri%10)&0x0f); write(0x86,ri); } } } if(mod==4) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k2==0) { delay(5); if(k2==0) { while(~k2); yue=(yue>>4)*10+(yue&0x0f); yue++; if(yue==13) yue=0; yue=((yue/10)<<4)+((yue%10)&0x0f); write(0x88,yue); } } } if(mod==5) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k2==0) { delay(5); if(k2==0) { while(~k2); nian=(nian>>4)*10+(nian&0x0f); nian++; if(nian==100) nian=0; nian=((nian/10)<<4)+((nian%10)&0x0f); write(0x8c,nian); } } } if(mod==3)//年月日减 { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k3==0) { delay(5); if(k3==0) { while(~k3); ri=(ri>>4)*10+(ri&0x0f); if(ri==0) ri=32; ri--; ri=((ri/10)<<4)+((ri%10)&0x0f); write(0x86,ri); } } } if(mod==4) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k3==0) { delay(5); if(k3==0) { while(~k3); yue=(yue>>4)*10+(yue&0x0f); if(yue==0) yue=32; yue--; yue=((yue/10)<<4)+((yue%10)&0x0f); write(0x88,yue); } } } if(mod==5) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k3==0) { delay(5); if(k3==0) { while(~k3); nian=(nian>>4)*10+(nian&0x0f); if(nian==0) nian=100; nian--; nian=((nian/10)<<4)+((nian%10)&0x0f); write(0x8c,nian); } } } //*################################################################################ if(mod==6) { if(k4==0)//如果k4=0,则退出设定 { delay(5); if(k4==0) { while(~k4); mod=0; } } if(k3==0) { delay(5); while(~k3); kaiguan++; } if(k2==0) { delay(5); while(~k2); a_fen=(a_fen>>4)*10+(a_fen&0x0f); a_fen++; if(a_fen==60) a_fen=0; a_fen=((a_fen/10)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- DS1302 时钟 语言 编程 完整 实例