一、原理分析
DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,并且具有闰年补偿等多种功能。
1、DS1302控制字格式:
2、DS1302 相关的寄存器:(数据格式:BCD码)
二、程序编写
将官方提供的资源包里的底层驱动代码拷贝到工程路径下:
ds1302.c
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include <reg52.h>
#include <intrins.h>
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
#endif
main.c
#include <reg52.h>
#include <ds1302.h>
//定义ds1302读操作的日历时钟存储器地址
unsigned char write_ds1302_add[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
//定义ds1302写操作的日历时钟存储器地址
unsigned char read_ds1302_add[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
//设置初始时间:2022年3月7日,周一,23点59分51秒(BCD码)
unsigned char time[7]={0x51,0x59,0x23,0x07,0x03,0x01,0x22};
unsigned char smg_nodot[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char smg_dot[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
void ds1302_init()//ds1302初始化
{
char i;
Write_Ds1302_Byte(0x8e,0x00);//写保护位wp置0,可进行写操作
for(i=0;i<7;i++)
{
Write_Ds1302_Byte(write_ds1302_add[i],time[i]);
}
Write_Ds1302_Byte(0x8e,0x80);//写保护位wp置1,禁止写操作
}
void read_ds1302_time()//读时间
{
char i;
for(i=0;i<7;i++)
{
time[i]=Read_Ds1302_Byte(read_ds1302_add[i]);
}
}
//数码管显示模块
void Delay_SMG(unsigned int t)
{
while(t--);
}
void DisplaySMG_Bit(unsigned char pos,unsigned char dat)
{
P2=0xE0;P0=0xff;//先全部关掉数码管,避免显示不正常
P2=0xC0;P0=0x01<<pos;
P2=0xE0;P0=dat;
}
void display_1302()
{
DisplaySMG_Bit(0,smg_nodot[time[2]/16]);
Delay_SMG(100);
DisplaySMG_Bit(1,smg_nodot[time[2]%16]);
Delay_SMG(100);//时
DisplaySMG_Bit(2,0xbf); //分隔符—
Delay_SMG(100);
DisplaySMG_Bit(3,smg_nodot[time[1]/16]);
Delay_SMG(100);
DisplaySMG_Bit(4,smg_nodot[time[1]%16]);
Delay_SMG(100);//分
DisplaySMG_Bit(5,0xbf);//分隔符—
Delay_SMG(100);
DisplaySMG_Bit(6,smg_nodot[time[0]/16]);
Delay_SMG(100);
DisplaySMG_Bit(7,smg_nodot[time[0]%16]);
Delay_SMG(100);//秒
P2=0xC0;P0=0xff;//关闭全部数码管,避免最右的数码管显示特别亮
P2=0xE0;P0=0xff;
}
void main()
{
P2=0x80;P0=0xff;//关闭LED灯
ds1302_init();
while(1)
{
read_ds1302_time();
display_1302();
}
}