DS1307实时时钟万年历

发布者:轻松自在最新更新时间:2020-08-18 来源: 51hei关键字:DS1307  实时时钟  万年历 手机看文章 扫描二维码
随时随地手机看文章

单片机源程序如下:

/****************************************************


电路图说明:

        将单片机P2.7和P1.0分别与RTC(实时时钟)的时钟信号SCL端

和数据信号SDA端相连, RTC的sout引脚与单片机P3.2相连,RTC的

地址是11010000.独立键盘k0~K3接P1.1~P1.3

程序功能:

          使用时钟芯片ds1307制作一个实时时钟

******************************************************/

#include

#include

#define uchar unsigned char

#define uint unsigned int

//实时时钟两信号线

sbit scl=P2^7;

sbit sda=P1^0;

//独立键盘扫描位

sbit k0=P1^1;

sbit k1=P1^2;

sbit k2=P1^3;

//液晶显示器控制位

sbit lcd_rs=P3^4;

sbit lcd_e=P3^5;

//数码管和led锁存器选通位

sbit duan=P2^0;

sbit wei=P2^1;

sbit led=P2^2;

void init();//初始化IIC总线,使总线处于备用状态,

                        //初始化lcd并显示上面table1和table2的值,初始化定时器0,初始化变量时分秒



/****************IIC总线控制函数***************************/

void IIC_start();//IIC通信开始信号

void IIC_stop();//IIC通信停止信号

void IIC_un_ack();//单片机发送非应答位

//void IIC_ack();//单片机发送应答位

void IIC_check_ack();//单片机检查应答位

void IIC_write_byte(uchar);//发送一字节数据

uchar IIC_read_byte();//接收一字节数据

void nop();//5us空操作延迟

/**********************************/

/**********ds1307读写函数*******************/

void ds1307_write_date(uchar ,uchar ,uchar);//向指定器件写一字节数据

                                                                        //参数1器件地址,参数2要存的数据存放位置8位地址

                                                                        //参数3要写的数据


uchar ds1307_read_date(uchar ,uchar );//从指定器件读一字节数据,

                                                                //参数1被通信器件地址,参数2要读的数据存放位置8位地址

                                                                //函数返回读取的数据。

void delay(uint);//基数1ms延迟程序

/***********************************/




/**************LCD操作函数**************************/


uchar hour,minute,second,k0_num;//时分秒变量,菜单键k0第几次按下计数,ds1307跟新标志

//时钟初显示

uchar code table1[]="2017-11-16 THUR";

uchar code table2[]="    23:59:55 ";




void lcd_write_com(uchar);//向液晶显示器写指令设置其显示的格式

void lcd_write_date(uchar);//向液晶显示器写显示的数据


/**********************************************/


/**************时钟函数*******************/

void lcd_write_second(uchar);//向lcd写秒

void lcd_write_minute(uchar);//向lcd写分

void lcd_write_hour(uchar);//向lcd写时

void run_time();//时钟走动显示

void keyscan();//菜单键扫描

/****************************************/


/*********十进值与BCD码之间互换**********/

uchar b_second,b_minute,b_hour;

uchar dectobcd(uchar);//十进值转bcd码

uchar bcdtodec(uchar);//bcd码转十进值

/****************************************/


void main()

{

        init();

        while(1)

        {

                keyscan();

        }

}


void nop()

{

        _nop_();_nop_();_nop_();

        _nop_();_nop_();_nop_();

}


void init()

{

        uchar i;

        //将数据线和时钟线拉高,处于备用状态即非忙

        sda=1;

        nop();

        scl=1;

        nop();

        

        //关数码管显示和8个LED显示

        duan=0;

        wei=0;

        led=0;

        lcd_e=0;


        

        //初始化写入LCD的时分秒

        second=55;

        minute=59;

        hour=23;

        //初始化ds1307

        ds1307_write_date(0xd0,0x07,0x10);//初始化1307的控制字,使其SOUT引脚输出1Hz的方波

        //初始化1307的时间

        ds1307_write_date(0xd0,6,0x14);                 

        ds1307_write_date(0xd0,5,0x06);   

        ds1307_write_date(0xd0,4,0x09);

        ds1307_write_date(0xd0,3,0x00);

        ds1307_write_date(0xd0,2,0x23);

        ds1307_write_date(0xd0,1,0x59);

        ds1307_write_date(0xd0,0,0x55);


        //初始化液晶显示器

        lcd_write_com(0x38);//设置16*2行,5*7点阵,8位数据接口

        lcd_write_com(0x06);//写字符指针和光标自动向右移动

        lcd_write_com(0x0c);//开显示,不显示光标,光标不闪烁

        lcd_write_com(0x01);//显示清屏

        for(i=0;i<15;i++)

        {

                lcd_write_date(table1[i]);

        }

        lcd_write_com(0x80+0x40);

        for(i=0;i<10;i++)

        {

                lcd_write_date(table2[i]);

        }

        

//开启外部中断0

        EA=1;

        EX0=1;

        IT0=1;

}

