单片机ds1302程序

合集下载

ds1302时钟芯片汇编控制程序

ds1302时钟芯片汇编控制程序
MOV R4,#8 ;----R4
OUTBIT1:MOV C,T_IO
RRC A
SETB T_CLK
CLR T_CLK
DJNZ R4,OUTBIT1
RET
;---------- ----------END DS0302--------------------------------
SETB T_CLK
CLR T_RST
mov R0,#SECOND
MOV R7,#3 ;秒/时/分;-----R7
MOV R1,#80H ;秒写地址;-----R1
S1302:
CLR T_RST
CLR T_CLK
SETB T_RST
MOV B,R1 ;写秒/时/分地址;---R1
LCALL WRITEBYTE
ds1302时钟芯片ds1302时钟电路ds1302时钟不走ds1302芯片功能ds1302ds1302lcd1602时钟ds1302芯片ds1302中文资料ds1302工作原理ds1302程序
DS1302初始化及读写操作汇编程序
;************ DS1302初始化子程序************************************
MOV R0,#SECOND ;------R0
MOV R7,#03H ;-----R7
MOV R2,#81H ;-----R2
G13021:CLR T_RST
CLR T_CLK
SETB T_RST
MOV B,R2
LCALL WRITEBYTE ;写操作时,将一字节的内容由B写至DS1302中
LCALL READBYTE ;读操作时,将一字节的内容读至A中
INBIT1:MOV A,B

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时,允许数据写入寄存器。

51单片机ds1302实时时钟程序

51单片机ds1302实时时钟程序

51单⽚机ds1302实时时钟程序#ifndef __DS1302_H_#define __DS1302_H_//---包含头⽂件---//#include#include//---重定义关键词---//#ifndefuchar#define uchar unsigned char#endif#ifndefuint#define uint unsigned int#endif//---定义ds1302使⽤的IO⼝---//sbit DSIO=P3^4;sbit RST=P3^5;sbit SCLK=P3^6;//---定义全局函数---//void Ds1302Write(ucharaddr, uchardat); uchar Ds1302Read(ucharaddr);void Ds1302Init();void Ds1302ReadTime();//---加⼊全局变量--//extern uchar TIME[7]; //加⼊全局变量#endif #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};/************************************************************************ * 函数名: Ds1302Write* 函数功能: 向DS1302命令(地址+数据)* 输⼊: addr,dat* 输出: ⽆************************************************************************* void Ds1302Write(ucharaddr, uchardat){uchar n;RST = 0;_nop_();SCLK = 0;//先将SCLK置低电平。

DS1302程序

DS1302程序

#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intuchar count_10ms; //定义10ms计数器sbit K1 = P3^2; //定义K1键sbit K2 = P3^3; //定义K2键sbit K3 = P3^4; //定义K3键sbit K4 = P3^5; //定义K4键sbit BEEP=P3^7; //定义蜂鸣器sbit reset = P1^2;sbit sclk = P1^0;sbit io = P1^1;sbit LCD_RS=P2^0;sbit LCD_RW=P2^1 ;sbit LCD_EN=P2^2;bit K1_FLAG=0; //定义按键标志位,当按下K1键时,该位置1,K1键未按下时,该位为0。

