ds1302时钟程序详解 含电路图 源程序 注释

合集下载

ds1302程序及原理图

ds1302程序及原理图

/**************************************************;文件名:DS1302.c;功能:设置时间,然后将时间读出显示在数码管上;硬件描述:PORTD口接数码管的8个笔段; PORTA 0~2及PORTE 0~2分别接6位数码管的位;RC3接SCK,RC4接SDA,RC2接RST*/#include "pic.h"#define uchar unsigned char#define uint unsigned int#define Hidden 16__CONFIG(HS&WDTDIS&LVPDIS); //配置文件,设置为HS方式振荡,禁止看门狗,低压编程关闭ucharDispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x8 6,0x8E,0xFF};uchar BitTab[]={0xfb,0xfd,0xfe};uchar DispBuf[6];#define LSB 0x01#define WrEnDisCmd 0x8e //写允许/禁止指令代码#define WrEnDat 0x00 //写允许数据#define WrDisDat 0x80 //写禁止数据#define OscEnDisCmd 0x80 //振荡器允许/禁止指令代码#define OscEnDat 0x00 //振荡器允许数据#define OscDisDat 0x80 //振荡器禁止数据#define WrMulti 0xbe //写入多个字节的指令代码#define WrSingle 0x84 //写入单个字节的指令代码#define RdMulti 0xbf //读出多个字节的指令代码#define cClk RC3 //与时钟线相连的PIC16F877A芯片的管脚#define cDat RC4 //与数据线相连的PIC16F877A芯片的管脚#define cRst RC2 //与复位端相连的PIC16F877A芯片的管脚#define SCL_CNT TRISC3 //SCL管脚控制位#define SDA_CNT TRISC4 //SDA管脚控制位#define RST_CNT TRISC2 //RST管脚控制位void mDelay(uint DelayTime){ uint temp;for(;DelayTime>0;DelayTime--){ for(temp=0;temp<270;temp++){;}}}void interrupt Disp(){ static uchar dCount; //用作显示的计数器if(TMR1IF==1&&TMR1IE==1)//Timer 1 inetrrupt{TMR1H=-(8000/256);TMR1L=-(8000%256); //重置定时初值}PORTA|=0x07; //关前面的显示PORTE|=0X07; //关前面的显示PORTD=DispTab[DispBuf[dCount]]; //显示第i位显示缓冲区中的内容if(dCount<3)PORTE&=BitTab[dCount]; //第1~3位是由PORTE控制的elsePORTA&=BitTab[dCount-3]; //第4~6位是由PORTA的低3位控制的dCount++;if(dCount==6)dCount=0;TMR1IF=0; //清中断标志}//数码管位 1 2 3 4 5 6//引脚RE0 RE1 RE2 RA2 RA1 RA0//根据这个表,只要改变PORTA&=0xfe,即可点亮任意一个数码管//例:PORTA&=0xfd //点亮第5位数码管// PORTE&=0xfe //点亮第3位数码管void uDelay(uchar i){ for(;i>0;i--){;}}void SendDat(uchar Dat){ uchar i;for(i=0;i<8;i++){cDat=Dat&LSB; //数据端等于tmp数据的末位值Dat>>=1;cClk=1;uDelay(1);cClk=0;}}/*写入1个或者多个字节,第1个参数是相关命令#define WrMulti 0xbe //写入多个字节的指令代码#define WrSingle 0x84 //写入单个字节的指令代码第2个参数是待写入的值第3个参数是待写入数组的指针*/void WriteByte(uchar CmdDat,uchar Num,uchar *pSend){uchar i=0;SDA_CNT=0; //数据端设为输出cRst=0;uDelay(1);cRst=1;SendDat(CmdDat);for(i=0;i<Num;i++){ SendDat(*(pSend+i));}cRst=0;}/*读出字节,第一个参数是命令#define RdMulti 0xbf //读出多个字节的指令代码第2个参数是读出的字节数,第3个是指收数据数组指针*/void RecByte(uchar CmdDat,uchar Num,uchar *pRec){uchar i,j,tmp;SDA_CNT=0; //数据端设为输出cRst=0; //复位引脚为低电平uDelay(1);cClk=0;uDelay(1);cRst=1;SendDat(CmdDat); //发送命令SDA_CNT=1; //数据端设为输入for(i=0;i<Num;i++){ for(j=0;j<8;j++){ tmp>>=1;if(cDat)tmp|=0x80;cClk=1;uDelay(1);cClk=0;}*(pRec+i)=tmp;}uDelay(1);cRst=0;}/*当写保护寄存器的最高位为0时,允许数据写入寄存器。

基于DS1302设计的数字钟原理图与PCB教程

基于DS1302设计的数字钟原理图与PCB教程

基于DS1302设计的数字钟任务一电路原理图的设计1、最小系统电路步骤一:新建设计。

双击桌面PROTEUS软件图标,打开软件,单击工具栏“File”,出现如下图所示下拉菜单。

单击“New Design”菜单,弹出如下对话框。

选择绘图模板,我们选择DEFAULT模板,单击DEFAULT图标,单击“OK”按钮。

进入原理图编辑界面,如下图所示。

存。

单击保存图标,弹出对话框,选择文件存储路径。

如下图所示:我们把文件保存在桌面的“电路原理图”这个文件夹内。

单击“保存”按钮弹出对话框,在“文件名”编辑框中填写电路原理图名称,“基于DS1302设计的数字钟”。

如下图所示。

路原理图标,如下图所示。

步骤三:选择主控元器件。

在编辑框最左边的工具栏中选择图标,进入器件模式,然后单击图标,弹出“Pick Device”对话框,如下图所示:AT89C51单片机,如下图所示:单击OK按钮,单片机芯片选择完成,这时在对象选择器和预览窗口中均出现了所选择的芯片AT89C52,在对象选择器单击芯片名称,如AT89C52,再把鼠标移至编辑窗口区(工作区),右击鼠标,主控芯片AT89C52就拖入了工作区。

单片机芯片选择完毕。

如下图所示:步骤四:时钟振荡电路的设计。

51单片机的18和19引脚外接2个皮法级的电容和晶振就可以构成时钟振荡电路。

按照上一步骤选择AT89C52芯片的方法一一从元器件库中选择2个30pf的电容、12M的晶振,还有一个地。

如下图所示:个电阻R1、R2和电容组成,具体电路结构如下图所示:此外,还有电源电路,单片机的20引脚、40引脚分别接电源的地和电。

另外单片机31引脚直接接地,表示单片机的CPU直接从片内的ROM中读取指令。

2、DS1302时钟电路DS1302时钟电路主要由时钟芯片DS1302和单片的P1口相连,DS1302有8个引脚,1引脚直接接电,2、3引脚跨接一个32768HZ的晶振,4引脚接地,5、6、7引脚分别连接单片机P1口的P1^2、P1^0、P1^1。

DS1302程序及连接图

DS1302程序及连接图

