ds1302时钟程序详解-ds1302程序流程图(C程序)

合集下载

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显示时钟的C程序

DS1302显示时钟的C程序

#include&lt;reg52.h&gt; //包含单片机寄存器的头文件#include&lt;intrins.h&gt; //包含_nop_()函数定义的头文件#define uint unsigned int#define uchar unsigned charunsigned char code digit[10]={&quot;0123456789&quot;}; //定义字符数组显示数字sbit SCLK=P1^0; //位定义1302芯片的接口,时钟输出端口定义在P1.0引脚 sbit DATA=P1^1; //位定义1302芯片的接口,数据输出端定义在P1.1引脚sbit RST=P1^2; //位定义1302芯片的接口,复位端口定义在P1.2引脚/*****************************************************函数功能:延时若干微秒入口参数:n***************************************************/void delay(uint i){ unsigned char j;while(i--){for(j=110;j&gt;0;j--){;}}}/*****************************************************函数功能:向1302写一个字节数据入口参数:x***************************************************/void Write1302(unsigned char dat){unsigned char i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备 delay(2); //稍微等待,使硬件做好准备for(i=0;i&lt;8;i++) //连续写8个二进制位数据{DATA=dat&amp;0x01; //取出dat的第0位数据写入1302 低位在前,高位在后 delay(2); //稍微等待,使硬件做好准备SCLK=1; //上升沿写入数据delay(2); //稍微等待,使硬件做好准备SCLK=0; //重新拉低SCLK,形成脉冲dat&gt;&gt;=1; //将dat的各数据位右移1位,准备写入下一个数据位 }}/*****************************************************函数功能:根据命令字,向1302写一个字节数据入口参数:Cmd,储存命令字;dat,储存待写的数据。

DS1302时钟芯片 C语言程序设计

DS1302时钟芯片 C语言程序设计