uchar code line1_data[] = {"---LCD Clcok---"}; //定义第1行显示的字符uchar code line2_data[] = {"****"}; //定义第2行显示的字符uchar disp_buf[8] ={0x00}; //定义显示缓冲区uchar time_buf[7] ={0,0,0x12,0,0,0,0}; //DS1302时间缓冲区,存放秒、分、时、日、月、星期、年uchar temp [2]={0}; //用来存放设置时的小时、分钟的中间值/********以下是函数声明********/void Delay_ms(uint xms) ;bit lcd_busy();void lcd_wcmd(uchar cmd);void lcd_wdat(uchar dat) ;void lcd_clr() ;void lcd_init() ;void write_byte(uchar inbyte); //写一字节数据函数声明uchar read_byte(); //读一字节数据函数声明void write_ds1302(uchar cmd,uchar indata); //写DS1302函数声明uchar read_ds1302(uchar addr); //读DS1302函数声明void set_ds1302(uchar addr,uchar *p,uchar n); //设置DS1302初始时间函数声明void get_ds1302(uchar addr,uchar *p,uchar n); //读当前时间函数声明void init_ds1302(); //DS1302初始化函数声明/********以下是延时函数********/void Delay_ms(uint xms){uint i,j;for(i=xms;i>0;i--) //i=xms即延时约xms毫秒for(j=110;j>0;j--);}/********以下是LCD忙碌检查函数********/bit lcd_busy(){bit result;LCD_RS = 0;LCD_RW = 1;LCD_EN = 1;_nop_();_nop_();_nop_();_nop_();result = (bit)(P0&0x80);LCD_EN = 0;return result;}/********以下是写指令寄存器IR函数********/void lcd_wcmd(uchar cmd){while(lcd_busy());LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;_nop_();_nop_();P0 = cmd;_nop_();_nop_();_nop_();_nop_();LCD_EN = 1;_nop_();_nop_();_nop_();_nop_();LCD_EN = 0;}/********以下是写寄存器DR函数********/void lcd_wdat(uchar dat){while(lcd_busy());LCD_RS = 1;LCD_RW = 0;LCD_EN = 0;P0 = dat;_nop_();_nop_();_nop_();_nop_();LCD_EN = 1;_nop_();_nop_();_nop_();_nop_();LCD_EN = 0;}/********以下是LCD清屏函数********/void lcd_clr(){lcd_wcmd(0x01); //清除LCD的显示内容Delay_ms(5);}/********以下是LCD初始化函数********/void lcd_init(){Delay_ms(15); //等待LCD电源稳定lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据Delay_ms(5);lcd_wcmd(0x38);Delay_ms(5);lcd_wcmd(0x38);Delay_ms(5);lcd_wcmd(0x0c); //显示开,关光标Delay_ms(5);lcd_wcmd(0x06); //移动光标Delay_ms(5);lcd_wcmd(0x01); //清除LCD的显示内容Delay_ms(5);}/********以下是写一字节数据函数********/void write_byte(uchar inbyte){uchar i;for(i=0;i<8;i++){sclk=0; //写时低电平改变数据if(inbyte&0x01)io=1;elseio=0;sclk=1; //高电平把数据写入DS1302_nop_();inbyte=inbyte>>1;}}/********以下是读一字节数据函数********/uchar read_byte(){uchar i,temp=0;io=1;for(i=0;i<7;i++){sclk=0;if(io==1)temp=temp|0x80;elsetemp=temp&0x7f;sclk=1; //产生下跳沿temp=temp>>1;}return (temp);}/********写DS1302函数, 往DS1302的某个地址写入数据********/ void write_ds1302(uchar cmd,uchar indata){sclk=0;reset=1;write_byte(cmd);write_byte(indata);sclk=0;reset=0;}/********读DS1302函数,读DS1302某地址的的数据********/ uchar read_ds1302(uchar addr){uchar backdata;sclk=0;reset=1;write_byte(addr); //先写地址backdata=read_byte(); //然后读数据sclk=0;reset=0;return (backdata);}/********设置初始时间函数********void set_ds1302(uchar addr,uchar *p,uchar n){write_ds1302(0x8e,0x00); //写控制字,允许写操作for(;n>0;n--){write_ds1302(addr,*p);p++;addr=addr+2;}write_ds1302(0x8e,0x80); //写保护,不允许写}********读取当前时间函数********void get_ds1302(uchar addr,uchar *p,uchar n){for(;n>0;n--){*p=read_ds1302(addr);p++;addr=addr+2;}}********初始化DS1302函数********/void init_ds1302(){reset=0;sclk=0;write_ds1302(0x80,0x00); //写秒寄存器write_ds1302(0x90,0xab); //写充电器write_ds1302(0x8e,0x80); //写保护控制字,禁止写}/*********以下是蜂鸣器响一声函数********/void beep(){BEEP=0; //蜂鸣器响Delay_ms(100);BEEP=1; //关闭蜂鸣器Delay_ms(100);}/********以下是转换函数,负责将走时数据转换为适合LCD显示的数据********/void LCD_conv (uchar in1,in2,in3 )//形参in1、in2、in3接收实参time_buf[2]、time_buf[1]、time_buf[0]传来的小时、分钟、秒数据{disp_buf[0]=in1/10+0x30; //小时十位数据disp_buf[1]=in1%10+0x30; //小时个位数据disp_buf[2]=in2/10+0x30; //分钟十位数据disp_buf[3]=in2%10+0x30; //分钟个位数据disp_buf[4]=in3/10+0x30; //秒十位数据disp_buf[5]=in3%10+0x30; //秒个位数据}/********以下是LCD显示函数,负责将函数LCD_conv转换后的数据显示在LCD上********/void LCD_disp (){lcd_wcmd(0x44 | 0x80); //从第2行第4列开始显示lcd_wdat(disp_buf[0]); //显示小时十位lcd_wdat(disp_buf[1]); //显示小时个位lcd_wdat(0x3a); //显示':'lcd_wdat(disp_buf[2]); //显示分钟十位lcd_wdat(disp_buf[3]); //显示分钟个位lcd_wdat(0x3a); //显示':'lcd_wdat(disp_buf[4]); //显示秒十位lcd_wdat(disp_buf[5]); //显示秒个位}/********以下是按键处理函数********/void KeyProcess(){uchar min16,hour16; //定义16进制的分钟和小时变量write_ds1302(0x8e,0x00); //DS1302写保护控制字,允许写write_ds1302(0x80,0x80); //时钟停止运行if(K2==0) //K2键用来对小时进行加1调整{Delay_ms(10); //延时去抖if(K2==0){while(!K2); //等待K2键释放beep();time_buf[2]=time_buf[2]+1; //小时加1if(time_buf[2]==24) time_buf[2]=0; //当变成24时初始化为0hour16=time_buf[2]/10*16+time_buf[2]%10; //将所得的小时数据转变成16进制数据write_ds1302(0x84,hour16); //将调整后的小时数据写入DS1302}}if(K3==0) // K3键用来对分钟进行加1调整{Delay_ms(10); //延时去抖if(K3==0){while(!K3); //等待K3键释放beep();time_buf[1]=time_buf[1]+1; //分钟加1if(time_buf[1]==60) time_buf[1]=0; //当分钟加到60时初始化为0min16=time_buf[1]/10*16+time_buf[1]%10; //将所得的分钟数据转变成16进制数据write_ds1302(0x82,min16); //将调整后的分钟数据写入DS1302}}if(K4==0) //K4键是确认键{Delay_ms(10); //延时去抖if(K4==0){while(!K4); //等待K4键释放beep();write_ds1302(0x80,0x00); //调整完毕后,启动时钟运行write_ds1302(0x8e,0x80); //写保护控制字,禁止写K1_FLAG=0; //将K1键按下标志位清0}}}/********以下是读取时间函数,负责读取当前的时间,并将读取到的时间转换为10进制数********/void get_time(){uchar sec,min,hour; //定义秒、分和小时变量write_ds1302(0x8e,0x00); //控制命令,WP=0,允许写操作write_ds1302(0x90,0xab); //涓流充电控制sec=read_ds1302(0x81); //读取秒min=read_ds1302(0x83); //读取分hour=read_ds1302(0x85); //读取时time_buf[0]=sec/16*10+sec%16; //将读取到的16进制数转化为10进制time_buf[1]=min/16*10+min%16; //将读取到的16进制数转化为10进制time_buf[2]=hour/16*10+hour%16; //将读取到的16进制数转化为10进制}/********以下是主函数********/void main(void){uchar i;P0 = 0xff;P2 = 0xff;lcd_init(); //LCD初始化函数(在LCD驱动程序软件包中)lcd_clr(); //清屏函数(在LCD驱动程序软件包中)lcd_wcmd(0x00|0x80); //设置显示位置为第1行第0列i = 0;while(line1_data[i] != '\0') //在第1行显示"---LCD Clcok---"{lcd_wdat(line1_data[i]); //显示第1行字符i++; //指向下一字符}lcd_wcmd(0x40|0x80); //设置显示位置为第2行第0列i = 0;while(line2_data[i] != '\0') //在第2行0~3列显示"****"{lcd_wdat(line2_data[i]); //显示第2行字符i++; //指向下一字符}lcd_wcmd(0x4c|0x80); //设置显示位置为第2行第12列i = 0;while(line2_data[i] != '\0') //在第2行12列之后显示"****"{lcd_wdat(line2_data[i]); //显示第2行字符i++; //指向下一字符}init_ds1302(); //DS1302初始化while(1){get_time(); //读取当前时间if(K1==0) //若K1键按下{Delay_ms(10); //延时10ms去抖if(K1==0){while(!K1); //等待K1键释放beep(); //蜂鸣器响一声K1_FLAG=1; //K1键标志位置1,以便进行时钟调整}}if(K1_FLAG==1)KeyProcess(); //若K1_FLAG为1,则进行走时调整LCD_conv(time_buf[2],time_buf[1],time_buf[0]); //将DS1302的小时/分/秒传送到转换函数LCD_disp(); //调LCD显示函数,显示小时、分和秒}}。

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与单片机的连接,51单片机操作ds1302流程展示