/****************************************************************************** ** 标题: 试验数码管显示时钟**** 通过本例程了解DS1302时钟芯片的基本原理和使用,理解并掌握DS1302时钟芯片** 驱动程序的编写以及实现数字字符在数码管中的显示。

** 注意:JP1302跳线冒要短接。

** 请学员认真消化本例程,懂DS1302在C语言中的操作******************************************************************************** */#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#include <intrins.h>sbit SCK=P3^6; //时钟sbit SDA=P3^4; //数据sbit RST = P3^5;// DS1302复位sbit LS138A=P2^2;sbit LS138B=P2^3;sbit LS138C=P2^4;bit ReadRTC_Flag;//定义读DS1302标志unsigned char l_tmpdate[7]={0,0,12,15,5,3,8};//秒分时日月周年08-05-15 12:00:00unsigned char l_tmpdisplay[8];code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年最低位读写位code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴数码管0-9 '-' '熄灭‘表/******************************************************************//* 函数声明*//******************************************************************/void Write_Ds1302_byte(unsigned char temp);void Write_Ds1302( unsigned char address,unsigned char dat );unsigned char Read_Ds1302 ( unsigned char address );void Read_RTC(void);//read RTCvoid Set_RTC(void); //set RTCvoid InitTIMER0(void);//inital timer0/******************************************************************//* 主函数*//******************************************************************/void main(void){InitTIMER0(); //初始化定时器0Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽while(1){if(ReadRTC_Flag){ReadRTC_Flag=0;Read_RTC();l_tmpdisplay[0]=l_tmpdate[2]/16; //数据的转换,因我们采用数码管0~9的显示,将数据分开l_tmpdisplay[1]=l_tmpdate[2]&0x0f;l_tmpdisplay[2]=10; //加入"-"l_tmpdisplay[3]=l_tmpdate[1]/16;l_tmpdisplay[4]=l_tmpdate[1]&0x0f;l_tmpdisplay[5]=10;l_tmpdisplay[6]=l_tmpdate[0]/16;l_tmpdisplay[7]=l_tmpdate[0]&0x0f;}}}/******************************************************************//* 定时器0初始化*//******************************************************************/void InitTIMER0(void){TMOD|=0x01;//定时器设置16位TH0=0xef;//初始化值TL0=0xf0;ET0=1;TR0=1;EA=1;}/******************************************************************/ /* 写一个字节*/ /******************************************************************/ void Write_Ds1302_Byte(unsigned char temp){unsigned char i;for (i=0;i<8;i++) //循环8次写入数据{SCK=0;SDA=temp&0x01; //每次传输低字节temp>>=1; //右移一位SCK=1;}}/******************************************************************/ /* 写入DS1302 */ /******************************************************************/ void Write_Ds1302( unsigned char address,unsigned char dat ){RST=0;_nop_();SCK=0;_nop_();RST=1;_nop_(); //启动Write_Ds1302_Byte(address); //发送地址Write_Ds1302_Byte(dat); //发送数据RST=0; //恢复}/******************************************************************/ /* 读出DS1302数据*/ /******************************************************************/ unsigned char Read_Ds1302 ( unsigned char address ){unsigned char i,temp=0x00;RST=0;_nop_();_nop_();SCK=0;_nop_();_nop_();RST=1;_nop_();_nop_();Write_Ds1302_Byte(address);for (i=0;i<8;i++) //循环8次读取数据{if(SDA)temp|=0x80; //每次传输低字节SCK=0;temp>>=1; //右移一位_nop_();_nop_();_nop_();SCK=1;}RST=0;_nop_(); //以下为DS1302复位的稳定时间_nop_();RST=0;SCK=0;_nop_();_nop_();_nop_();_nop_();SCK=1;_nop_();_nop_();SDA=0;_nop_();_nop_();SDA=1;_nop_();_nop_();return (temp); //返回}/******************************************************************/ /* 读时钟数据*/ /******************************************************************/ void Read_RTC(void) //读取日历{unsigned char i,*p;p=read_rtc_address; //地址传递for(i=0;i<7;i++) //分7次读取秒分时日月周年{l_tmpdate[i]=Read_Ds1302(*p);p++;}}/******************************************************************/ /* 设定时钟数据*/ /******************************************************************/ void Set_RTC(void) //设定日历{unsigned char i,*p,tmp;for(i=0;i<7;i++){ //BCD处理tmp=l_tmpdate[i]/10;l_tmpdate[i]=l_tmpdate[i]%10;l_tmpdate[i]=l_tmpdate[i]+tmp*16;}Write_Ds1302(0x8E,0X00);p=write_rtc_address; //传地址for(i=0;i<7;i++) //7次写入秒分时日月周年{Write_Ds1302(*p,l_tmpdate[i]);p++;}Write_Ds1302(0x8E,0x80);}/******************************************************************/ /* 定时器中断函数*/ /******************************************************************/ void tim(void) interrupt 1 using 1//中断,用于数码管扫描{static unsigned char i,num;TH0=0xf5;TL0=0xe0;P0=table[l_tmpdisplay[i]]; //查表法得到要显示数字的数码段switch(i){case 0:LS138A=0; LS138B=0; LS138C=0; break;case 1:LS138A=1; LS138B=0; LS138C=0; break;case 2:LS138A=0; LS138B=1; LS138C=0; break;case 3:LS138A=1; LS138B=1; LS138C=0; break;case 4:LS138A=0; LS138B=0; LS138C=1; break;case 5:LS138A=1; LS138B=0; LS138C=1; break;case 6:LS138A=0; LS138B=1; LS138C=1; break;case 7:LS138A=1; LS138B=1; LS138C=1; break;}i++;if(i==8){i=0;num++;if(10==num) //隔段时间读取1302的数据。

ds1302时钟程序详解,ds1302程序流程图

ds1302时钟程序详解,ds1302程序流程图

ds1302时钟程序详解,ds1302程序流程图(C程序)ds1302时钟程序详解DS1302 的控制字如图2所示。

控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。

数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。

同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

DS1302的寄存器DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表1。

此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。

时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。

DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。

ds1302程序流程图DS1302实时时间流程图4示出DS1302的实时时间流程。

根据此流程框图,不难采集实时时间。

下面结合流程图对DS1302的基本操作进行编程:根据本人在调试中遇到的问题,特作如下说明:DS1302 与微处理器进行数据交换时,首先由微处理器向电路发送命令字节,命令字节最高位MSB(D7)必须为逻辑1,如果D7=0,则禁止写DS1302,即写保护;D6=0,指定时钟数据,D6=1,指定RAM数据;D5~D1指定输入或输出的特定寄存器;最低位L SB(D0)为逻辑0,指定写操作(输入), D0=1,指定读操作(输出)。

ds1302实时时钟程序说明

ds1302实时时钟程序说明
下面是DS1302内部寄存器的地址的说明。
DS1302实时时钟在数码管上进行实时显示的程序
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit rst=P2^4;
sbit io=P2^0;
}
write_ds1302(0x8e,0x80); //进行写保护
}
void read_rtc()
{
uchar i;
for(i=0;i<7;i++)
{
time_data[i]=read_ds1302(read_add[i]);
}
}
void time_pros()
{
disp[0]=time_data[6]%16;//将BCD码(这里与十六进制没有区别)进行十位个位的分离
{
j=time_data[i]/10;//十位5
time_data[i]%=10;//各位8
time_data[i]=time_data[i]+j*16;
}
write_ds1302(0x8e,0x00);//去除写保护
for(i=0;i<7;i++)
{
write_ds1302(write_add[i],time_data[i]);
disp[1]=time_data[6]/16;
disp[2]=17;
disp[3]=time_data[5]%16;
disp[4]=time_data[5]/16;
disp[5]=17;

DS1302时钟芯片实例讲解

DS1302时钟芯片实例讲解

Page 13
Page 14
驱动程序
Page 15
Page 4
DS1302的寄存器:
DS1302有关于日历、时间的寄存器共有12个。其中七个 寄存器(读时81H--8DH,写时80H--8CH),存放的数据 格式是BCD码形式。
Page 5
注意: 注意:
1)、小时寄存器(85H、84H)的位7用来定义DS1302 是运行12小时模式还是24小时模式。为高时是12小时模 式。在12小时模式时,位5为1是下午(PM)。在24小时 模式时,位5是第二个10小时位。 2)、秒寄存器(81H、80H)的位7定义为时钟暂停标志 (CH)。当CH=1时,时钟振荡器停止,DS1302为低能 耗状态,CH=0时,时钟正常运行。 3)、控制寄存器(8FH、8EH)位7为写保护位,其他7 位均置0。在任何对时钟和RAM写操作之前,WP位必须 置0。当WP=1时,写保护位防止对任意寄存器进行写操 作。
Page 11
小时寄存器 1 日寄存器 月寄存器 1 1
星期寄存器 1 年寄存器 1
寄存器名称
D 7 1
D6 RAM/C K 0 0 0 1 1 1 1
D D4 D3 D2 5 A A3 A2 A1 4 0 0 1 0 0 1 1 0 1 0 1 0 … 1 1 1DS1302时钟芯片实例讲解
11-嵌本班--赵晶
DS1302的简介:
Page 2
DS1302外部引脚分配及功能:
X1、X2:32.768KHz晶振接入引脚。 X1、X2:32.768KHz晶振接入引脚。 晶振接入引脚 GND: GND: 接 地。 CE:复位引脚,低电平有效, CE:复位引脚,低电平有效,操作时高电 平。 I/O:数据输入/输出引脚, I/O:数据输入/输出引脚,具有三态功 能。 SCLK:串行时钟输入引脚。 SCLK:串行时钟输入引脚。 Vcc1: 工作电源引脚。 Vcc1: 工作电源引脚。 Vcc2: 备用电源引脚。 Vcc2: 备用电源引脚。

DS1302时钟程序(完整版),液晶显示

DS1302时钟程序(完整版),液晶显示

#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar table0[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; //液晶显示数字0——9代码sbit SCLK=P1^0;sbit DATA=P1^1;sbit CE=P1^2;sbit RS=P2^0;sbit RW=P2^1;sbit EN=P2^2;sbit FB=P0^7;sbit start=P1^4;sbit stop=P1^5;uchar i;/*******************延时n微秒函数*****************/void delaynus(uchar n) //n us延时函数{// uchar i;for(i=n;i>0;i--);}/*******************写数据函数*****************/void write1302(uchar add,uchar dat){CE=0;SCLK=0;CE=1;for(i=0;i<8;i++) //写入地址{DATA=add&0x01;SCLK=1;SCLK=0;add>>=1;}for(i=0;i<8;i++) //写入数据{DATA=dat&0x01;SCLK=1;SCLK=0;dat>>=1;}SCLK=1;CE=0;}/*******************读数据函数*****************/uchar read1302(uchar add){uchar dat;CE=0;SCLK=0;CE=1;for(i=8;i>0;i--) //写入地址{DATA=add&0x01;SCLK=1;SCLK=0;add>>=1;}for(i=8;i>0;i--) //读出数据/********************为神马???**************************/{dat>>=1;if(DATA==1)dat=dat|0x80;SCLK=1;SCLK=0;}SCLK=1;CE=0;return dat;}/*******************DS1302初始化函数*****************/void init1302(){uchar flag;flag=read1302(0x81);if(flag&0x80){write1302(0x8e,0x00);write1302(0x80,0x00);write1302(0x82,(((1/10)<<4)|(1%10)));write1302(0x84,(((20/10)<<4)|(20%10)));write1302(0x86,(((19/10)<<4)|(19%10)));write1302(0x88,(((7/10)<<4)|(7%10)));write1302(0x8a,((2/10)<<4)|(2%10));write1302(0x8c,(((11/10)<<4)|(11%10)));write1302(0x90,0xa5); //充电。

时钟芯片DS1302 的程序(C51程序)

时钟芯片DS1302 的程序(C51程序)

时钟芯片DS1302 的程序(C51程序)模块名称:DS1302.c功能:实时时钟模块时钟芯片型号:DS1302 程序设计:zhaojunjie********************************************************************* /#includesbit T_CLK = P2^7; /*实时时钟时钟线引脚 */ sbit T_IO = P1^4; /*实时时钟数据线引脚 */ sbit T_RST = P1^5; /*实时时钟复位线引脚 */sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;void RTInputByte(uchar); /* 输入 1Byte */uchar RTOutputByte(void); /* 输出?1Byte */void W1302(uchar, uchar);uchar R1302(uchar);void Set1302(uchar *); /* 设置时间 */void Bcd2asc(uchar,uchar *);void Get1302(uchar curtime[]); /* 读取1302当前时间 *//********************************************************************函数名:RTInputByte()功能:实时时钟写入一字节说明:往DS1302写入1Byte数据 (内部函数)入口参数:d 写入的数据返回值:无设计:zhaojunjie********************************************************************* **/void RTInputByte(uchar d){uchar i;ACC = d;for(i=8; i>0; i--){T_IO = ACC0; /*相当于汇编中的 RRC */T_CLK = 1;T_CLK = 0;ACC = ACC >> 1;}}/********************************************************************函数名:RTOutputByte()功能:实时时钟读取一字节说明:从DS1302读取1Byte数据 (内部函数)入口参数:无返回值:ACC设计:zhaojunjie********************************************************************* **/uchar RTOutputByte(void){uchar i;for(i=8; i>0; i--){ACC = ACC >>1; /*相当于汇编中的 RRC */ACC7 = T_IO;T_CLK = 1;T_CLK = 0;}return(ACC);}/********************************************************************函数名:W1302()功能:往DS1302写入数据说明:先写地址,后写命令/数据 (内部函数)调用:RTInputByte() , RTOutputByte()入口参数:ucAddr: DS1302地址, ucData: 要写的数据返回值:无设计:zhaojunjie********************************************************************* **/void W1302(uchar ucAddr, uchar ucDa){T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(ucAddr); /* 地址,命令 */RTInputByte(ucDa); /* 写1Byte数据*/T_CLK = 1;T_RST = 0;}/********************************************************************函数名:R1302()功能:读取DS1302某地址的数据说明:先写地址,后读命令/数据 (内部函数)调用:RTInputByte() , RTOutputByte()入口参数:ucAddr: DS1302地址返回值:ucData :读取的数据设计:zhaojunjie********************************************************************* **/uchar R1302(uchar ucAddr){uchar ucData;T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(ucAddr); /* 地址,命令 */ucData = RTOutputByte(); /* 读1Byte数据 */T_CLK = 1;T_RST = 0;return(ucData);}/********************************************************************函数名:BurstW1302T()功能:往DS1302写入时钟数据(多字节方式)说明:先写地址,后写命令/数据调用:RTInputByte()入口参数:pWClock: 时钟数据地址格式为: 秒分时日月星期年控制8Byte (BCD码)1B 1B 1B 1B 1B 1B 1B 1B返回值:无设计:zhaojunjie********************************************************************* **/void BurstW1302T(uchar *pWClock){uchar i;W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(0xbe); /* 0xbe:时钟多字节写命令 */for (i = 8; i>0; i--) /*8Byte = 7Byte 时钟数据 + 1Byte 控制*/{RTInputByte(*pWClock); /* 写1Byte数据*/pWClock++;}T_CLK = 1;T_RST = 0;}/********************************************************************函数名:BurstR1302T()功能:读取DS1302时钟数据说明:先写地址/命令,后读数据(时钟多字节方式)调用:RTInputByte() , RTOutputByte()入口参数:pRClock: 读取时钟数据地址格式为: 秒分时日月星期年7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B返回值:无设计:zhaojunjie********************************************************************* **/void BurstR1302T(uchar *pRClock){uchar i;T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(0xbf); /* 0xbf:时钟多字节读命令 */for (i=8; i>0; i--){*pRClock = RTOutputByte(); /* 读1Byte数据 */pRClock++;}T_CLK = 1;}/********************************************************************函数名:BurstW1302R()功能:往DS1302寄存器数写入数据(多字节方式)说明:先写地址,后写数据(寄存器多字节方式)调用:RTInputByte()入口参数:pWReg: 寄存器数据地址返回值:无设计:zhaojunjie********************************************************************* **/void BurstW1302R(uchar *pWReg){uchar i;W1302(0x8e,0x00); /* 控制命令,WP=0,写操作*/T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(0xfe); /* 0xbe:时钟多字节写命令*/for (i=31; i>0; i--) /* 31Byte 寄存器数据 */{RTInputByte(*pWReg); /* 写1Byte数据*/pWReg++;}T_CLK = 1;T_RST = 0;}/********************************************************************函数名:BurstR1302R()功能:读取DS1302寄存器数据说明:先写地址,后读命令/数据(寄存器多字节方式)调用:RTInputByte() , RTOutputByte()入口参数:pRReg: 寄存器数据地址返回值:无设计:zhaojunjie********************************************************************* **/void BurstR1302R(uchar *pRReg){uchar i;T_CLK = 0;T_RST = 1;RTInputByte(0xff); /* 0xff:时钟多字节读命令 */for (i=31; i>0; i--) /*31Byte 寄存器数据 */{*pRReg = RTOutputByte(); /* 读1Byte数据 */pRReg++;}T_CLK = 1;T_RST = 0;}/********************************************************************函数名:Set1302()功能:设置初始时间说明:先写地址,后读命令/数据(寄存器多字节方式)调用:W1302()入口参数:pClock: 设置时钟数据地址格式为: 秒分时日月星期年7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B返回值:无设计:zhaojunjie********************************************************************* **/void Set1302(uchar *pClock){uchar i;uchar ucAddr = 0x80;W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/for(i =7; i>0; i--){W1302(ucAddr,*pClock); /* 秒分时日月星期年*/pClock++;ucAddr +=2;}W1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/}/********************************************************************函数名:Get1302()功能:读取DS1302当前时间说明:调用:R1302()入口参数:ucCurtime: 保存当前时间地址。

超详细的ds1302使用说明及其例程

