技术文档

51单片机 ds1302 教你玩单片机之DS1302

小编 2024-10-06 技术文档 23 0

教你玩单片机之DS1302

以下所有内容仅适合新手,大神请勿介意哈,如有错误,麻烦大家指正,不喜勿喷。

DS1302简介

DS1302是一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。工作电压宽达2.5~5.5V。采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后备电源进行涓细电流充电的能力。

DS1302的引脚排列,其中Vcc2为主电源,VCC1为后备电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。X1和X2是振荡源,外接32.768kHz晶振。RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据传送的方法。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时,在Vcc>2.0V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。I/O为串行数据输入输出端(双向),后面有详细说明。SCLK为时钟输入端。 下图为DS1302的引脚功能图:

原理图

DS1302是通过SPI串行总线跟单片机通信的,当进行一次读写操作时最少得读写两个字节,第一个字节是控制字节,就是一个命令,告诉DS1302是读还是写操作,是对RAM还是对CLOK寄存器操作。第二个字节就是要读或写的数据了。

单字节读

只有在SCLK为低电平时,才能将CE置为高电平。所以在进行操作之前先将SCLK置低电平,然后将CE置为高电平,接着开始在IO上面放入要传送的电平信号,然后跳变SCLK。数据在SCLK上升沿时,DS1302读取数据,在SCLK下降沿时,DS1302放置数据到IO上

单字节写

只有在SCLK为低电平时,才能将RST置为高电平。说以在进行操作之前先将SCLK置低电平,然后将RST置为高电平,开始在IO上面放入要传送的电平信号,然后跳变SCLK。数据在SCLK上升沿时,DS1302读取数据,在SCLK下降沿时,DS1302放置数据到IO上

DS1302的时钟寄存器

时钟/日历包含在7个寄存器中,数据在时钟/日历寄存器中是二进制编码的十进制格式存储的,也就是常说的BCD码存储的。

时钟寄存器的第8个字节是写保护寄存器。当WP为“1”的时候是开启写保护,这个时候是禁止对DS1302进行写操作的。当WP为“0”的时候是关闭写保护,这个时候才能对DS1302进行写操作。

因为万年历程序过长,所以,需要看程序的朋友,可以进入我的主页查看文章:《单片机之DS1302万年历实验程序》

单片机之DS1302万年历实验程序

这篇文章是接上一篇《教你玩单片机之DS1302》的内容,有不明白的朋友可以进入我的主页,看我之前发的内容,不喜勿喷。

万年历实验

实验效果 :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒日月,按K2选择设置加1。

主程序

#include<reg51.h>

#include"lcd.h"

#include"ds1302.h"

sbit K1=P3^1;

sbit K2=P3^0;

sbit K3=P3^2;

sbit K4=P3^3;

void Int0Configuration();

void LcdDisplay();

unsigned char SetState,SetPlace;

void Delay10ms(void); //误差 0us

void main()

{

unsigned char i;

Int0Configuration();

LcdInit();

Ds1302Init();

while(1)

{

if(SetState==0)

{

Ds1302ReadTime();

}

else

{

if(K1==0)//检测按键K1是否按下

{

Delay10ms();//消除抖动

if(K1==0)

{

SetPlace++;

if(SetPlace>=7)

SetPlace=0;

}

while((i<50)&&(K1==0)) //检测按键是否松开

{

Delay10ms();

i++;

}

i=0;

}

if(K2==0)//检测按键K2是否按下

{

Delay10ms();//消除抖动

if(K2==0)

{

TIME[SetPlace]++;

if((TIME[SetPlace]&0x0f)>9) //换成BCD码。

{

TIME[SetPlace]=TIME[SetPlace]+6;

}

if((TIME[SetPlace]>=0x60)&&(SetPlace<2))//分秒只能到59

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x24)&&(SetPlace==2))//小时只能到23

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x32)&&(SetPlace==3))//日只能到31

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x13)&&(SetPlace==4))//月只能到12

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x7)&&(SetPlace==5))//周只能到7

{

TIME[SetPlace]=1;

}

//if(SetPlace==5)//月只能到12

//{

//TIME[SetPlace]=;

//}

}

while((i<50)&&(K2==0)) //检测按键是否松开

{

Delay10ms();

i++;

}

i=0;

}

}

LcdDisplay();

}

}

void LcdDisplay()