ds1302与单片机的连接,51单片机操作ds1302流程展示

ds1302 与单片机的连接,51 单片机操作ds1302 流程
展示
在许多单片机系统中常需要一些与时间有关的控制这就有需要使用实时时钟,因为在测控系统中需要做一些特殊数据的记录及其出现时间的记
录。

那幺实时时钟就能够很好的解决这个问题,今天我们就来谈谈ds1302 与单片机之间是如何作用联系的,单片机又是如何对时钟芯片进行操作的,一
起来了解一下。

51 单片机操作ds1302 流程展示
DS1302 通过3 根线与MCU 连接串行数据发送,接收时钟信号由MCU 发送,可外接备用电池以便主电源断电后不丢失数据,并可编程对备用电源充电。

DS1302 的结构如下:。

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

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

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指定输入或输出的特定寄存器;最低位LSB(D0)为逻辑0,指定写操作(输入),D0=1,指定读操作(输出)。

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驱动程序详解1

DS1302驱动程序详解1

DS1302驱动程序详解DS1302引脚介绍特性介绍驱动程序详解sbit IO=P1^0; //DS1302数据线sbit SCLK=P1^1; //DS1302时钟线sbit RST=P1^2; //DS1302复位线uchar WEEK[][4]={"SUN","***","MON","TUS","WEN","THU","FRI","SAT"}; //亦可定义成指针数组*WEEK[]uchar LCD_DSY_BUFFER1[]={"DA TE 00-00-00 "};uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00 "};uchar DateTime[7];void Initialize_LCD();void Display_LCD_String(uchar p,uchar *s);void DelayMS(uint ms);//------------------------------------------------------------------//向DS1302写入一个字节//------------------------------------------------------------------void Write_A_Byte_TO_DS1302(uchar x){uchar i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备for (i=0;i<8;i++){IO=x & 0x01; //取出x的第0位数据写入1302SCLK=1; //上升沿写入数据SCLK=0; //重新拉低SCLK,形成脉冲x >>=1; //将x的各数据位右移1位,准备写入下一个数据位}}//------------------------------------------------------------------//从DS1302读取一个字节,//注意:DS1302中所存放的数据是BCD码,在读写时要注意转换////------------------------------------------------------------------uchar Get_A_Byte_FROM_DS1302(){uchar i,b=0x00;for (i=0;i<8;i++){b |= _crol_((uchar)IO,i);//将uchar类型的IO数据左移i位SCLK=1; //将SCLK置于高电平,为下降沿读出SCLK=0; //时钟下降沿读取}return (b/16)*10+b%16; //将BCD码转换为十进制数}//------------------------------------------------------------------//从DS1302指定位置读取数据//------------------------------------------------------------------ uchar Read_Data(uchar addr){uchar dat;RST=0; //拉低RSTSCLK=0; //确保写数据前SCLK被拉低RST=1; //启动数据传输Write_A_Byte_TO_DS1302(addr); //写入命令字dat=Get_A_Byte_FROM_DS1302();SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递return dat;}//------------------------------------------------------------------//读取当前日期时间//------------------------------------------------------------------ void GetTime(){uchar i,addr =0x81;for (i=0;i<7;i++){DateTime[i] = Read_Data(addr);addr+=2;}}//------------------------------------------------------------------//日期与时间值转换为数字字符//------------------------------------------------------------------ void Format_DataTime(uchar d,uchar *a){a[0]=d/10+'0';a[1]=d%10+'0';}//------------------------------------------------------------------//主程序//------------------------------------------------------------------ void main(){Initialize_LCD();while(1){GetTime();Format_DataTime(DateTime[6],LCD_DSY_BUFFER1+5); //0x8D 年份寄存器Format_DataTime(DateTime[4],LCD_DSY_BUFFER1+8); //0x89 月份寄存器Format_DataTime(DateTime[3],LCD_DSY_BUFFER1+11); //0x87 日期寄存器//星期strcpy (LCD_DSY_BUFFER1+13,WEEK[DateTime[5]]);//将字符串WEEK[DateTime[5]]复制到字符数组LCD_DSY_BUFFER1+13中//0x8B 周日寄存器Format_DataTime(DateTime[2],LCD_DSY_BUFFER2+5); //0x85 小时寄存器Format_DataTime(DateTime[1],LCD_DSY_BUFFER2+8); //0x83 分钟寄存器Format_DataTime(DateTime[0],LCD_DSY_BUFFER2+11); //0x81 秒寄存器Display_LCD_String(0x00,LCD_DSY_BUFFER1); //第一行显示年、月、日、星期几Display_LCD_String(0x40,LCD_DSY_BUFFER2); //第二行显示小时、分钟、秒}}。

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程序