超详细的ds1302使用说明及其例程
允许写保护允许写保护十六进制转十禁止写保秒位初始分钟初始化51单片机综合学习系统之单片机综合学习系统之ds1302时钟应用篇时钟应用篇电子制作电子制作2008年需引用请注明出处需引用请注明出处年10月月站长原创如站长原创如大家好通过以前的学习我们已经对51单片机综合学习系统的使用方法及学习方式有所了解与熟悉学会了使用ad模数转换的基本知识体会到了综合学习系统的易用性与易学性这一期我们将一起学习ds1302时钟的基本原理与应用实例
DS1302时钟芯片简介
DS1302是 DALLAS 公司推出的涓流充电时钟芯片,内含一个实时时钟/日历和31字节静 态 RAM,可以通过串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、 星期、月、年的信息,每个月的天数和闰年的天数可自动调整,时钟操作可通过 AM/PM 标 志位决定采用24或12小时时间格式。DS1302与单片机之间能简单地采用同步串行的方式进 行通信,仅需三根 I/O 线:复位(RST)、I/O 数据线、串行时钟(SCLK)。时钟/RAM 的读 /写数据以一字节或多达31字节的字符组方式通信。DS1302工作时功耗很低,保持数据和时 钟信息时,功耗小于1mW。
Write1302 (WRITE_PROTECT,0x80); 允许写保护
}
//十六进制转十
//禁止写保 //秒位初始 //分钟初始化
// //
51单片机综合学习系统之 DS1302时钟应用篇 《电子制作》2008年10月 站长原创,如 需引用请注明出处
大家好,通过以前的学习,我们已经对51单片机综合学习系统的使用方法及学习方式有 所了解与熟悉,学会了使用 AD 模数转换的基本知识,体会到了综合学习系统的易用性与易 学性,这一期我们将一起学习 DS1302时钟的基本原理与应用实例。

DS1302原理及程序说明

DS1302原理及程序说明

DS1302原理及程序说明DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31字节静态RAM ,通过简单的串行接口与单片机进行通信。

实时时钟/日历电路提供秒、分、时、日、日期、月、年的信息,每月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM 指示决定采用24 或12 小时格式。

DS1302 与单片机之间能简单地采用同步串行的方式进行,DS1302的引脚命名如图1-1所示。

通信仅需用到三根信号线:(1)CE 片选,(2)I/O 数据线,(3)SCLK 串行时钟,DS1302与CPU 的连接如图1-2所示。

时钟/RAM 的读/写数据以一个字节或多字节的字符组方式通信,DS1302工作时功耗很低,保持数据和时钟信息时功率小于1mW 。

DS1302具有双电源管脚,用于主电源和备份电源供应Vcc1,为可编程涓流充电电源附加七个字节存储器,它广泛应用于电话传真便携式仪器以及电池供电的仪器仪表等产品领域。

DS1302主要的性能指标如下:实时时钟具有能计算2100 年之前的秒、分、时、日、日期、星期、月、年的能力,还有闰年调整的能力31× 8 位暂存数据存储RAM 串行I/O 口方式,使得管脚数量最少宽范围工作电压2.0~ 5.5V工作电流2.0V 时,小于300nA读/写时钟或RAM 数据时有两种传送方式:单字节传送和多字节传送字符组方式8 脚DIP 封装或可选的8 脚SOIC 封装根据表面装配简单3 线接口与TTL 兼容Vcc=5V 。

DS1302的读写模式工作时序如图1-3和图1-4所示。

图1-3 单字节读模式图1-4 单字节写模式注:在多字节模式下,SCLK 发出同步脉冲,CS 须持续保持高电平直到多字节操作结束,图1-1 DS1302引脚图1-2 DS1302与CPU 接口DS1302内部寄存器的地址定义如表1-1所示。

表1-1 寄存器的地址及定义实验说明1. DS1302与51单片机的连接IO ——P2.7:串行数据输入/输出引脚SCLK ——P2.6:串行时钟引脚CE ——P2.4:片选CE2. LCD 与单片机连接;************************************************************************* ; LCD Module LMB1602 与单片机连接:;************************************************************************* ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ;Vss Vdd V o RS R/W E D0 D1 D2 D3 D4 D5 D6 D7 BLA BLK ; 0V +5V 0V P32 P33 P34 ---------------- P1[0..7] ---------------- +5V 0V;*************************************************************************3. LCD 显示功能说明LCD1602显示格式如图1-5所示。

DS1302 时钟电路

DS1302 时钟电路

时钟电路1应用:1.1需要显示时钟及日期或实现时钟控制的电子设备。

1.2本电路在HGT2110、HGT3101、HDM2100、HDM3200中成功应用。

2特性:2.1年、月、日、时、分、秒、星期的实时走时;2.2可设置为12小时制或24小时制走时;2.3日历时钟数据可读写,可启动写保护;2.4可接入3V电池,断电后由电池供电走时,电池供电通常可持续一年以上;2.5可对电池设置充电参数。

3核心部件:3.1DS1302,DIP8 或SOP8封装(推荐)。

4外围关键元件:4.132768Hz晶体振荡器;4.23V电池。

5设计注意事项:5.1晶体振荡器必须采用32768Hz,其引脚不得接入其它元件;5.2晶振引脚具有高阻抗特性,印制板漏电会导致停振。

设计时引脚应尽量短,远离周边元件或导线,并应大于2mm;5.3此器件对潮湿、低温敏感,推荐线路进行防潮处理;5.4不推荐使用大容量电容替代电池,电容引脚易与其它线路板接通造成其它线路板元件损坏。

6软件设计要点:6.1上电初始化必须设置为充电;6.2上电后对秒进行操作,可避免时钟锁定;6.3非写入数据操作后启动写保护;7原理图:7.1见DS1302.Ddb文件;8引脚说明或时序图:8.1见DS1302.pdf文件;9主要指标:10C语言例程:10.1本例在HDM3200消防电话总机中应用,CPU为ATmega32L ,工作频率为4MHz。