void IIC_start()

{

        //在时钟信号有效scl=1时,数据线负跳变

        sda=1;

        nop();

        scl=1;

        nop();

        sda=0;

        nop();

        scl=0;//拉低为下个时钟数据作准备

        nop();

}

void IIC_stop()

{

        //在时钟信号有效scl=1时,数据线正跳变,释放总线,使总线处于备用状态即非忙

        sda=0;

        nop();

        scl=1;

        nop();

        sda=1;

        nop();

        nop();

        nop();

}

void IIC_un_ack()

{

        //时钟信号有效时,sda给1,给出非应答

        sda=1;

        nop();

        scl=1;

        nop();

        scl=0;//拉低为下个时钟数据作准备

        nop();

}

/*

void IIC_ack()

{

        //时钟信号有效时,sda给0,给出应答

        sda=0;

        nop();

        scl=1;

        nop();

        scl=0;//拉低为下个时钟数据作准备

        nop();

}

*/

void IIC_check_ack()

{

        //uchar i;

        //时钟信号有效时,检测数据信号sda是否为0,给0说明有应答信号

        scl=1;

        //while((sda==1)&&(i<255)) i++;

        nop();

        scl=0;//拉低为下个时钟数据作准备

        nop();

}

uchar IIC_read_byte( )

{

        uchar i,temp;//temp用于存放从数据线读到的数据


        for(i=0;i<8;i++)//从数据线读取一个字节(8位)

        {

                scl=1;

                nop();

                temp=(temp<<1)|sda;//temp左移,腾出第0位,然后将数据线上的一位数用或

                                                                 //运算存放到temp的第0位

                scl=0;//拉低为下个时钟数据作准备        

                nop();

        }

        return temp;        

}


void IIC_write_byte(uchar byte)

{

        uchar i;

        for(i=0;i<8;i++)//向数据线写一个字节(8位)

        {

                byte=byte<<1;//左移位,将byte第7位移到PSW中的进位标志位CY中

                sda=CY;

                nop();

                scl=1;

                nop();

                scl=0;//拉低为下个时钟数据作准备

                nop();

        }

        sda=1;//释放总线,准备接收被控设备应答信号

        nop();

}


void ds1307_write_date(uchar d_address,uchar r_address,uchar date)

{


        IIC_start();

        IIC_write_byte(d_address & (~0x01));//写器件地址,方向是写,所以或上0x00

        IIC_check_ack();//等待应答

        IIC_write_byte(r_address);//写存储器数据存放的8位地址

        IIC_check_ack();//等待应答

        IIC_write_byte(date);//写一字节数据

        IIC_check_ack();//等待应答

        IIC_stop();

}


uchar ds1307_read_date(uchar d_address,uchar r_address)

{

        uchar r;

        IIC_start();

        IIC_write_byte(d_address & (~0x01));//写器件地址,方向是写

        IIC_check_ack();//等待应答

        IIC_write_byte(r_address);//写存储器数据存放的8位地址

        IIC_check_ack();//等待应答


        //换方向

        IIC_start();

        IIC_write_byte(d_address|0x01);//写器件地址,方向是读,所以或上1

    IIC_check_ack();

        r=IIC_read_byte();//读取一个字节数据

[1] [2] [3]
关键字:DS1307  实时时钟  万年历 引用地址:DS1307实时时钟万年历

上一篇:一个不用中断可立即跳出当前单片机程序运行状态的操作
下一篇:基于STC15F2K60S2的内部AD转换程序(1602显示)

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved