一、芯片介绍
DS1302是一种串行接口的实时时钟,高性能、低功耗,内部有可编程的日历时钟和31个字节的静态RAM,可以自动进行闰年补偿
工作电压范围宽(2.5V~5.5V),还有对备用电池进行涓流充电功能,可有效延长备用电池的使用寿命
DS1302用于数据记录,能实现数据与该数据出现的时间同时记录,因此应用广泛。
二、原理分析
1.引脚介绍
VCC1 | 主电源 |
---|---|
VCC2 | 备用电源,当VCC2大于VCC1 + 0.2V时,由VCC2向DS1302供电否则由VCC1向DS1302供电 |
SCLK | 串行时钟输入端,控制数据输入和输出 |
IO | 双向输入线 |
RST(CE) | 使能端,RST为高时允许读写DS1302数据,为低时禁止读写 |
X1,X2 | 外接32.768KHZ圆形晶振,给时钟芯片提供工作频率 |
2.命令字及寄存器介绍
使用该芯片时,当想要读取某一个数据时,先写入对应的命令字字符,然后接着读或写出对应的寄存器。至于驱动程序我认为不用掌握,考试时赛点资源包里会有,可直接调用。
秒寄存器(81H、80H)
bit7定义为时钟暂停标志(CH)
当该位置为1时,时钟振荡器停止,DS1302处于低功耗状态
当该位置为0时,时钟开始运行
小时寄存器(85H、84H)
bit7用于定义DS1302是运行于12小时模式还是24小时模式,
当为1时,现在12小时模式,此时bit5为AM/PM位
在24小时模式时,此位为小时数据位
控制寄存器(8FH、8EH)
bit7是写保护位(WP),其他7位均为0,
在任何对时钟或RAM读写操作之前,WP位必须为0。当WP位为1时,不能对任何时钟日历寄存器或RAM进行写操作。
3.补充
移位
1.右移">>",无符号时,高位补零,低位舍弃;但在处理有符号数的时候会有不同。有符号数高位是零,则右移时高位补零;如果是负数即高位是1,那么有的系统会移入1,称算术右移(大部分系统),有的会移入0,称逻辑右移。
2."<<",C语言中的左移运算,无论是有符号数还是无符号数都是按照逻辑左移来操作,即向左移动若干位,低位补0即可,高位舍弃。
三、程序例程
#include<stc15f2k60s2.h>
#include<intrins.h>
#include<ds1302.h>
#define uchar unsigned char
uchar hour=23,minute=59,seconds=55,temp;
uchar wei_tab[]={0xff,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位选从0到8依次为全选,1号管到八、8号管
uchar duan_tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x98,0xbf}; //段选从0到10依次为,0到9以及‘-’
void Delay1ms();
void close_buzz();
void dispaly(uchar wei,uchar duan);
void ds1302_init();
void ds1302_data_get();
void main()
{
close_buzz();
ds1302_init();
while(1)
{
ds1302_data_get();
dispaly(7,seconds/10);
dispaly(8,seconds%10);
dispaly(4,minute/10);
dispaly(5,minute%10);
dispaly(1,hour/10);
dispaly(2,hour%10);
}
}
void dispaly(uchar wei,uchar duan)
{
P2=0xc0; //1100 0000,译码器输出Y6,选择位选锁存器
P0=wei_tab[wei];
P2=0xff;
P0=duan_tab[duan];
Delay1ms();
}
void close_buzz()
{
P2=0xa0; //ULN2003
P0=0x00; //主要是想关了蜂鸣器
}
void ds1302_init()
{
// temp=(year/10)<<4+year%10;
// Write_Ds1302_Byte(0x8C,temp); //年
// Write_Ds1302_Byte(0x8a,temp); //天(周)
// Write_Ds1302_Byte(0x88,temp); //月
// Write_Ds1302_Byte(0x86,temp); //日(月)
Write_Ds1302_Byte(0x8e,0); //清除写保护
temp=((hour/10)<<4)+hour%10; //24小时制,4,5存十位;0,1,2,3位存个位
Write_Ds1302_Byte(0x84,temp); //时
temp=((minute/10)<<4)+minute%10; //高四位存十位,第四位存低位
Write_Ds1302_Byte(0x82,temp); //分
temp=((seconds/10)<<4)+seconds%10; //高四位存十位,第四位存低位
Write_Ds1302_Byte(0x80,temp); //秒
Write_Ds1302_Byte(0x8e,0x80); //清除写保护
}
void ds1302_data_get()
{
temp=Read_Ds1302_Byte (0x81); //秒
seconds=10*(temp>>4)+(temp&0x0f);
temp=Read_Ds1302_Byte (0x83); //分
minute=10*(temp>>4)+(temp&0x0f);
temp=Read_Ds1302_Byte (0x85); //时
hour=10*(temp>>4)+(temp&0x0f);
}
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
四、心得
1.初始化(往里面写初始时间之前)之前要先清除写保护,写完之后再开启写保护(命令字0x8e)(wp)。
2.数据转换时,进行逻辑算数运算时,记不清运算符优先级的,一定要加上括号。
3.在程序编写时数码管的显示顺序似乎会对程序产生影响,没有发现什么原因,注意下吧。