//************************************************************************// // 日历时钟DS1302公用变量说明 // // -------------------------------------------------------------------- // // uchar cale[7] 下标对应 0 1 2 3 4 5 6 // // year month day hour minute second week // // 年月日时分秒星期 // // write_cale(why) 将cale[]中指定的日期或时间写入dallas中 // // get_cale(why); 获得由why指定的日期或时钟,并且赋值给cale[why] // // why--指定年、周、月、日、时、分、秒中的一个, why可取year或 // // month或day或hour或minute或second或week // //************************************************************************// // -------------------------------------------------------------------- // // 充电设置 //// -------------------------------------------------------------------- // // 使用bttay_charger(uchar charge_set)函数,其中 // // charge_set: 0--不充电 4.3V时 0mA 0mA // // 1--2K充电 4.3V时 1.8mA 1.5mA // // 2--4K充电 4.3V时 0.9mA 0.8mA // // 3--8K充电 4.3V时 0.45mA 0.4mA // // 默认使用1只二极管建议使用4K电阻(0.9mA) // // -------------------------------------------------------------------- // //************************************************************************////DS1302时钟端口定义(以下端口可根据实际使用改变)-------------------------// #define SET_DS_RST SETBIT(PORTD,1) //ret=1#define CLK_DS_RST CLRBIT(PORTD,1) //ret=0#define SET_DS_SCL SETBIT(PORTB,7) //scl=1#define CLK_DS_SCL CLRBIT(PORTB,7) //scl=0#define SET_DS_DAT SETBIT(PORTB,2) //data=1#define CLK_DS_DAT CLRBIT(PORTB,2) //data=0#define IN_DS_DAT CLRBIT(DDRB,2) //data port is input#define OUT_DS_DAT SETBIT(DDRB,2) //data port is output#define CHK_DS_DAT CHKBIT(PINB,2) //get data#define dec_dallas(x) ((x/10)*16+x%10) //将10进制数转换为dallas数#define dallas_dec(x) ((x/16)*10+x%16) //将dallas数转换为10进制数//日历时钟全局变量定义---------------------------------------------------// unsigned char cale[7]; //日期缓存数据,下标用以下宏表示#define year 0 //年#define month 1 //月#define day 2 //日#define hour 3 //时#define minute 4 //分#define second 5 //秒#define week 6 //星期//**********************************************************//// DS1302日历时钟电路程序 //// ------------------------------------------------------ //// 涓流充电:read_dallas(0x91) write_dallas(0x90) //// 控制:read_dallas(0x8f) write_dallas(0x8e) //// 年:read_dallas(0x8d) write_dallas(0x8c) //// 周:read_dallas(0x8B) write_dallas(0x8a) //// 月:read_dallas(0x89) write_dallas(0x88) //// 日:read_dallas(0x87) write_dallas(0x86) //// 时:read_dallas(0x85) write_dallas(0x84) //// 分:read_dallas(0x83) write_dallas(0x82) //// 秒:read_dallas(0x81) write_dallas(0x80) //// ----------------------------------------------------- //// 内有31字节RAM 存储器,掉电失去: //// write_dallas(0xc0 - 0xfc) 偶数写 //// read_dallas(0xc1 - 0xfd) 奇数读 ////**********************************************************////**********************************************************//// 数据写入时钟芯片DS1302 //// ------------------------------------------------------ //// 功能:将数据ch写入地址为rtc_add的存储单元中 //// 输入参数:地址----uchar rtc_add //// 数据----uchar ch ////**********************************************************//void write_dallas(uchar rtc_add,uchar ch){unsigned char i;OUT_DS_DAT; //set DAT outputCLK_DS_SCL; //CLK=0SET_DS_RST; //RST=1for(i=0;i<8;i++){if(rtc_add & (0x01<<i)) SET_DS_DAT; //DAT=1else CLK_DS_DAT; //DAT=0SET_DS_SCL; //CLK=1CLK_DS_SCL; //CLK=0}for(i=0;i<8;i++){if(ch & (0x01<<i)) SET_DS_DAT; //DAT=1else CLK_DS_DAT; //DAT=0SET_DS_SCL; //CLK=1CLK_DS_SCL; //CLK=0}CLK_DS_RST; //RST=0 IN_DS_DAT; //set DAT input}g//**********************************************************//// 从时钟芯片DS1302 读出数据 //// ------------------------------------------------------ //// 功能:将数据ch写入由地址为rtc_add存储单元中读出数据 //// 输入参数:地址----uchar rtc_add //// 返回参数:数据----uchar read_dallas() ////**********************************************************// unsigned char read_dallas(unsigned char rtc_add){unsigned char i,j;j=0;OUT_DS_DAT; //set DAT outputCLK_DS_SCL; //CLK=0SET_DS_RST; //RST=1for(i=0;i<8;i++) {if(rtc_add & (0x01<<i)) SET_DS_DAT; //DAT=1else CLK_DS_DAT; //DAT=0SET_DS_SCL; //CLK=1CLK_DS_SCL; //CLK=0}IN_DS_DAT; //set DAT inputSET_DS_DAT; //DAT=1 置为上拉电阻for(i=0;i<8;i++) {if(CHK_DS_DAT) j|=0x01<<i; //j=DATSET_DS_SCL; //CLK=1CLK_DS_SCL; //CLK=0}CLK_DS_RST; //RST=0;return(j);}//**********************************************************//// 设置DS1302日期或时间 //// ------------------------------------------------------ //// 功能:将cale[]中指定的日期或时间设置到DS1302中 //// 输入参数:why--指定年、周、月、日、时、分、秒中的一个 //// 即year、week、month、day、hour、minute、second //// 以下例程将8点30分10秒写入DS1302: //// cale[hour]=8; //// cale[minute]=30; //// cale[second]=10; //// for(i=hour; i<=second; i++) write_cale(i); ////**********************************************************// void write_cale(uchar why){uchar d;write_dallas(0x8e,0x00); //关闭写保护d=dec_dallas(cale[why]);if(!why) write_dallas(0x8c,d); //写年else if(why<week) write_dallas(0x80+(10-why*2),d); //写月日时分秒else write_dallas(0x8a,d); //写星期write_dallas(0x8e,0x80); //启动写保护}//**********************************************************//// 获得DS1302指定的日期或时间 //// ------------------------------------------------------ //// 功能:将DS1302中指定的日期或时间赋给cale[why] //// 输入参数:why--指定年、周、月、日、时、分、秒中的一个 //// 即year、week、month、day、hour、minute、second //// 以下例程获取DS102当前时间,并将时间写入cale[]中: //// for(i=hour; i<=second; i++) get_cale(i); ////**********************************************************//void get_cale(uchar why){uchar d;if(!why) d=read_dallas(0x8d); //读年else if(why<week) d=read_dallas(139-(why*2)); //读月日时分秒 else d=read_dallas(0x8b); //读周cale[why]=dallas_dec(d);}//**********************************************************//// 快速获得月、日、时、分、秒 //// ------------------------------------------------------ //// 功能:获取DS1302当前月、日、时、分、秒写入cale[] ////**********************************************************//void fast_get_cale(void){uchar i;for(i=1;i<6;i++) cale[i]=dallas_dec(read_dallas(139-(i*2)));}//**********************************************************//// 获得秒 //// ------------------------------------------------------ //// 功能:直接返回当前秒 //// 返回参数:当前秒—get_second() ////**********************************************************//unsigned char get_second(void) {return dallas_dec(read_dallas(0x81));}//**********************************************************//// 电池充电设置 (应在电路上电时进行初始化设置) //// ------------------------------------------------------ //// 功能:对电池充电方式进行选择或设置 //// 输入参数:charge_set (取值见下表) //// 使用read_dallas(0x91) write_dallas(0x90) 进行设置 //// ------------------------------------------------------ //// 关于充电寄存器: //// D7 D6 D5 D4 D3 D2 D1 D0 //// -------------------------------------------------- //// | 充电设置1010 | 二极管设置|充电限流电阻| //// -------------------------------------------------- //// | 1010: 使能充电 |01: 接通1D |00:无 01:2K | //// | |10: 接通2D |10:4K 11:8K | //// -------------------------------------------------- //// ------------------------------------------------------- //// | 串联电阻 | 1只二极管 | 2只二极管 | //// charge_set: 0--不充电 4.3V时 0mA 0mA //// charge_set: 1--2K充电 4.3V时 1.8mA 1.5mA //// charge_set: 2--4K充电 4.3V时 0.9mA 0.8mA //// charge_set: 3--8K充电 4.3V时 0.45mA 0.4mA //// ------------------------------------------------------ //// 默认使用1只二极管建议使用4K电阻(0.9mA) ////**********************************************************//void bttay_charger(uchar charge_set){write_dallas(0x8e,0x00); //关闭写保护if(!charge_set) write_dallas(0x90,0x00);else write_dallas(0x90,(0xa4|charge_set));write_dallas(0x8e,0x80); //启动写保护}//主程序中应用方法Void main(void){……//时钟初始化bttay_charger(2); //电池充电初始化:0.9mA充电 write_dallas(0x8e,0x00); //关闭写保护write_dallas(0x90,(0xa4|2));write_dallas(0x8e,0x80); //启动写保护get_rili(second);if(rili[second]>59) //时钟自锁时去除锁保护{rili[second]=0;write_rili(second);}get_rili(year); //获得年fast_get_rili(); //获得年月日时分秒……while(1){……}}编著:王立新日期:2009年5月。

DS1302程序及连接图

DS1302程序及连接图