{

LcdWriteCom(0x80+0X40);

LcdWriteData('0'+TIME[2]/16);//时

LcdWriteData('0'+(TIME[2]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[1]/16);//分

LcdWriteData('0'+(TIME[1]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[0]/16);//秒

LcdWriteData('0'+(TIME[0]&0x0f));

LcdWriteCom(0x80);

LcdWriteData('2');

LcdWriteData('0');

LcdWriteData('0'+TIME[6]/16);//年

LcdWriteData('0'+(TIME[6]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[4]/16);//月

LcdWriteData('0'+(TIME[4]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[3]/16);//日

LcdWriteData('0'+(TIME[3]&0x0f));

LcdWriteCom(0x8D);

LcdWriteData('0'+(TIME[5]&0x07));//星期

}

void Int0Configuration()

{

//设置INT0

IT0=1;//跳变沿出发方式(下降沿)

EX0=1;//打开INT0的中断允许。

EA=1;//打开总中断

}

void Int0() interrupt 0

{

Delay10ms();

if(K3==0)

{

SetState=~SetState;

SetPlace=0;

Ds1302Init();

}

}

void Delay10ms(void) //误差 0us

{

unsigned char a,b,c;

for(c=1;c>0;c--)

for(b=38;b>0;b--)

for(a=130;a>0;a--);

}

#include"lcd.h"

#include"lcd.h"

void Lcd1602_Delay1ms(uint c) //误差 0us

{

uchar a,b;

for (; c>0; c--)

{

for (b=199;b>0;b--)

{

for(a=1;a>0;a--);

}

}

}

#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时

void LcdWriteCom(uchar com) //写入命令

{

LCD1602_E = 0; //使能

LCD1602_RS = 0; //选择发送命令

LCD1602_RW = 0; //选择写入

LCD1602_DATAPINS = com; //放入命令

Lcd1602_Delay1ms(1);//等待数据稳定

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5); //保持时间

LCD1602_E = 0;

}

#else

void LcdWriteCom(uchar com) //写入命令

{

LCD1602_E = 0; //使能清零

LCD1602_RS = 0; //选择写入命令

LCD1602_RW = 0; //选择写入

LCD1602_DATAPINS = com;//由于4位的接线是接到P0口的高四位,所以传送高四位不用改

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

//Lcd1602_Delay1ms(1);

LCD1602_DATAPINS = com << 4; //发送低四位

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

}

#endif

#ifndef LCD1602_4PINS

void LcdWriteData(uchar dat)//写入数据

{

LCD1602_E = 0;//使能清零

LCD1602_RS = 1;//选择输入数据

LCD1602_RW = 0;//选择写入

LCD1602_DATAPINS = dat; //写入数据

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5); //保持时间

LCD1602_E = 0;

}

#else

void LcdWriteData(uchar dat)//写入数据

{

LCD1602_E = 0; //使能清零

LCD1602_RS = 1; //选择写入数据

LCD1602_RW = 0; //选择写入

LCD1602_DATAPINS = dat;//由于4位的接线是接到P0口的高四位,所以传送高四位不用改

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

LCD1602_DATAPINS = dat << 4; //写入低四位

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

}

#endif

#ifndefLCD1602_4PINS

void LcdInit() //LCD初始化子程序

{

LcdWriteCom(0x38); //开显示

LcdWriteCom(0x0c); //开显示不显示光标

LcdWriteCom(0x06); //写一个指针加1

LcdWriteCom(0x01); //清屏

LcdWriteCom(0x80); //设置数据指针起点

}

#else

void LcdInit() //LCD初始化子程序

{

LcdWriteCom(0x32); //将8位总线转为4位总线

LcdWriteCom(0x28); //在四位线下的初始化

LcdWriteCom(0x0c); //开显示不显示光标

LcdWriteCom(0x06); //写一个指针加1

LcdWriteCom(0x01); //清屏

LcdWriteCom(0x80); //设置数据指针起点

}

#endif

#include"ds1302.h"

#include"ds1302.h"

//---DS1302写入和读取时分秒的地址命令---//

//---秒分时日月周年 最低位读写位;-------//

uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};

uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//

//---存储顺序是秒分时日月周年,存储格式是用BCD码---//

uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};

void Ds1302Write(uchar addr, uchar dat)