;1.每次上电,必须把秒寄存器高位(第7位)设置为0,时钟才能走时。

;2.如果需要写入数据和时钟日历信息,必须把“写保护”寄存器设置成为0 ;内存数据定义BitCnt data 30h ; 数据位计数器ByteCnt data 31h ; 数据字节计数器Command data 32h ; 命令字节地址RcvDat DATA 40H ; 接收数据缓冲区XmtDat DATA 50H ; 发送数据缓冲区;端口位定义IO_DATA bit P1.1 ; 数据传送总线SCLK bit P1.0 ; 时钟控制总线RST bit P1.2 ; 复位总线RS EQU P1.3;确定具体硬件的连接方式RW EQU P1.4 ;确定具体硬件的连接方式E EQU P1.5 ;确定具体硬件的连接方式ORG 0000HLJMP START;**************************** ;main programORG 0030HSTART: CLR RSTMOV SP,#2AH;------------------------------------初始化1302-------------------------SET1302:LCALL Write_Multiplebyte;初始化1302,将我们要设定的数据写入CG:LCALL Read_Multiplebyte;将我们设定的数据读出来MOV P3,#10000000BLCALL ENABLEMOV P3,#00011100BLCALL ENABLEMOV P3,#00110000BLCALL ENABLEMOV P3,#01100000BLCALL ENABLEMOV P3,#00000001BLCALL ENABLELCALL STLCDJNB P2.4,SETB_TIMELCALL YSLJMP CGSETB_TIME:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#01110011BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIME1JB P2.5,LJMP_ADDINC 45HLJMP_ADD:JB P2.6,LJMP_SUBBDEC 45HLJMP_SUBB:MOV A,45HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULIMOV A,45HADD A,#6MOV 45H,ACHULI:MOV A,45HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULIMOV A,45HSUBB A,#6MOV 45H,AZAICHULI:LCALL STLCDMOV P3,#01110011BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTTTTLJMP SETB_TIMEOUTPUTTTT:LJMP OUTPUTSETB_TIME1:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#11010011BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIME2JB P2.5,LJMP_ADD1INC 43HLJMP_ADD1:JB P2.6,LJMP_SUBB1DEC 43HLJMP_SUBB1:MOV A,43HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI1MOV A,43HADD A,#6MOV 43H,ACHULI1:MOV A,43HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI1MOV A,43HSUBB A,#6MOV 43H,AZAICHULI1:LCALL STLCDMOV P3,#11010011BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTLJMP SETB_TIME1SETB_TIME2:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#00010011BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIME3JB P2.5,LJMP_ADD2INC 44HLJMP_ADD2:JB P2.6,LJMP_SUBB2DEC 44HLJMP_SUBB2:MOV A,44HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI2MOV A,44HADD A,#6MOV 44H,ACHULI2:MOV A,44HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI2MOV A,44HSUBB A,#6MOV 44H,AZAICHULI2:LCALL STLCDMOV P3,#00010011BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTLJMP SETB_TIME2OUTPUT:LCALL Write_Enable;写允许MOV Command,#0BEh ;命令字节为BEhMOV ByteCnt,#8 ;多字节写入模式此模块为8 个MOV R0,#XmtDat;数据地址覆给R0MOV XmtDat,40H ;秒单元内容为59hMOV XmtDat+1,41H ;分单元内容为59hMOV XmtDat+2,42H ;时单元内容为13hMOV XmtDat+3,43H ;日期单元内容为21hMOV XmtDat+4,44H ;月单元内容为06hMOV XmtDat+5,45H ;星期单元内容为03hMOV XmtDat+6,46H ;年单元内容为00hMOV XmtDat+7,#0 ;写保护单元内容为00hLCALL Send_Byte ;调用写入数据子程序LJMP CGSETB_TIME3:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#10100011BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIME4JB P2.5,LJMP_ADD3INC 46HLJMP_ADD3:JB P2.6,LJMP_SUBB3DEC 46HLJMP_SUBB3:MOV A,46HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI3MOV A,46HADD A,#6MOV 46H,ACHULI3:MOV A,46HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI3MOV A,46HSUBB A,#6MOV 46H,AZAICHULI3:LCALL STLCDMOV P3,#10100011BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTLJMP SETB_TIME3SETB_TIME4:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#11010001BJNB P2.4,SETB_TIME5JB P2.5,LJMP_ADD4INC 40HLJMP_ADD4:JB P2.6,LJMP_SUBB4DEC 40HLJMP_SUBB4:MOV A,40HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI4MOV A,40HADD A,#6MOV 40H,ACHULI4:MOV A,40HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI4MOV A,40HSUBB A,#6MOV 40H,AZAICHULI4:LCALL STLCDMOV P3,#11010001BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTTLJMP SETB_TIME4SETB_TIME5:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#00010001BJNB P2.4,SETB_TIME6JB P2.5,LJMP_ADD5INC 41HLJMP_ADD5:JB P2.6,LJMP_SUBB5DEC 41HLJMP_SUBB5:MOV A,41HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI5MOV A,41HADD A,#6MOV 41H,ACHULI5:MOV A,41HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI5MOV A,41HSUBB A,#6MOV 41H,AZAICHULI5:LCALL STLCDMOV P3,#00010001BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTTLJMP SETB_TIME5OUTPUTT:LJMP OUTPUTSETB_TIME6:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#10100001BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIMEEJB P2.5,LJMP_ADD6INC 42HLJMP_ADD6:JB P2.6,LJMP_SUBB6DEC 42HLJMP_SUBB6:MOV A,42HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI6MOV A,42HADD A,#6MOV 42H,ACHULI6:MOV A,42HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI6MOV A,42HSUBB A,#6MOV 42H,AZAICHULI6:LCALL STLCDMOV P3,#10100001BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTTLJMP SETB_TIME6SETB_TIMEE:LJMP SETB_TIMESend_Byte:CLR RST ;复位引脚为低电平所有数据传送终止NOPCLR SCLK; 清时钟总线NOPSETB RST ;复位引脚为高电平逻辑控制有效NOPMOV A,Command; 准备发送命令字节MOV BitCnt,#08hS_Byte0:RRC A ;将最低位传送给进位位CMOV IO_DATA,C ;位传送至数据总线NOPSETB SCLK ;时钟上升沿发送数据有效NOPCLR SCLK ;清时钟总线DJNZ BitCnt,S_Byte0 ;位传送未完毕则继续NOPS_Byte1: ;准备发送数据MOV A,@R0 ;传送数据过程与传送命令相同MOV BitCnt,#08hS_Byte2:RRC AMOV IO_DATA,CNOPSETB SCLKNOPCLR SCLKDJNZ BitCnt,S_Byte2INC R0 ;发送数据的内存地址加1DJNZ ByteCnt,S_Byte1 ;字节传送未完毕则继续NOPCLR RST ;逻辑操作完毕清RSTRETReceive_Byte:CLR RST ;复位引脚为低电平所有数据传送终止NOPCLR SCLK ;清时钟总线NOPSETB RST ;复位引脚为高电平逻辑控制有效MOV A,Command ;准备发送命令字节MOV BitCnt,#08h ;传送位数为8R_Byte0:RRC A ;将最低位传送给进位位CMOV IO_DATA,C ;位传送至数据总线NOPSETB SCLK ;时钟上升沿发送数据有效NOPCLR SCLK ;清时钟总线DJNZ BitCnt,R_Byte0 ;位传送未完毕则继续NOPR_Byte1: ;准备接收数据CLR A ;清类加器CLR C ;清进位位CMOV BitCnt,#08h ;接收位数为8R_Byte2:NOPMOV C,IO_DATA ;数据总线上的数据传送给CRRC A ;从最低位接收数据SETB SCLK ;时钟总线置高NOPCLR SCLK ;时钟下降沿接收数据有效DJNZ BitCnt,R_Byte2 ;位接收未完毕则继续MOV @R1,A ;接收到的完整数据字节放入接收内存缓冲区INC R1 ;接收数据的内存地址加1DJNZ ByteCnt,R_Byte1 ;字节接收未完毕则继续NOPCLR RST ;逻辑操作完毕清RSTRET;--写保护寄存器操作------------------------------------------ Write_Enable:MOV Command,#8Eh ;命令字节为8EMOV ByteCnt,#1 ;单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#00h ;数据内容为0 写入允许ACALL Send_Byte ;调用写入数据子程序RET;当写保护寄存器的最高位为1 时禁止数据写入寄存器---------------Write_Disable:MOV Command,#8Eh ;命令字节为8EMOV ByteCnt,#1 ;单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#80h ;数据内容为80h 禁止写入ACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处;当把秒寄存器的第7 位时钟停止位设置为0 时起动时钟开始---------Osc_Enable:MOV Command,#80h ; 命令字节为80MOV ByteCnt,#1 ; 单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#00h ;数据内容为0 振荡器工作允许ACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处;当把秒寄存器的第7 位时钟停止位设置为1 时时钟振荡器停止HT1380 进入低功耗方式---------------Osc_Disable:MOV Command,#80h ;命令字节为80MOV ByteCnt,#1 ;单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#80h ;数据内容为80h 振荡器停止ACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处;写入00 年6 月21 日星期三13 时59 分59---------------------Write_Multiplebyte:MOV Command,#0BEh ;命令字节为BEhMOV ByteCnt,#8 ;多字节写入模式此模块为8 个MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#48h ;秒单元内容为59hMOV XmtDat+1,#14h ;分单元内容为59hMOV XmtDat+2,#09h ;时单元内容为13hMOV XmtDat+3,#16h ;日期单元内容为21h MOV XmtDat+4,#15h ;月单元内容为06hMOV XmtDat+5,#05h ;星期单元内容为03h MOV XmtDat+6,#07 ;年单元内容为00hMOV XmtDat+7,#0 ;写保护单元内容为00h ACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处;读出寄存器0-7 的内容程序设置如下Read_Multiplebyte:MOV Command,#0BFh ;命令字节为BFhMOV ByteCnt,#8 ;多字节读出模式此模块为8 个MOV R1,#RcvDat ;数据地址覆给R1ACALL Receive_Byte; 调用读出数据子程序RET; 返回调用本子程序处SSH:MOV B,#16DIV ABMOV 61H,BMOV 62H,AMOV R1,#62HMOV A,@R1MOV DPTR,#TABMOVC A,@A+DPTRMOV P3,ASETB RSCLR RWCLR ELCALL DELAYSETB EMOV A,@R1MOV DPTR,#TABMOVC A,@A+DPTRMOV P3,ASETB RSCLR RWCLR ELCALL DELAYSETB ERETENABLE:CLR RS ;写入控制命令的子程序CLR RWCLR EACALL DELAYSETB ERETDELAY:MOV P3,#0FFH ;判断液晶显示器是否忙的子程序CLR RSSETB RWCLR ENOPSETB EJB P3.0,DELAY ;如果P1.7为高电平表示忙就循环等待RET;写入8 时12 小时模式程序设置如下Write_Singlebyte:MOV Command,#84h ; 命令字节为84hMOV ByteCnt,#1 ; 单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#88h ;数据内容为88hACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处MOV P3,#00000001B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV A,#0;显示时间字符MOV R7,#0TIME:MOV DPTR,#TAB2MOVC A,@A+DPTRMOV P3,ALCALL CCFF1INC R7MOV A,R7CJNE A,#5,TIMEMOV A,42HLCALL SSHMOV P3,#10110100BLCALL CCFF1MOV A,41HLCALL SSHMOV P3,#10110100BLCALL CCFF1MOV A,40HLCALL SSHMOV P3,#00000011BLCALL ENABLEMOV A,#0;显示日期字符MOV R7,#0DATE:MOV DPTR,#TAB1MOVC A,@A+DPTRMOV P3,ALCALL CCFF1INC R7CJNE A,#5,DATEMOV A,46HLCALL SSHMOV P3,#10110100B LCALL CCFF1MOV A,44HLCALL SSHMOV P3,#10110100B LCALL CCFF1MOV A,43HLCALL SSHMOV P3,#00000100B LCALL CCFF1MOV A,45HLCALL SSHRETYS:MOV R5,#60D2:MOV R6,#50D1: MOV R7,#66DJNZ R7, $DJNZ R6,D1DJNZ R5,D2RETCCFF1:SETB RSCLR RWCLR ELCALL DELAY SETB ERETTAB:DB00001100B,10001100B,01001100B,11001100B,00101100B,10101100B,01101100B,111 01100B,00011100B,10011100B,01110100B,10110100BTAB2:DB 00101010b,10010110b,10110110b,10100110b,01011100bTAB1:DB 00100010b,10000110b,00101110b,10100110b,01011100bEND。