/****************************************************************************** ** 标题: 试验数码管显示时钟**** 通过本例程了解DS1302时钟芯片的基本原理和使用,理解并掌握DS1302时钟芯片** 驱动程序的编写以及实现数字字符在数码管中的显示。

** 注意:JP1302跳线冒要短接。

** 请学员认真消化本例程,懂DS1302在C语言中的操作******************************************************************************** */#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#include <intrins.h>sbit SCK=P3^6; //时钟sbit SDA=P3^4; //数据sbit RST = P3^5;// DS1302复位sbit LS138A=P2^2;sbit LS138B=P2^3;sbit LS138C=P2^4;bit ReadRTC_Flag;//定义读DS1302标志unsigned char l_tmpdate[7]={0,0,12,15,5,3,8};//秒分时日月周年08-05-15 12:00:00unsigned char l_tmpdisplay[8];code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年最低位读写位code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴数码管0-9 '-' '熄灭‘表/******************************************************************//* 函数声明*//******************************************************************/void Write_Ds1302_byte(unsigned char temp);void Write_Ds1302( unsigned char address,unsigned char dat );unsigned char Read_Ds1302 ( unsigned char address );void Read_RTC(void);//read RTCvoid Set_RTC(void); //set RTCvoid InitTIMER0(void);//inital timer0/******************************************************************//* 主函数*//******************************************************************/void main(void){InitTIMER0(); //初始化定时器0Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽while(1){if(ReadRTC_Flag){ReadRTC_Flag=0;Read_RTC();l_tmpdisplay[0]=l_tmpdate[2]/16; //数据的转换,因我们采用数码管0~9的显示,将数据分开l_tmpdisplay[1]=l_tmpdate[2]&0x0f;l_tmpdisplay[2]=10; //加入"-"l_tmpdisplay[3]=l_tmpdate[1]/16;l_tmpdisplay[4]=l_tmpdate[1]&0x0f;l_tmpdisplay[5]=10;l_tmpdisplay[6]=l_tmpdate[0]/16;l_tmpdisplay[7]=l_tmpdate[0]&0x0f;}}}/******************************************************************//* 定时器0初始化*//******************************************************************/void InitTIMER0(void){TMOD|=0x01;//定时器设置16位TH0=0xef;//初始化值TL0=0xf0;ET0=1;TR0=1;EA=1;}/******************************************************************/ /* 写一个字节*/ /******************************************************************/ void Write_Ds1302_Byte(unsigned char temp){unsigned char i;for (i=0;i<8;i++) //循环8次写入数据{SCK=0;SDA=temp&0x01; //每次传输低字节temp>>=1; //右移一位SCK=1;}}/******************************************************************/ /* 写入DS1302 */ /******************************************************************/ void Write_Ds1302( unsigned char address,unsigned char dat ){RST=0;_nop_();SCK=0;_nop_();RST=1;_nop_(); //启动Write_Ds1302_Byte(address); //发送地址Write_Ds1302_Byte(dat); //发送数据RST=0; //恢复}/******************************************************************/ /* 读出DS1302数据*/ /******************************************************************/ unsigned char Read_Ds1302 ( unsigned char address ){unsigned char i,temp=0x00;RST=0;_nop_();_nop_();SCK=0;_nop_();_nop_();RST=1;_nop_();_nop_();Write_Ds1302_Byte(address);for (i=0;i<8;i++) //循环8次读取数据{if(SDA)temp|=0x80; //每次传输低字节SCK=0;temp>>=1; //右移一位_nop_();_nop_();_nop_();SCK=1;}RST=0;_nop_(); //以下为DS1302复位的稳定时间_nop_();RST=0;SCK=0;_nop_();_nop_();_nop_();_nop_();SCK=1;_nop_();_nop_();SDA=0;_nop_();_nop_();SDA=1;_nop_();_nop_();return (temp); //返回}/******************************************************************/ /* 读时钟数据*/ /******************************************************************/ void Read_RTC(void) //读取日历{unsigned char i,*p;p=read_rtc_address; //地址传递for(i=0;i<7;i++) //分7次读取秒分时日月周年{l_tmpdate[i]=Read_Ds1302(*p);p++;}}/******************************************************************/ /* 设定时钟数据*/ /******************************************************************/ void Set_RTC(void) //设定日历{unsigned char i,*p,tmp;for(i=0;i<7;i++){ //BCD处理tmp=l_tmpdate[i]/10;l_tmpdate[i]=l_tmpdate[i]%10;l_tmpdate[i]=l_tmpdate[i]+tmp*16;}Write_Ds1302(0x8E,0X00);p=write_rtc_address; //传地址for(i=0;i<7;i++) //7次写入秒分时日月周年{Write_Ds1302(*p,l_tmpdate[i]);p++;}Write_Ds1302(0x8E,0x80);}/******************************************************************/ /* 定时器中断函数*/ /******************************************************************/ void tim(void) interrupt 1 using 1//中断,用于数码管扫描{static unsigned char i,num;TH0=0xf5;TL0=0xe0;P0=table[l_tmpdisplay[i]]; //查表法得到要显示数字的数码段switch(i){case 0:LS138A=0; LS138B=0; LS138C=0; break;case 1:LS138A=1; LS138B=0; LS138C=0; break;case 2:LS138A=0; LS138B=1; LS138C=0; break;case 3:LS138A=1; LS138B=1; LS138C=0; break;case 4:LS138A=0; LS138B=0; LS138C=1; break;case 5:LS138A=1; LS138B=0; LS138C=1; break;case 6:LS138A=0; LS138B=1; LS138C=1; break;case 7:LS138A=1; LS138B=1; LS138C=1; break;}i++;if(i==8){i=0;num++;if(10==num) //隔段时间读取1302的数据。

基于STM32的DS1302时钟模块驱动程序(详细)

基于STM32的DS1302时钟模块驱动程序(详细)

基于STM32的DS1302时钟模块驱动程序(详细)⽬录1.项⽬概述2.DS1032的数据⼿册解析2.1 DS1302的引脚介绍2.2 DS1302的通讯协议及时序2.3 DS1302的相关寄存器3.程序代码及其注释4.结果演⽰5.附录:7针0.96⼨OLED屏驱动代码(SPI驱动)1.项⽬概述本程序采⽤的主控芯⽚为STM32F103RCT6,通过主控芯⽚驱动DS1302时钟模块,并将其实时时间显⽰在7针0.96⼨OLED屏上。

使⽤STM32的普通IO⼝模拟DS1302的通信时序,使⽤STM32的SPI外设驱动OLED屏。

下⾯从DS1302的数据⼿册开始完成整个项⽬。

2.DS1302数据⼿册解析2.1DS1302引脚介绍VCC1,VCC2是电源引脚,VCC1是主供电引脚,VCC2接备⽤电池,当主供电电源电量不⾜或者断电时,备⽤电池会通过VCC2及时供电,保证时钟模块在主供电引脚断电后任然会正常计时。

GND是地引脚。

X1,X2是有关晶振的引脚,不做深究。

CE引脚是输⼊引脚,在单⽚机从DS1302读取数据或者向其写⼊数据时,CE引脚必须配置为⾼电平。

在芯⽚内部连接有40K下拉电阻。

I/O引脚充当双向数据引脚,即数据的发送和接收都在这条线上完成。

SCLK是同步时钟引脚,控制I/O引脚上数据的接收和发送。

2.2 DS1302的通讯协议及时序指令字节启动每次的数据传输,上图说明了指令字节的构造。

①位7必须为逻辑1,位7为逻辑0时指令会失效。

②我们使⽤的不是RAM当中的寄存器及数据,故位6应该为逻辑0。

③位1到位5为寄存器地址。

④位0为逻辑0时表明要往指定寄存器⾥⾯写数据,为逻辑1时要从指定寄存器⾥⾯读出数据。

指令字节的传输总是从位0(LSB)开始传输。

上图是ds1302通信时序图。

1.CE和时钟控制。

将CE置⾼将开启数据传输,CE输⼊提供俩个功能,⾸先CE开启了通信数据进⼊移位寄存器的通路,其次CE提供了⼀个可以终⽌单个字节或者多个字节的数据传输。

DS1302时钟芯片C51源代码源程序

DS1302时钟芯片C51源代码源程序