{

uchar n;

RST = 0;

_nop_();

SCLK = 0;//先将SCLK置低电平。

_nop_();

RST = 1; //然后将RST(CE)置高电平。

_nop_();

for (n=0; n<8; n++)//开始传送八位地址命令

{

DSIO = addr & 0x01;//数据从低位开始传送

addr >>= 1;

SCLK = 1;//数据在上升沿时,DS1302读取数据

_nop_();

SCLK = 0;

_nop_();

}

for (n=0; n<8; n++)//写入8位数据

{

DSIO = dat & 0x01;

dat >>= 1;

SCLK = 1;//数据在上升沿时,DS1302读取数据

_nop_();

SCLK = 0;

_nop_();

}

RST = 0;//传送数据结束

_nop_();

}

uchar Ds1302Read(uchar addr)

{

uchar n,dat,dat1;

RST = 0;

_nop_();

SCLK = 0;//先将SCLK置低电平。

_nop_();

RST = 1;//然后将RST(CE)置高电平。

_nop_();

for(n=0; n<8; n++)//开始传送八位地址命令

{

DSIO = addr & 0x01;//数据从低位开始传送

addr >>= 1;

SCLK = 1;//数据在上升沿时,DS1302读取数据

_nop_();

SCLK = 0;//DS1302下降沿时,放置数据

_nop_();

}

_nop_();

for(n=0; n<8; n++)//读取8位数据

{

dat1 = DSIO;//从最低位开始接收

dat = (dat>>1) | (dat1<<7);

SCLK = 1;

_nop_();

SCLK = 0;//DS1302下降沿时,放置数据

_nop_();

}

RST = 0;

_nop_();//以下为DS1302复位的稳定时间,必须的。

SCLK = 1;

_nop_();

DSIO = 0;

_nop_();

DSIO = 1;

_nop_();

return dat;

}

void Ds1302Init()

{

uchar n;

Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能

for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年

{

Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);

}

Ds1302Write(0x8E,0x80); //打开写保护功能

}

void Ds1302ReadTime()

{

uchar n;

for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年

{

TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);

}

}

相关问答

英语翻译本课题使用 51单片机 , DS1302 时钟芯片, DS 18B20温度芯...

[最佳回答]Thisprojectistouse51Single-ChipMicrocomputer,DS1302clockCMOSchip,DS18B20temperatureCMOS...

DS1302 定时器有什么用?

DS1302是时钟芯片,产生标准的时钟数据,并不是定时器,所以,只能按时钟计时,不能定时。要定时,用单片机根据DS1302的时间,由定时起始时间,结束时间来判断,...DS...

ds1302 时钟芯片是电子时钟电路?

简单说,DS1302是个产生实时时钟的芯片,通过她可以得到年、月、日、周日、时、分、秒等等数据;单片机可以通过编程,实现DS1302芯片功能,显然,需要编程,而...

DS1302 时钟为什么 DS1302 的时钟设?

简单说,DS1302是个产生实时时钟的芯片,通过她可以得到年、月、日、周日、时、分、秒等等数据;单片机可以通过编程,实现DS1302芯片功能,显然,需要编程,而使...

DS1302 读不到时间数据-ZOL问答

dssclk=0;dsres=1;for(i=0;i<8;i++){dssclk=0;dsio=0;if(addr&0x01)dsio=1;dssclk...

单片机 芯片怎么插?

DS1302芯片与51单片机的连接X1、X2:32.768KHz晶振接入引脚。(15分频1HZ——1S定时,时钟通用晶振)GND:接地。RET:复位引脚,低电平有效,操作时高电平。I...

法拉电容, 单片机 ,时间可以存多久?

存不了多久,可能就两到三分钟,但如果给DS1302这样的芯片供电,维持工作几十分钟不在话下,单片机耗电10ma左右,而DS1302耗电只有几十微安,二者相差几百倍,因...

我要做一个路灯控制系统,就是让 单片机 晚上18:00开始工作进行控制,次日6点单片机关闭,怎样控制单片机的?

你好!利用单片机的最小系统,加上时钟DS1302,设置好开启和关闭时间,就能完成了你好!利用单片机的最小系统,加上时钟DS1302,设置好开启和关闭时间,就能完成了

单片机 数字钟毕业中期检查表中的一个问题 - 沈禾欣子 的回答...

你问什么问题??淮安信息职5261业技术学院综合毕业实践说明4102书(论文1653)2009-2010学年系专业摘要:数字电子时钟电路设计系统,以AT89C51单片机为...

求一个 51单片机 定时闹钟程序。要C语言。能够调时间 - 198***...

我来发一个C语言211351单片机时钟程序,希望5261能帮到你/*程序功能:4102带定时闹铃时钟*//*-------...

猜你喜欢