DS1302程序-单片机常用器件驱动及应用实例

DS1302程序-单片机常用器件驱动及应用实例

DS1302程序-单片机常用器件驱动及应用实例1 DS1302 简介:DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。

实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。

工作电压宽达2.5~5.5V。

采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。

DS1302的外部引脚分配如图1所示及内部结构如图2所示。

DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。

图1 DS1302的外部引脚分配图2 DS1302的内部结构各引脚的功能为:Vcc1:主电源;Vcc2:备份电源。

当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2<Vcc1时,由Vcc1向DS1302供电。

SCLK:串行时钟,输入;I/O:三线接口时的双向数据线;CE:输入信号,在读、写数据期间,必须为高。

该引脚有两个功能:第一,CE开始控制字访问移位寄存器的控制逻辑;其次,CE提供结束单字节或多字节数据传输的方法。

DS1302有下列几组寄存器:①DS1302有关日历、时间的寄存器共有12个,其中有7个寄存器(读时81h~8 Dh,写时80h~8Ch),存放的数据格式为BCD码形式,如图3所示。

图 3 DS1302有关日历、时间的寄存器小时寄存器(85h、84h)的位7用于定义DS1302是运行于12小时模式还是24小时模式。

当为高时,选择12小时模式。

在12小时模式时,位5是,当为1时,表示P M。