DS1302时钟芯片C51源代码源程序DS1302--- 51C语言代码,头文件与对应C代码已分离开,直接可用(自己写,绝对可用。

)其中星期几能直接由日期按公式推算出来,time.week=(time.year/100)/4-2*(time.year/100)+(time.year%100)+(time.year%100)/4+26*(tim e.month+1)/10 +time.day-1;(详情请搜:蔡乐公式)///////////////////////////////////////////////////////////////DS1302头文件:#ifndef _ds1302_h_#define _ds1302_h_#define uchar unsigned char#define uint unsigned int#define ulong unsigned long#define u32 unsigned long intsbit sdinn = P2^6;sbit sclkk = P2^5;sbit cee = P2^7;#define second_w 0x80#define second_r 0x81#define minute_w 0x82#define minute_r 0x83#define hour_w 0x84#define hour_r 0x85#define day_w 0x86#define day_r 0x87#define month_w 0x88#define month_r 0x89#define year_w 0x8c#define year_r 0x8d#define week_w 0x8a#define week_r 0x8b#define protect_w 0xc0#define protect_r 0xc1#define clock_base_w 0xc2#define clock_base_r 0xc3#define clock_state_w 0xcc#define clock_state_r 0xcd#define D_protect 0x77typedef struct{uint year;uint month;uint day;uint hour;uint minute;uint second;uint week;} Time_info;void DS1302_Writebyte(uchar dat);void time_write2DS1302(Time_info Time);void time_read_from_DS1302(Time_info *Time);uchar DS1302_Readbyte();void DS1302Write(uchar cmd, uchar dat);uchar DS1302Read(uchar cmd);void Init_DS1302(void);void display_date(unsigned char X,unsigned char Y,Time_info Read_T); void writeDate2DS1302(Time_info Time);void time_HMS2DS1302(Time_info Time);void Alarm_respond();void sendtime2computer();#endif///////////////////////////////////////////////////////////DS1302-C代码:#include "option.h"xdata uchar trans_buf;extern xdata uchar Date_Index;extern xdata uchar Time_Index;extern xdata uchar Write_date_buff[15];extern xdata uchar Alarm_buff[7];extern xdata uchar Alarm_arrive;extern xdata uchar arriveminute;extern xdata uchar Alarm_state;extern xdata Time_info Read_Time;xdata uchar tiao_buff[30];xdata uint hour,minute,second;xdata uchar old_second=250;void delay(unsigned long int i){while(i--);}void time_write2DS1302(Time_info Time)DS1302Write(0x8e,0x00);//写保护关trans_buf = ((Time.year%100/10)<<4)+((Time.year%10)&0X0F); // 写入年DS1302Write(year_w, trans_buf);trans_buf = (((Time.month%100/10)<<4)&0x10) + ((Time.month%10)&0X0F); //写入月DS1302Write(month_w, trans_buf);trans_buf = (((Time.day%100/10)<<4)&0x30) + ((Time.day%10)&0X0F);//写入日DS1302Write(day_w, trans_buf);trans_buf = (((Time.hour%100/10)<<4)&0x30)+((Time.hour%10)&0X0F);//写入时DS1302Write(hour_w, trans_buf);trans_buf = (((Time.minute%100/10)<<4)&0x70) + ((Time.minute%10)&0X0F); //写入分DS1302Write(minute_w, trans_buf);trans_buf = (((Time.second%100/10)<<4)&0x70) + ((Time.second%10)&0X0F); //写入秒DS1302Write(second_w, trans_buf);trans_buf = Time.week%7; //写入星期DS1302Write(week_w, trans_buf);DS1302Write(0x8e,0x80); //开写保护}void writeDate2DS1302(Time_info Time){DS1302Write(0x8e,0x00);//写保护关trans_buf = ((Time.year%100/10)<<4)+((Time.year%10)&0X0F); // 写入年DS1302Write(year_w, trans_buf);trans_buf = (((Time.month%100/10)<<4)&0x10) +((Time.month%10)&0X0F); //写入月DS1302Write(month_w, trans_buf);trans_buf = (((Time.day%100/10)<<4)&0x30) + ((Time.day%10)&0X0F);//写入日DS1302Write(day_w, trans_buf);Time.week = (int)(Time.year/100)/4-(int)2*(Time.year/100)+(int)(Time.year%100)+(int)(Time.year%100)/4+(int)26*(Time.mo nth+1)/10+(int)Time.day-1;// printf("--week:%5d--",Time.week);Time.week %= 7;if(Time.week == 0) Time.week = 7;trans_buf = Time.week; //写入星期DS1302Write(week_w, trans_buf);DS1302Write(0x8e,0x80); //开写保护}void time_HMS2DS1302(Time_info Time){DS1302Write(0x8e,0x00);//写保护关trans_buf = (((Time.hour%100/10)<<4)&0x30)+((Time.hour%10)&0X0F);//写入时DS1302Write(hour_w, trans_buf);trans_buf = (((Time.minute%100/10)<<4)&0x70) + ((Time.minute%10)&0X0F); //写入分DS1302Write(minute_w, trans_buf);trans_buf = (((Time.second%100/10)<<4)&0x70) + ((Time.second%10)&0X0F); //写入秒DS1302Write(second_w, trans_buf);DS1302Write(0x8e,0x80); //开写保护}void time_read_from_DS1302(Time_info *Time){Time->year = DS1302Read(year_r);Time->month = DS1302Read(month_r);Time->day = DS1302Read(day_r);Time->hour = DS1302Read(hour_r);Time->minute = DS1302Read(minute_r);Time->second = DS1302Read(second_r);Time->week = DS1302Read(week_r);Time->year = 2000+((Time->year>>4)*10)+(Time->year&0x0f);Time->month = ((Time->month>>4)*10) + (Time->month&0x0f);Time->day = (Time->day>>4)*10 + (Time->day&0x0f);Time->hour = (Time->hour>>4)*10 + (Time->hour&0x0f);Time->minute = ((Time->minute>>4)*10) + (Time->minute&0x0f);Time->second = (Time->second>>4)*10 + (Time->second&0x0f); }void DS1302_Writebyte(uchar dat){uchar i;sclkk = 0;delay(300);for(i = 0; i < 8; i++){sdinn = dat & 0x01;delay(90);sclkk = 1;delay(180);sclkk = 0;dat >>= 1;}}uchar DS1302_Readbyte(){uchar i, dat = 0;delay(90);for(i = 0; i < 8; i++){dat >>=1;if(sdinn)dat |= 0x80;sclkk = 1;delay(60);sclkk = 0;delay(60);}sdinn = 0;return dat;}void DS1302Write(uchar cmd, uchar dat) {cee = 0;sclkk = 0;cee = 1;DS1302_Writebyte(cmd);DS1302_Writebyte(dat);sclkk = 1;cee = 0;}uchar DS1302Read(uchar cmd) {uchar dat = 0;cee = 0;sclkk = 0;cee = 1;DS1302_Writebyte(cmd);dat = DS1302_Readbyte();sclkk = 1;cee = 0;return dat;}void Init_DS1302(void){Time_info time;uchar init_state;DS1302Write(0x8e,0x00);//写保护关init_state = DS1302Read(protect_r); DS1302Write(0x8e,0x80); //开写保护if(init_state != D_protect){time.year = 2014;time.month = 12;time.day = 5;time.hour = 18;time.minute = 57;time.second = 50; //日期换算为星期[c/4]-2c+y+[y/4]+[26(m+1)/10]+d-1time.week = (time.year/100)/4-2*(time.year/100)+(time.year %100)+(time.year%100)/4+26*(time.month+1)/10+time.da y-1;time.week %= 7;if(time.week == 0) time.week = 7;time_write2DS1302(time);DS1302Write(0x8e,0x00);//写保护关DS1302Write(protect_w,D_protect); //初始化一次标示DS1302Write(0x8e,0x80); //开写保护}DS1302Write(0x8e,0x00);//写保护关Alarm_buff[0] = DS1302Read(clock_base_r+0);Alarm_buff[1] = DS1302Read(clock_base_r+2);Alarm_buff[2] = DS1302Read(clock_base_r+4);Alarm_buff[3] = DS1302Read(clock_base_r+6);Alarm_buff[4] = DS1302Read(clock_base_r+8);Alarm_buff[5] = DS1302Read(clock_base_r+10);Alarm_state = DS1302Read(clock_state_r);DS1302Write(0x8e,0x80); //开写保护}void display_date(unsigned char X,unsigned char Y,Time_info Read_T) {xdata char dis_info[12];sprintf(dis_info, "%04d/%02d/%02d", (int)Read_T.year, (int) Read_T.month, (int)Read_T.day);LCD_write_english_string(X,Y,dis_info);sprintf(dis_info, "%02d/%02d/%02d", (int)Read_T.hour, (int) Read_T.minute, (int)Read_T.second);LCD_write_english_string(X+6,Y+1,dis_info);sprintf(dis_info, "Week:%d", (int)Read_T.week);LCD_write_english_string(X+12,Y+2,dis_info);}void Alarm_respond(){hour = (uint)Alarm_buff[0]*10+Alarm_buff[1];minute = (uint)Alarm_buff[2]*10+Alarm_buff[3];second = (uint)Alarm_buff[4]*10+Alarm_buff[5];if(Alarm_state==1){time_read_from_DS1302(&Read_Time);if((old_second < Read_Time.second)||(Read_Time.second==0)){if(arriveminute!=Read_Time.minute) Alarm_arrive = 0;if((Read_Time.hour == hour)&&(Read_Time.minute== minute)&&(Read_Time.second == second)){Alarm_arrive = 1;arriveminute = Read_Time.minute;}}old_second = Read_Time.second;}}void sendtime2computer(){time_read_from_DS1302(&Read_Time);printf("time%04d/%02d/%02d/%02d:%02d:%02d", Read_Time.year, Read_Time.month, Read_Time.day, Read_Time.hour, Read_Time.minute,Read_Time.second);printf("%d--\n",Read_Time.week);}。

DS1302时钟基础使用(含代码)

