实时时钟DS1302Nebula Pi评测报告·

Nebula Pi 开发板评测报告(十三)——实时时钟(RTC)DS1302功能测试

ii11nnocent

ii11nnocent

1898 0

RTC(Real Time Clock)是实时时钟的简称,可以为我们提供精确的实时时间,其中具有代表性的就是DS1302数字时钟芯片,通过单片机与DS1302的通信就可以读取DS1302中存储的时间信息。利用下面的程序可以实现在LCD1602上显示当前的时间(Brust模式):

ds1302.h:

#ifndef _DS1302_H
#define _DS1302_H

#include "reg52.h"

extern unsigned char *week;

void WriteByte_1302(unsigned char dat);
unsigned char ReadByte_1302(void);
void Write_1302( unsigned char addr , unsigned char dat );
unsigned char Read_1302( unsigned char addr );
void DS1302_Init( unsigned char *InitTime );
void GetCurrentTime( unsigned char *CurrentTime );
void BurstWrite_1302( unsigned char *Time );
void BrustRead_1302( unsigned char *CurrentTime );
void WeekTransform( unsigned char w );

#endif

ds1302.c:

#include "ds1302.h"

sbit CE     = P0^5;         //位定义DS1302CE、I/O和SCLK引脚
sbit IO     = P0^4;
sbit SCLK = P0^3;
unsigned char *week;

//向DS1302写入一个字节的函数
void WriteByte_1302(unsigned char dat)
{
    unsigned char i;
    bit flag;

    for(i=0;i<8;i++)
    {
        //写入数据时候从低位到高位
        flag = dat & 0x01;      //待传送的数据的低位存入flag等待传输
        
        IO = flag;
        SCLK = 0;
        SCLK = 1;       //在SCLK上产生一个上升沿,完成一位数据写入
        
        dat = dat >>1;      //将dat右移一位,继续写入
    }
}

//从DS1302读出一个字节的函数,返回值为一个字节的数据
unsigned char ReadByte_1302(void)
{
    unsigned char i,flag,dat;
    
    for(i=0;i<8;i++)
    {
        SCLK = 1;
        SCLK = 0;       //在SCLK上产生一个下降沿,完成一位数据的读出
        
        flag = IO;  //将读出的一位数据放入flag中
        
        dat = ( dat >>1 ) | ( flag <<7 );           //循环8次,每次都将读出的数据放入最高位
    }
    return dat;     //将读出的数据返回
}

//向固定地址写入单字节数据的函数
void Write_1302( unsigned char addr , unsigned char dat )
{
    CE = 1;     //拉高CE引脚
    WriteByte_1302( addr );     //写入地址数据
    WriteByte_1302( dat );      //写入数据
    CE = 0;     //拉低CE引脚
    SCLK = 0;   //拉低SCLK,为下一次传输做准备
}

//从固定地址读出数据
unsigned char Read_1302( unsigned char addr )
{
    unsigned char dat;
    
    CE = 1;     //拉高CE引脚
    WriteByte_1302( addr );     //写入地址数据
    dat = ReadByte_1302();      //将读出的数据存放到dat中
    CE = 0;     //拉低CE引脚

    return dat;
}

//DS1302初始化,写入初始化时间
void DS1302_Init( unsigned char *InitTime )
{
//  unsigned char i;
    
    CE = 0;     //拉低CE引脚
    SCLK = 0;   //拉低SCLK引脚
    Write_1302( 0x8E , 0x00 );  //向0x8E寄存器写入0,解除写保护
    
    /****
    for( i=0;i<7;i++ )
    {
        Write_1302( 0x80 + 2*i , InitTime[i] ); //依次写入秒、分、时、日、月、星期、年的数据
    }
    ****/
    BurstWrite_1302( InitTime );
}

//获取当前时间
void GetCurrentTime( unsigned char *CurrentTime )
{
    //unsigned char i;
    
    CE = 0;     //拉低CE引脚
    SCLK = 0;   //拉低SCLK引脚
    
    /****
    for( i=0;i<7;i++ )
    {
        *CurrentTime = Read_1302( 0x81 + 2*i ); //依次读取秒、分、时、日、月、星期、年的数据
        CurrentTime ++;     //地址+1,存储数据
    }
    ****/
    BrustRead_1302( CurrentTime );
}

/****下面是突发模式下的读写函数****/

//突发写数据函数
void BurstWrite_1302( unsigned char *Time )
{
    unsigned char i;
    
    CE = 1;     //拉高CE引脚
    WriteByte_1302(0xBE);       //突发模式专用写指令
    for( i=0;i<7;i++ )
    {
        WriteByte_1302(Time[i]);    //向1302写入时间数据
    }
    WriteByte_1302(0);                  //向第八个寄存器写入0,防止出错
    CE = 0;     //拉低CE引脚
}