在24小时模式时,位5是第二个10小时位。

秒寄存器(81h、80h)的位7定义为时钟暂停标志(CH)。

ds1302程序

ds1302程序

#include<reg52.h>#define uchar unsigned charsbit RST=P1^2;sbit SDA=P1^1;sbit SCLK=P1^0;sbit rs=P1^3;sbit lcden=P1^4;sbit key1=P3^7;sbit key2=P3^6;sbit key3=P3^5;uchar t,addr,x,y;void delay(unsigned char t){unsigned char i,j;for(i=t;i>0;i--)for(j=110;j>0;j--);}void delayus(unsigned char t1){for(;t1>0;t1--);}void write_com(unsigned char com)//写lcd1602控制命令{rs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_dat(unsigned char dat) //写lcd1602显示数据命令{rs=1;P0=dat;delay(5);lcden=1;delay(5);lcden=0;}void DS1302WriteByte(uchar dat){uchar i;SCLK=0;delayus(2);for(i=0;i<8;i++){SDA=dat&0x01;delayus(2);SCLK=1;delayus(2);SCLK=0;dat>>=1;}}void DS1302Read(uchar cmd) //读ds1302的时间信息并显示出来{uchar dat,a2,i;RST=0;SCLK=0;RST=1;DS1302WriteByte(cmd);delayus(2);for(i=0;i<8;i++){dat>>=1;if(SDA==1)dat|=0x80;SCLK=1;delayus(2);SCLK=0;delayus(2);}SCLK=1;RST=0;if(cmd==0x8b){dat=dat%16;write_dat(0x30+dat);}else{a2=dat%16;dat=dat/16;write_dat(0x30+a2);write_dat(0x30+dat);}}void DS1302Write(uchar cmd, uchar dat) //写时间信息到ds1302 {RST=0;SCLK=0;RST=1;DS1302WriteByte(cmd);DS1302WriteByte(dat);SCLK=1;RST=0;}void init() //初始化部分{P2=0; //关闭锁存器端口write_com(0x01);write_com(0x38);write_com(0x0c);write_com(0x04);DS1302Write(0x8e,0x00);}void key() //按键控制部分{ uchar q;if(key1==0){DS1302Write(0x80,0x80);write_com(0x0f);delay(40);if(key1==0){t++;if(t==9)t=1;switch(t){case 1:write_com(0x85); addr=0x85;break;case 2:write_com(0x88); addr=0x88;break;case 3:write_com(0x8b); addr=0x8b;break;case 4:write_com(0x8e); addr=0x8e;break;case 5:write_com(0xc5); addr=0xc5;break;case 6:write_com(0xc8); addr=0xc8;break;case 7: write_com(0xcb); addr=0xcb;break;case 8: x=x*16+y;DS1302Write(0x80,x);write_com(0x0c);t=0;break;}while(key1==0);x=0;y=0;}}if(key2==0||key3==0){delay(40);if(key2==0){if(t==4)y=0;elsex++;}if(key3==0)y++;switch (t){case 1: if(x==10)x=0;if(y==10)y=0;q=x*16+y;DS1302Write(0x8c,q);break;case 2: if(x==0){if(y==10)y=0;}if(x==1){ if(y==3)y=0;}if(x==2)x=0;q=x*16+y;DS1302Write(0x88,q); break;case 3: if(x==4)x=0;if(y==32)y=0;q=x*16+y;DS1302Write(0x86,q);break;case 4:if(y==8)y=0;q=x*16+y;DS1302Write(0x8a,q); break;case 5: if(x==0||x==1){if(y==10)y=0;}if(x==2){ if(y==4)y=0;}if(x==3)x=0;q=x*16+y;DS1302Write(0x84,q); break;case 6:if(x==6)x=0;if(y==10)y=0;q=x*16+y;DS1302Write(0x82,q);break;case 7: if(x==6)x=0;if(y==10)y=0;q=x*16+y+0x80;DS1302Write(0x80,q);break;}if(addr==0x8e){write_com(addr);write_dat(0x30+y);write_com(addr);}else{write_com(addr);write_dat(0x30+y);write_dat(0x30+x);write_com(addr);}while(key2==0||key3==0);}}void main(){init();while(1){key();if(t==0){write_com(0xcb); // 在第二行显示DS1302Read(0x81); // 读秒write_dat(0x3a);DS1302Read(0x83); // 读分write_dat(0x3a);DS1302Read(0x85); // 读时write_com(0x8e); // 在第一行显示DS1302Read(0x8b); // 读星期write_dat(0x2a);write_dat(' ');DS1302Read(0x87); // 读日write_dat(0x2f);DS1302Read(0x89); // 读月write_dat(0x2f);DS1302Read(0x8d); // 读年write_dat(0x30);write_dat(0x32);} }}。