DS1302时钟基础使用(含代码)

DS1302时钟基础使⽤(含代码)了解其管脚X1 X2 32.768KHz 晶振管脚GND 地RST 复位脚I/O 数据输⼊/输出引脚,具有三态SCLK 串⾏时钟Vcc1,Vcc2(备⽤电源供电)电源供电管脚DS1302 的寄存器及⽚内RAM控制寄存器⽤于存放DS1302的控制命令字,DS1302的RST引脚回到⾼电平后写⼊的第⼀个字就为控制命令。

它⽤于对DS1302读写过程进⾏控制,它的格式如下:D7:固定为1D6:RAM/CK位,=1⽚内RAM,=0⽇历、时钟寄存器选择位。

D5~D1:地址位,⽤于选择进⾏读写的⽇历、时钟寄存器或⽚内RAM。

对⽇历、时钟寄存器或⽚内RAM的选择见表。

D0:读写选择,=0写,=1读⽇历时钟寄存器写保护寄存器⽤于初始化时钟void Ds1302Init(){uchar n;Ds1302Write(0x8E,0X00); //禁⽌写保护,就是关闭写保护功能for (n=0; n<7; n++)//写⼊7个字节的时钟信号:分秒时⽇⽉周年{Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);}Ds1302Write(0x8E,0x80); //打开写保护功能}寄存器说明数据输出输⼊在控制指令字输⼊后的下⼀个SCLK时钟的上升沿时,数据被写⼊DS1302,数据输⼊从低位即位0开始。

同样,在紧跟8位的控制指令字后的下⼀个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到⾼位7。

单字节读和写DS1302是通过SPI串⾏总线跟单⽚机通信的,当进⾏⼀次读写操作时最少得读写两个字节,第⼀个字节是控制字节,就是⼀个命令,告诉DS1302是读还是写操作,是对RAM还是对CLOK寄存器操作。

第⼆个字节就是要读或写的数据了。

单字节读写:只有在SCLK为低电平时,才能将CE置为⾼电平。

所以在进⾏操作之前先将SCLK置低电平,然后将CE置为⾼电平,接着开始在IO上⾯放⼊要传送的电平信号,然后跳变SCLK。

DS1302中文资料,带源代码

DS1302中文资料,带源代码

DS1302 引脚
X1 X2 32.768KHz 晶振管脚 GND 地 CE 复位脚 I/O 数据输入/输出引脚 SCLK 串行时钟 Vcc1,Vcc2 电源供电管脚
各引脚的功能为:
Vcc1:主电源;Vcc2:备份电源。当Vcc2>Vcc1+0.2V时,由Vcc2 向DS1302供电,当Vcc2< Vcc1时,由Vcc1向DS1302供电。 SCLK:串行时钟,输入,控制数据的输入与输出; I/O:三线接口时的双向数据线; CE:输入信号,在读、写数据期间,必须为高。该引脚有两个功能: 第一,CE开始控制字访问移位寄存器的控制逻辑;其次, CE 提供结束单字节或多字节数据传输的方法。
参考电路:
如上图所示: DS1302 与单片机的连接也仅需要 3 条线:CE 引脚、SCLK 串行时钟 引脚、I/O 串行数据引脚,Vcc2 为备用电源,外接 32.768kHz 晶振, 为芯片提供计时脉冲。
实际电路:
Vcc_5V:为电路中的主电源;Vcc2,也就是 BT1 为备份电源。当 Vcc2>Vcc1+0.2V 时, 由 Vcc2 向 DS1302 供 电 , 当 Vcc2< Vcc1 时 , 由 Vcc1 向 DS1302 供电 CLK 和 I/O 虽然和 IIC 总线接在一条引脚上,但 DS1302 其实并不是 使用 IIC 总线,而是一种三线式总线,
delayus(2); } return dat;//返回读取出的数据 }
寄存器和 RAM
对 DS1302 的操作就是对其内部寄存器的操作,DS1302 内部共有 12 个寄存器, 其中有: 7 个寄存器与日历、时钟相关,存放的数据位为 BCD 码形式。 此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器 及与 RAM 相关的寄存器等。 时钟突发寄存器可一次性顺序读写除充电寄存器以外的寄存器。 如下所示:
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

以下资料摘自电子发烧友网感谢作者,版权归网站所有,资料仅供参考
ds1302时钟程序详解
DS1302 的控制字如图2所示。

控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。

2.3 数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。

同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

2.4 DS1302的寄存器
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表1。

此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。

时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。

DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。

ds1302程序流程图
3.2 DS1302实时时间流程
图4示出DS1302的实时时间流程。

根据此流程框图,不难采集实时时间。

下面结合流程图对DS1302的基本操作进行编程:
根据本人在调试中遇到的问题,特作如下说明:DS1302 与微处理器进行数据交换时,首先由微处理器向电路发送命令字节,命令字节最高位MSB(D7)必须为逻辑1,如果D7=0,则禁止写DS1302,即写保护;D6=0,指定时钟数据,D6=1,指定RAM数据;D5~D1指定输入或输出的特定寄存器;最低位LSB(D0)为逻辑0,指定写操作(输入),D0=1,指定读操作(输出)。

在DS1302的时钟日历或RAM 进行数据传送时,DS1302必须首先发送命令字节。

若进行单字节传送,8位命令字节传送结束之后,在下2个SCLK周期的上升沿输入数据字节,或在下8个SCLK周期的下降沿输出数据字节。

DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;再一类为突发方式下的RAM 寄存器,在此方式下可一次性读、写所有的RAM的31个字节。

要特别说明的是备用电源B1,可以用电池或者超级电容器(0.1F以上)。

虽然DS1302在主电源掉电后的耗电很小,但是,如果要长时间保证时钟正常,最好选用小型充电电池。

可以用老式电脑主板上的3.6V充电电池。

如果断电时间较短(几小时或几天)时,就可以用漏电较小的普通电解电容器代替。

100 μF就可以保证1小时的正常走时。

DS1302在第一次加电后,必须进行初始化操作。

初始化后就可以按正常方法调整时间。

实时时钟电路DS1302的原理及应用
实时时钟电路DS1302的原理及应用
现在流行的串行时钟电路很多,如DS1302、DS1307、PCF8485等。

这些电路的接口简单、价格低廉、使用方便,被广泛地采用。

本文介绍的实时时钟电路DS1302是DALLAS公司的一种具有涓细电流充电能力的电路,主要特点是采用串行数据传输,可为掉电保护电源提供可编程的充电功能,并且可以关闭充电功能。

采用普通32.768kHz晶振。

2 DS1302的结构及工作原理
DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。

采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。

DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。

DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。

2.1 引脚功能及结构
图1示出DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。

在主电源关闭的情况下,也能保持时钟的连续运行。

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.5V 之前,RST必须保持低电平。

只有在SCLK为低电平时,才能将RST置为高电平。

I/O为串行数据输入输出端(双向),后面有详细说明。

SCLK始终是输入端。

2.2 DS1302的控制字节
DS1302的控制字如图2所示。

控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。

2.3 数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。

同样,在紧跟8位的控制指令字后的下一个SCLK 脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

2.4 DS1302的寄存器
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表1。

此外,DS1302还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。

时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。

DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。

3 DS1302实时显示时间的软硬件
DS1302与CPU的连接需要三条线,即SCLK(7)、I/O(6)、RST(5)。

图3示出DS1302与89C2051的连接图,其中,时钟的显示用LCD。

3.1 DS1302与CPU的连接
实际上,在调试程序时可以不加电容器,只加一个32.768kHz的晶振即可。

只是选择晶振时,不同的晶振,误差也较大。

另外,还可以在上面的电路中加入DS18B20,同时显示实时温度。

只要占用CPU一个口线即可。

LCD还可以换成LED,还可以使用北京卫信杰科技发展有限公司生产的10位多功能8段液晶显示模块LCM101,内含看门狗(WDT)/时钟发生器及两种频率的蜂鸣器驱动电路,并有内置显示RAM,可显示任意字段笔划,具有3-4线串行接口,可与任何单片机、IC 接口。

功耗低,显示状态时电流为2μA(典型值),省电模式时小于1μA,工作电压为2.4V~3.3V,显示清晰。

3.2 DS1302实时时间流程
图4示出DS1302的实时时间流程。

根据此流程框图,不难采集实时时间。

下面结合流程图对DS1302的基本操作进行编程:。

相关文档
最新文档