DS1302 时钟 51单片机实现时钟显示

DS1302 具有能计算2100年以前的秒分时……的能力,还有闰年调整功能

主要性能指标:

1、工作电压范围:2.0~5.5V
2、工作电流范围:2.0V时,电流小于200nA,功耗极低
3、TTL兼容
4、采用主电源和备份电源双电源供应
5、两种数据传送方式:单字节传送和多字节传送
6、采用串行数据传送方式

DS1302 时钟 51单片机实现时钟显示_第1张图片

x1,x2:晶振接入引脚
I/O:input/output具有三态功能
VCC1:工作电源
vcc2:备用电源引脚,接入电池或者大电容
sclk: 串行时钟输入

DS1302.h

#ifndef DS1302_H
#define DS1302_H

#include "reg52.h"
#include "intrins.h"

#ifndef  uchar //同理于c文件中的typedef unsigned char  uchar;
#define uchar unsigned char
#endif
#ifndef  uint 
#define uint unsigned int 
#endif


sbit DSIO = P3^4;
sbit RST = P3^5;
sbit SCLK = P3^6;

void Ds1302Write(uchar addr,uchar dat);
uchar  Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302readTime();
extern uchar TIME[7];



#endif

SPI:串行外围接口

DS1302 时钟 51单片机实现时钟显示_第2张图片
SPI接口主要以主从方式工作的,这种模式通常有一个主器件或多个从器件,其接口包括以下四种信号:
sclk: 时钟器件由主器件产生
MOSI:主器件数据output,从器件input
MISO:主器件数据input,从器件output
~SS:从器件使能信号,由主器件控制

缺点:没有指定的流控制,没有应答机制,确认是否接受到数据

Ds1302.c

#include "Ds1302.h"
/*
DS1302写入和读取时分秒的地址命令
秒分时日月周年 最低位读写位;
*/
uchar code READ_RTC_ADDR[7]=
        {0x81,0x83,0x85,0x87,0x89,0x8B,0x8D};
uchar code WEITE_RTC_ADDR[7]=
        {0x80,0x82,0x84,0x86,0x88,0x8A,0x8C};
/*
DS1302时钟初始化2018年5月13日星期六23点00分00秒。
存储顺序是秒分时日月周年,存储格式是用BCD码
*/
uchar TIME[7]={0,0,0x23,0x013,0x05,0x06,0x18};

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

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

*/
void Ds1302Write(uchar addr,uchar dat)//向DS1302命令(地址+数据)
{
    uchar n;
    RST=0;_nop_();
    SCLK=0;_nop_();
    RST=1;_nop_();
    for(n=0;n<8;n++){//地址传送
        DSIO=addr&0x01;
        addr>>=1;
        SCLK=1;_nop_();
        SCLK=0;_nop_();
    }
    for(n=0;n<8;n++){//读数据
        DSIO=dat&0x01;
        dat>>=1;
        SCLK=1;_nop_();//数据在SCLK上升沿时,DS1302读写数据,
                        //在SCLK下降沿时,DS1302放置数据到IO上
        SCLK=0;_nop_();
    }
    RST=0;_nop_();
}
uchar  Ds1302Read(uchar addr)
{
    uchar r,dat1,dat;
    RST=0;_nop_();
    SCLK=0;_nop_();
    RST=1;_nop_();
    for(r=0;r<8;r++){
        DSIO=addr&0x01;
        addr>>=1;
        SCLK=1;_nop_();
        SCLK=0;_nop_();
    }
    _nop_();
    for(r=0;r<8;r++){
        dat1=DSIO;
        dat=(dat>>1)|(dat1<<7);
        SCLK=1;_nop_();//数据在SCLK上升沿时,DS1302读写数据,
                        //在SCLK下降沿时,DS1302放置数据到IO上
        SCLK=0;_nop_();
    }
    RST=0;_nop_();
    SCLK=1;_nop_();
    DSIO=0;_nop_();
    DSIO=1;_nop_();
    return dat;

}

/*
控制寄存器用于存放DS1302的控制命令字,
DS1302的RST引脚回到高电平后写入的第一个字就为控制命令。
它用于对DS1302读写过程进行控制,它的格式如下:
这里写图片描述

D7:固定为1
D6:RAM/CK位,=1片内RAM,=0日历、时钟寄存器选择位。
D5~D1:地址位,用于选择进行读写的日历、时钟寄存器或片内RAM。对日历、时钟寄存器或片内RAM的选择见表。
D0: 读写选择,=0写,=1读

*/

void Ds1302Init()
{
    uchar n;
     Ds1302Write(0x8e,0x00);//禁止写保护
     for(n=0;n<8;n++){
          Ds1302Write(WRITE_RTC_ADDR[n],TIME[N]);
    }
          Ds1302Write(0x8e,0x80);//打开写保护
}


void Ds1302readTime()//读取时钟信息
{
    uchar n;
     for(n=0;n<8;n++){
         TIME[n]=Ds1302Read(READ_RTC_ADDR[n]);
    }
}



main.c

#include "reg52.h"
#include "Ds1302.h"

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

typedef unsigned int u16;
typedef unsigned char u8;

char num=0;
u8 DisplayData[8];
u8 code smgduan[10]=
        {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

void delay(u16 i){//最简单的延时程序
    while(i--);
}

void dispros()
{
    Da1302readtime();
    DisplayData[0] = smgduan[TIME[2]/16];               //时
    DisplayData[1] = smgduan[TIME[2]&0x0f];              
    DisplayData[2] = 0x40;
    DisplayData[3] = smgduan[TIME[1]/16];               //分
    DisplayData[4] = smgduan[TIME[1]&0x0f]; 
    DisplayData[5] = 0x40;
    DisplayData[6] = smgduan[TIME[0]/16];               //秒
    DisplayData[7] = smgduan[TIME[0]&0x0f];
}


void display()
{
u8 i;
    for(i=0;i<8;i++)
    {
        switch(i)    //位选,选择点亮的数码管,
        {
            case(0):
                LSA=0;LSB=0;LSC=0; break;//显示第0位
            case(1):
                LSA=1;LSB=0;LSC=0; break;//显示第1位
            case(2):
                LSA=0;LSB=1;LSC=0; break;//显示第2位
            case(3):
                LSA=1;LSB=1;LSC=0; break;//显示第3位
            case(4):
                LSA=0;LSB=0;LSC=1; break;//显示第4位
            case(5):
                LSA=1;LSB=0;LSC=1; break;//显示第5位
            case(6):
                LSA=0;LSB=1;LSC=1; break;//显示第6位
            case(7):
                LSA=1;LSB=1;LSC=1; break;//显示第7位    
        }
        P0=DisplayData[i];//发送数据
        delay(100); //间隔一段时间扫描  
        P0=0x00;//消隐
    }       

}

//最基本的简单实现函数
void main()
{   
    Ds1302Init();
    while(1)
    {
        datapros();  //数据处理函数
        DigDisplay();//数码管显示函数      
    }       
}

你可能感兴趣的:(C51,C语言基础)