DS1302-程序-汇编程序

DS1302-程序-汇编程序
SETB RST
MOV A,#0FFH
ACALL SWRITE
RRLOP1:ACALL SREAD
MOV @R0,A
INC R0
DJNZ R3,RRLOP1
CLR RST
RET
;数据写到RAM中子程序
RAMWRITE:ACALL WRUNLOK
MOV 2EH,A ;高位送到2EH
ANL 2DH,#10H
MOV A,31H ;将31H(存放分)放到A
ANL A,#0FH
ORL A,2DH
MOV 2DH,A ; 低位送到2DH
MOV A,31H
ANL A,#0F0H
SWAP A
MOV R3,#8
ACALL RAMWRITE
MOV R0,#40H
MOV R3,#8
ACALL RAMREAD
RET
; 秒:30H 分:31H 时:32H 日:33H 月:34H 年:36H
; 执行非写保护方式子程序
WRUNLOK:
MOV 2AH,A ;高位送到2AH
ANL 29H,#10H
MOV A,33H ;将33H(存放日)放到A
ANL A,#0FH
ORL A,29H
MOV 29H,A ; 低位送到29H
MOV A,33H
ANL A,#0F0H
MOV A,@R0 ;秒低显示
MOVC A,@A+DPTR
MOV P0,A
MOV R2,#80H
DJNZ R2,$
SETB P1.0
CLR P1.1
DEC R0 ;秒高显示
MOV A,@R0