unsigned char i,tmp; time_buf[1]=ds1302_read_byte(ds1302_year_add); //年 time_buf[2]=ds1302_read_byte(ds1302_month_add); //月 time_buf[3]=ds1302_read_byte(ds1302_date_add); //日 time_buf[4]=ds1302_read_byte(ds1302_hr_add); //时 time_buf[5]=ds1302_read_byte(ds1302_min_add); //分 time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7F;//秒 time_buf[7]=ds1302_read_byte(ds1302_day_add); //周 for(i=0;i<8;i++){ //BCD处理 tmp=time_buf[i]/16; time_buf1[i]=time_buf[i]%16; time_buf1[i]=time_buf1[i]+tmp*10; } } /*DS302初始化函数*/ void ds1302_init(void) { RST_CLR; /*RST脚置低*/ SCK_CLR; /*SCK脚置低*/ }
} else { temp &= 0x7F; } SCK_SET; SCK_CLR; } RST_CLR; /*停止DS1302总线*/ return temp; } /*向DS302写入时钟数据*/ void ds1302_write_time(void) { unsigned char i,tmp; for(i=0;i<8;i++){ //BCD处理 tmp=time_buf1[i]/10; time_buf[i]=time_buf1[i]%10; time_buf[i]=time_buf[i]+tmp*16; } ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护 ds1302_write_byte(ds1302_sec_add,0x80); //暂停 ds1302_write_byte(ds1302_charger_add,0xa9); //涓流充电 ds1302_write_byte(ds1302_year_add,time_buf[1]); //年 ds1302_write_byte(ds1302_month_add,time_buf[2]); //月 ds1302_write_byte(ds1302_date_add,time_buf[3]); //日 ds1302_write_byte(ds1302_day_add,time_buf[7]); //周 ds1302_write_byte(ds1302_hr_add,time_buf[4]); //时 ds1302_write_byte(ds1302_min_add,time_buf[5]); //分 ds1302_write_byte(ds1302_sec_add,time_buf[6]); //秒 ds1302_write_byte(ds1302_day_add,time_buf[7]); //周 ds1302_write_byte(ds1302_control_add,0x80); //打开写保护 } /*从DS302读出时钟数据*/ void ds1302_read_time(void) {

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程序及连接图

/****************************************************************************** ** 标题: 试验数码管显示时钟**** 通过本例程了解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实时时钟在数码管上进行实时显示的程序
#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实时时钟c程序加仿真原理图

ds1302实时时钟c程序加仿真原理图

#ifndef _1602_yejing_#define _1602_yejing_#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcden=P3^4;sbit lcdrs=P3^5;void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com) {lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date){lcdrs=1;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void write_lcd(uchar x,char *cha){ uchar length,i=0;write_com(x);for(length=0;cha[length]!=0;length++);for(i=0;i<length;i++){write_data(cha[i]);delay(5);}}void write_bcd(uchar cha){uchar ch1,ch2;ch1=(cha&0x0f)+'0';ch2=((cha>>4)&0x0f)+'0';write_data(ch2);write_data(ch1);}void write_fd(float t)//显示float型函数{ uchar s1,s2,s3,s4;uint tt;tt=t*100;s1=tt/1000;s1+=0x30;s2=tt%1000/100;s2+=0x30;s3=tt%1000%100/10;s3+=0x30;s4=tt%10;s4+=0x30;write_data(s1);write_data(s2);write_data(46);write_data(s3);write_data(s4);}void init(){lcden=0;write_com(0x38);//设置16*2显示write_com(0x0c);//设置开显示,不显示光标write_com(0x06);//写一个字符后地址指针加1write_com(0x01);//显示清0,数据指针清0}#endif/**************************************************************************THE REAL TIMER DS1302 DRIVER LIBCOPYRIGHT (c) 2010 BY ZYK.-- ALL RIGHTS RESERVED --File Name: DS1302.hAuthor: ZHANG YUAN KECreated: 2010/06/21Modified: NORevision: 1.0***************************************************************************/ #ifndef _DS1302_2010_06_21_#define _DS1302_2010_06_21_sbit SCLK = P1^6; //实时时钟时钟线引脚sbit DIO = P1^7; //实时时钟数据线引脚sbit CE = P1^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;char sec,min,hour,day,mon,week,year;char *tab[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat",};void write_1302(uchar add,uchar dat){uchar i;ACC=add;CE=0;SCLK=0;CE=1;for(i=0;i<8;i++){DIO=ACC0;SCLK=1;SCLK=0;ACC>>=1;}ACC=dat;for(i=0;i<8;i++){DIO=ACC0;SCLK=1;SCLK=0;ACC>>=1;}CE=0;}uchar read_1302(uchar add){uchar i;ACC=add;CE=0;SCLK=0;CE=1;for(i=8;i>0;i--) // 为什么不能for(i=0;i<8;i++) 又为什么用我写的函数不能改时间!!!!!!!!!!!!{DIO=ACC0;SCLK=1;ACC>>=1;SCLK=0;}for(i=8;i>0;i--){ ACC>>=1;ACC7=DIO;SCLK=1;SCLK=0;}return(ACC);CE=0;}void inputbyte(uchar d) //实时时钟写入一字节(内部函数){uchar i;ACC=d;for(i=8;i>0;i--){DIO=ACC0; //相当于汇编中的RRCSCLK=1;SCLK=0;ACC>>=1;}}uchar outputbyte() //实时时钟读取一字节(内部函数){uchar i;for(i=8; i>0; i--){ACC=ACC>>1; //相当于汇编中的RRCACC7=DIO;SCLK=1;SCLK=0;}return(ACC);}void write_1302(uchar add,uchar dat) //ucAddr: DS1302地址, ucData: 要写的数据{CE=0;SCLK=0;CE=1;inputbyte(add); // 地址,命令inputbyte(dat); // 写1Byte数据CE=0;}uchar read_1302(uchar add) //读取DS1302某地址的数据{uchar dat;CE=0;SCLK=0;CE=1;inputbyte(add); // 地址,命令dat=outputbyte(); // 读1Byte数据CE=0;return(dat);}void setprotect(bit flag){if(flag)write_1302(0x8e,0x80);elsewrite_1302(0x8e,0x00);}void gettime_1302(){sec=read_1302(0x81);min=read_1302(0x83);hour=read_1302(0x85);day=read_1302(0x87);mon=read_1302(0x89);week=read_1302(0x8b);year=read_1302(0x8d);}void stop_time(bit flag) // 是否将时钟停止{unsigned char dat;dat=read_1302(0x81);setprotect(0);if(flag)write_1302(0x80, dat|0x80);elsewrite_1302(0x80, dat&0x7F);}void init_1302(){uchar second=read_1302(0x81);if(second&0x80)write_1302(0x80,0);}/****************************************************************************** **void BurstWrite1302(unsigned char *pWClock) //往DS1302写入时钟数据(多字节方式) {unsigned char i;Write1302(0x8e,0x00); // 控制命令,WP=0,写操作?DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(0xbe); // 0xbe:时钟多字节写命令for (i = 8; i>0; i--) //8Byte = 7Byte 时钟数据+ 1Byte 控制{DS1302InputByte(*pWClock); // 写1Byte数据pWClock++;}DS1302_CLK = 1;DS1302_RST = 0;}void BurstRead1302(unsigned char *pRClock) //读取DS1302时钟数据(时钟多字节方式) {unsigned char i;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(0xbf); // 0xbf:时钟多字节读命令for (i=8; i>0; i--){*pRClock = DS1302OutputByte(); // 读1Byte数据pRClock++;}DS1302_CLK = 1;DS1302_RST = 0;}******************************************************************************* */#endif#include "1602.h"#include "DS1302.h"sbit set=P3^2;sbit jia1=P3^0;sbit jian1=P3^1;uchar bcdtoasc(uchar cha){return ((cha/16)*10+(cha%16));}uchar asctobcd(uchar cha){return ((cha/10)*16+(cha%10));}void disp_week(){ switch(week){case 1:{write_lcd(0xcd,tab[0]); break;}case 2:{write_lcd(0xcd,tab[1]); break;}case 3:{write_lcd(0xcd,tab[2]); break;}case 4:{write_lcd(0xcd,tab[3]); break;}case 5:{write_lcd(0xcd,tab[4]); break;}case 6:{write_lcd(0xcd,tab[5]); break;}case 7:{write_lcd(0xcd,tab[6]); break;}}}void disp_time(){write_com(0x87);write_bcd(year);write_com(0x8a);write_bcd(mon);write_com(0x8d);write_bcd(day);write_com(0xc5);write_bcd(hour);write_com(0xc8);write_bcd(min);write_com(0xcb);write_bcd(sec);disp_week();}void keyscan(){jia1=1;jian1=1;stop_time(1);if(set==0){delay(10);if(set==0) {delay(200); slect++;}if(slect==8) {slect=0; stop_time(0);write_com(0x0c);} }if(slect){switch(slect){ case 1:{write_com(0xcb);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);sec=read_1302(0x81);sec=sec&0x7f;sec=bcdtoasc(sec);sec+=1;if(sec==60)sec=0;sec=asctobcd(sec);write_1302(0x80,sec);write_com(0x0c);write_bcd(sec);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);sec=read_1302(0x81);sec=sec&0x7f;sec=bcdtoasc(sec);sec-=1;if(sec<0)sec=59;sec=asctobcd(sec);write_1302(0x80,sec);write_com(0x0c);write_bcd(sec);}}break;}case 2:{write_com(0xc8);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);min=read_1302(0x83);min=bcdtoasc(min);min+=1;if(min==60)min=0;min=asctobcd(min);write_1302(0x82,min);write_com(0x0c);write_bcd(min);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);min=read_1302(0x83);min=bcdtoasc(min);min-=1;if(min<0)min=59;min=asctobcd(min);write_1302(0x82,min);write_com(0x0c);write_bcd(min);}}break;}case 3:{write_com(0xc5);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);hour=read_1302(0x85);hour=bcdtoasc(hour);hour+=1;if(hour==24)hour=0;hour=asctobcd(hour);write_1302(0x84,hour);write_com(0x0c);write_bcd(hour);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);hour=read_1302(0x85);hour=bcdtoasc(hour);hour-=1;if(hour<0)hour=23;hour=asctobcd(hour);write_1302(0x84,hour);write_com(0x0c);write_bcd(hour);}}break;}case 4:{write_com(0x8d);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);mon=read_1302(0x89);year=read_1302(0x8d);day=read_1302(0x87);day=bcdtoasc(day);day+=1;year=bcdtoasc(year);if(year%4==0){if(mon==2){if(day==29)day=1;}else if(day==30)day=1;}else{ switch(mon){case 1:{if(day==32)day=1;break;}case 2:{if(day==30)day=1;break;}case 3:{if(day==32)day=1;break;}case 4:{if(day==31)day=1;break;}case 5:{if(day==32)day=1;break;}case 6:{if(day==31)day=1;break;}case 7:{if(day==32)day=1;break;}case 8:{if(day==32)day=1;break;}case 9:{if(day==31)day=1;break;}case 0x10:{if(day==32)day=1;break;}case 0x11:{if(day==31)day=1;break;}case 0x12:{if(day==32)day=1;break;}}if(mon==1|mon==3|mon==5|mon==7|mon==8|mon==0x10|mon==0x12) if(day==32)day=0; */if(mon==4|mon==6|mon==9|mon==0x11){if(day==31)day=1;}else if(day==32)day=1;}day=asctobcd(day);write_1302(0x86,day);write_com(0x0c);write_bcd(day);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);day=read_1302(0x87);day=bcdtoasc(day);day-=1;if(day<1){ mon=read_1302(0x89);year=read_1302(0x8d);switch(mon){ case 0x01: {day=31; break;}case 0x02: {day=29; break;}case 3: {day=31; break;}case 4: {day=30; break;}case 5: {day=31; break;}case 6: {day=30; break;}case 7: {day=31; break;}case 8: {day=31; break;}case 9: {day=30; break;}case 0x10: {day=31; break;}case 0x11: {day=30; break;}case 0x12: {day=31; break;}}year=bcdtoasc(year);if(year%4==0)if(mon==2)day=28;}day=asctobcd(day);write_1302(0x86,day);write_com(0x0c);write_bcd(day);}}break;}case 5:{write_com(0x8a);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);mon=read_1302(0x89);mon=bcdtoasc(mon);mon+=1;if(mon==13)mon=1;mon=asctobcd(mon);write_1302(0x88,mon);write_com(0x0c);write_bcd(mon);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);mon=bcdtoasc(mon);mon-=1;if(mon<1)mon=12;mon=asctobcd(mon);write_1302(0x88,mon);write_com(0x0c);write_bcd(mon);}}break;}case 6:{write_com(0x87);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);year=read_1302(0x8d);year=bcdtoasc(year);year+=1;if(year==100)year=0;year=asctobcd(year);write_1302(0x8c,year);write_com(0x0c);write_bcd(year);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);year=read_1302(0x8d);year=bcdtoasc(year);year-=1;if(year<0)year=99;year=asctobcd(year);write_com(0x0c);write_bcd(year);}}break;}case 7:{write_com(0xcd);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);week=read_1302(0x8b);week=bcdtoasc(week);week+=1;if(week==8)week=1;week=asctobcd(week);write_1302(0x8a,week);write_com(0x0c);disp_week();/* switch(week){case 1:{write_lcd(0xcd,tab[0]); break;}case 2:{write_lcd(0xcd,tab[1]); break;}case 3:{write_lcd(0xcd,tab[2]); break;}case 4:{write_lcd(0xcd,tab[3]); break;}case 5:{write_lcd(0xcd,tab[4]); break;}case 6:{write_lcd(0xcd,tab[5]); break;}case 7:{write_lcd(0xcd,tab[6]); break;}} */}}if(jian1==0){delay(10);if(jian1==0){ delay(200);week=read_1302(0x8b);week=bcdtoasc(week);week-=1;if(week<1)week=7;week=asctobcd(week);write_1302(0x8a,week);write_com(0x0c);disp_week();/* switch(week){case 1:{write_lcd(0xcd,tab[0]); break;}case 2:{write_lcd(0xcd,tab[1]); break;}case 3:{write_lcd(0xcd,tab[2]); break;}case 4:{write_lcd(0xcd,tab[3]); break;}case 5:{write_lcd(0xcd,tab[4]); break;}case 6:{write_lcd(0xcd,tab[5]); break;}case 7:{write_lcd(0xcd,tab[6]); break;} } */}}break; }}}}main(){init();init_1302();write_lcd(0x80,"DATE:20 - -");write_lcd(0x80+0x40,"TIME: : :");while(1){gettime_1302();set=1;if(set==0){delay(10);if(set==0){delay(200);slect++;}}while(slect)keyscan();disp_time();delay(30);}}。

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); //充电。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ds1302时钟程序详解,ds1302程序流程图(C程序)
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寄存器,此方式下可一次性读写所有的RA
M的31个字节,命令控制字为FEH(写)、FFH(读)。

ds1302程序流程图
3.2 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的时钟日历或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在第一次加电后,必须进行初始化操作。

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

相关文档
最新文档