//突发读数据函数
void BrustRead_1302( unsigned char *CurrentTime )
{
    unsigned char i;
    
    CE = 1;     //拉高CE引脚
    WriteByte_1302(0xBF);       //突发模式专用写指令
    for( i=0;i<7;i++ )
    {
        *CurrentTime = ReadByte_1302(); //读取一个字节的数据
        CurrentTime ++;                             //地址+1
    }
    CE = 0;     //拉低CE引脚
}

void WeekTransform( unsigned char w )
{
    switch( w )
    {
        case 1:week = "Mon";break;
        case 2:week = "Tue";break;
        case 3:week = "Wed";break;
        case 4:week = "Thu";break;
        case 5:week = "Fri";break;
        case 6:week = "Sat";break;
        case 7:week = "Sun";break;
        default: week = "error";break;
    }
}

main.c:

#include "reg52.h"  
#include "intrins.h"  
#include "stdio.h"  
#include "LCD1602.h"  
#include "ds1302.h"  
  
bit flag;       //定时500ms标志位  
  
//定义初始时间,秒、分、时、日、月、星期、年  
unsigned char code InitTime[7] = { 0x55,0x15,0x08,0x21,0x05,0x04,0x21 };      
  
//存储获取时间的数组  
unsigned char CurrentTime[7];  
  
//显示字符存储变量  
unsigned char DisplayString[20];    
  
void Timer0_Init(void)  
{  
    TMOD |= 0x01;       //配置定时器工作模式  
    TH0 = 0x4C;  
    TL0 = 0x00;         //定时50ms初值    
    TR0 = 1;  
    ET0 = 1;  
    EA = 1;                 //启动定时器,开定时器中断和总中断  
}   
  
  
void main()  
{  
    LCD_Init();             //初始化LCD1602  
    Timer0_Init();      //初始化定时器  
    DS1302_Init(InitTime);  //初始化时钟  
      
    while(1)  
    {         
        if( flag )      //flag=1时,即500ms定时时间到时  
        {  
            flag = 0;       //标志位清零  
            GetCurrentTime(CurrentTime);    //获取当前时间  
              
            DisplayString[0] = '2';DisplayString[1] = '0';  
              
            //取出年的十位、个位,然后转换成对应数字的ASCII码  
            DisplayString[2] = (CurrentTime[6]>>4)+'0';       DisplayString[3] = (CurrentTime[6]&0x0F)+'0';                 
            DisplayString[4] = '-';  
              
            //取出月的十位、个位,然后转换成对应数字的ASCII码  
            DisplayString[5] = (CurrentTime[4]>>4)+'0';       DisplayString[6] = (CurrentTime[4]&0x0F)+'0';         
            DisplayString[7] = '-';  
              
            //取出日的十位、个位,然后转换成对应数字的ASCII码  
            DisplayString[8] = (CurrentTime[3]>>4)+'0';       DisplayString[9] = (CurrentTime[3]&0x0F)+'0';         
            DisplayString[10] = '\0';       //结束  
              
            //取出时的十位、个位,然后转换成对应数字的ASCII码  
            DisplayString[11] = (CurrentTime[2]>>4)+'0';      DisplayString[12] = (CurrentTime[2]&0x0F)+'0';        
            DisplayString[13] = ':';  
              
            //取出分的十位、个位,然后转换成对应数字的ASCII码  
            DisplayString[14] = (CurrentTime[1]>>4)+'0';      DisplayString[15] = (CurrentTime[1]&0x0F)+'0';        
            DisplayString[16] = ':';  
              
            //取出秒的十位、个位,然后转换成对应数字的ASCII码  
            DisplayString[17] = (CurrentTime[0]>>4)+'0';      DisplayString[18] = (CurrentTime[0]&0x0F)+'0';        
            DisplayString[19] = '\0';       //结束  
                        
                        WeekTransform( ( (CurrentTime[5]&0x0F) ) ); //将星期转换成对应的英文
              
            LCD_WriteString(1,2,DisplayString);  
            LCD_WriteString(2,2,DisplayString+11);                              
        LCD_WriteString(2,12,week);            //分两行显示
        }         
    }  
}  
  
void Timer0(void) interrupt 1 using 1  
{  
    static unsigned int i;    
    TH0 = 0x4C;  
    TL0 = 0x00;         //重新赋初值  
    i++;  
    if( i == 10 )       //10次50ms就到了500ms  
    {  
        i=0;  
        flag = 1;           //500ms定时到,标志位置1,由main函数置0  
    }  
  
}

DS1302.mp4

所属系列

从当前文章继续阅读它所在合集中的前后内容。

相关文章

优先推荐同专题、同标签和同作者内容,补足热门文章。

评论 0

登录 后参与评论

评论

成为第一个评论的人