DS1302芯片C语言程序

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数码管显示程序
clock_s2=clock_s2&0xff;
clock_s1<<=4;
clock_s1=clock_s1|clock_s2;// 10to16
clock_f1=mie/10;
clock_f2=mie%10;
clock_f1=clock_f1&0xff; //全1出1与运算
clock_f2=clock_f2&0xff;
delay(1);P0=0X00;}
if(cant1==5)
cant1=0;
P2=2;
P0=ledmap[10];//显示"-"数组里的0x40
delay(1);
P0=0X00;
if(cant2<=3)
{
P2=3;
P0=ledmap[clock_fs];//分十位
delay(1);
P0=0X00;
P2=4;
if(mie>=60)
{
mie=0;
}
delayAJ(10);
}//以上时钟+设定
}
}
if(down==0)
{
delayAJ(5);//消抖
if(down==0)
{
delayAJ(5);
if(b==1)
{
hour--;
if(hour<0)
{
hour=23;
}
delayAJ(10);
}
if(b==2)
delayAJ(5);
}
while(!set)
{
delayAJ(5);
}
}
if(b!=0)//时分设定
{
if(up==0)

DS1302汇编程序

DS1302汇编程序

标签:DS1302汇编程序ds1302汇编程序以下是我的DS1302汇编程序;******************************************************************** */T_RST Bit P3.3 ;实时时钟复位线引脚T_CLK Bit P3.4 ;实时时钟时钟线引脚T_IO Bit P3.5 ;实时时钟数据线引脚SECOND EQU 30HMINUTE EQU 31HHOUR EQU 32HDAY EQU 33HMONTH EQU 34HWEEK EQU 35HYEARL EQU 36H;******************************************************************** */ORG 0000HLJMP STARTORG 0060HSTART: ;CLR T_RST;CLR T_CLKMOV SP,#60H ;修改堆栈MOV SECOND,#00H ;初始时间设为12:00:00MOV MINUTE,#00HMOV HOUR,#12HMOV DAY,#01H ;初始日期设为08年1月1日第一周 MOV MONTH,#01HMOV WEEK,#01HMOV YEARL,#08HLCALL SETDS1302LCALL GET1302LCALL DISPLAYMAIN: MOV R3,#25MOV TMOD,#01HMOV TH0,#70H ;置定时器初值(定时40ms)MOV TL0,#00HSETB TR0 ;启动定时器0LP1: JBC TF0,LP2 ;查询计数溢出SJMP LP1 ;未到40 ms继续计数LP2: MOV TH0,#0B8H ;重新置定时器初值MOV TL0,#00HLCALL DISPLAY ;显示DJNZ R3,LP1 ;未到1 S继续循环LCALL GET1302 ;每过1s从DS1302读取一次时间 mov r3,#25SJMP lp1;---------------------------------------------------------------------------------------------------;字符显示码表DIG_CODE:DB 0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H;---------------------------------------------------------------------------------------------------;---------------------------------------------------------------------------------------------------;数码显示子程序DISPLAY:MOV DPTR,#DIG_CODE;*******************************************;显示秒MOV A,SECONDANL A,#0FHMOVC A,@A+DPTRMOV P2,AMOV P1,#11011111bLCALL DIS_DELAYMOV A,SECONDSWAP AANL A,#07HMOVC A,@A+DPTRMOV P2,AMOV P1,#11101111bLCALL DIS_DELAY;*******************************************;显示分MOV A,MINUTEANL A,#0FHMOVC A,@A+DPTRMOV P2,AMOV P1,#11110111bLCALL DIS_DELAYMOV A,MINUTESWAP AANL A,#07HMOVC A,@A+DPTRMOV P2,AMOV P1,#11111011bLCALL DIS_DELAY;*******************************************;显示小时MOV A,HOURANL A,#0FHMOVC A,@A+DPTRMOV P2,AMOV P1,#11111101bLCALL DIS_DELAYMOV A,HOURSWAP AANL A,#03HMOVC A,@A+DPTRMOV P2,AMOV P1,#11111110bLCALL DIS_DELAYRET;---------------------------------------------------------------------------------------------------;---------------------------------------------------------------------------------------------------;显示延时5ms子程序DIS_DELAY:PUSH PSWMOV R7,#10D1: MOV R6,#248D2: DJNZ R6,$DJNZ R7,D1POP PSWRET;---------------------------------------------------------------------------------------------------;---------------------------------------------------------------------------------------------------;设置DS1302初始时间,并启动计时SETDS1302:nopCLR T_CLKnopSETB T_RSTnopMOV B,#8EH ;写控制命令字LCALL INPUTBYTEMOV B,#00H ;写保护关闭LCALL INPUTBYTESETB T_CLKnopCLR T_RSTMOV R0,#SECOND ;内存中的时间首地址MOV R1,#80H ;DS1302中的时间首地址 MOV R7,#7 ;字节数SETLOOP:CLR T_RSTnopCLR T_CLKnopSETB T_RSTnopMOV B,R1 ;写命令字LCALL INPUTBYTEMOV A,@R0 ;设置时间MOV B,ALCALL INPUTBYTEINC R0INC R1INC R1SETB T_CLKnopCLR T_RSTnopDJNZ R7,SETLOOPCLR T_RSTnopCLR T_CLKnopSETB T_RSTnopLCALL INPUTBYTEMOV B,#80H ;开写保护LCALL INPUTBYTESETB T_CLKnopCLR T_RSTnopRET;---------------------------------------------------------------------------------------------------;从DS1302读取时间GET1302:MOV R0,#SECONDMOV R1,#81H ;DS1302中读时间的首地址MOV R7,#7GETLOOP:CLR T_RSTnopCLR T_CLKnopSETB T_RSTnopMOV B,R1LCALL INPUTBYTE ;写命令字LCALL OUTPUTBYTE ;读时间MOV @R0,A ;将从DS1302中读取的时间从内存中保存 INC R0 ;修改地址指针INC R1INC R1SETB T_CLKnopCLR T_RSTnopDJNZ R7,GETLOOPRET;---------------------------------------------------------------------------------------------------;向DS1302写一个字节INPUTBYTE:MOV R4,#8INPUTLOOP:MOV A,BRRC AMOV B,AMOV T_IO,CSETB T_CLKNOP;NOP;NOPCLR T_CLKDJNZ R4,INPUTLOOPRET;---------------------------------------------------------------------------------------------------;从DS1302读一个字节OUTPUTBYTE:clr aclr cMOV R4,#8OUTPUTLOOP:NOP;NOPMOV C,T_IORRC ASETB T_CLKNOP;NOP;NOPCLR T_CLKDJNZ R4,OUTPUTLOOPRETend。

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

#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit LCD1602_E=P3^6;
sbit LCD1602_RW=P3^5;
sbit LCD1602_RS=P3^4;
sbit DSIO=P0^7;
sbit RST=P0^5;
sbit SCLK=P0^6;
extern uchar TIME[7];
void Ds1302Write(uchar addr, uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302ReadTime();
void Lcd1602_Delay1ms(uint c); //误差0us
void LcdWriteCom(uchar com);
void LcdWriteData(uchar dat) ;
void LcdInit();
void LcdDisplay();
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}; uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};
void main()
{
LcdInit();
Ds1302Init();
while(1)
{
Ds1302ReadTime();
LcdDisplay();
}
}
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 Ds1302ReadTime()
{
uchar n;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
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 Lcd1602_Delay1ms(uint c) //误差0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //选择发送命令
LCD1602_RW = 0; //选择写入
P2= com; //放入命令
Lcd1602_Delay1ms(1); //等待数据稳定
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择输入数据
LCD1602_RW = 0; //选择写入
P2= dat; //写入数据
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
void LcdInit() //LCD初始化子程序{
LcdWriteCom(0x32); //将8位总线转为4位总线
LcdWriteCom(0x28); //在四位线下的初始化
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
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)); //星期
}。

相关文档
最新文档