微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > MCU和DSP > 51单片机-时钟芯片DS1302

51单片机-时钟芯片DS1302

时间:03-22 来源:互联网 点击:
在许多电子设备中,通常会进行一些与时间有关的控制,如果用系统的定时器来设计时钟的话,偶然的掉电或晶振的误差都会造成时间的错乱,更糟糕的是,若完全用程序设计时钟还会占用大量的系统资源,从而严重影响系统的其他功能。为此,很多芯片制造公司都设计出了各种各样的实时时钟芯片。  

常见的时钟芯片有两种。  

一种是体积非常小的表贴是元件,通常用在高端小型手持式仪器或设备中。这种芯片在使用时需要外接备份电池和外部晶振,电池用来保持主系统在意外时为时钟芯片供电,外部晶振用来给时钟芯片所必须的震荡来源。  

另一种体积相对较大,一般为直插式,它的内部有可充电锂电池,同时内部还集成了32.768KHZ的标准晶振。  

DS18B20是由DALLAS公司生产的,采用普通的32.768KHZ。  
DS18B20的内部结构:  


   
DS18B20的读数据时序:  
  


?  
如图的数据序列,左边是低位,右边是高位,在负跳变沿进行读数据,上升沿进行写数据。  
DS18B20的写数据时序:  


   
  
数据在SCLK在上升沿输入,前8位指定访问地址命令,在之后的时钟周期,读操作时输出的数据,写操作时输入数据。时钟脉冲的个数在单字节方式下为8个地址加8个数据。  
DS18B20的控制字:  


   


   
日历时钟寄存器与控制字对照:  


  
日历时钟寄存器:   


   
寄存器功能说明:  


  
万年历程序:     #include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uint i;
sbit SCLK = P1^3;
sbit IO = P1^4;
sbit RST = P1^5;
sbit RS = P1^0;
sbit RW = P1^1;
sbit E = P1^2;

uchar Time_Data[]={'0','1','2','3','4','5','6','7','8','9'};

void delay(uint t){
    int i,j;
    for(i = 0; i < t; i++)
        for(j = 10; j > 0; j--)
            ;
}

void lcd_com(uchar s){
    RS = 0;                    //低电平,写指令
    P2 = s;                    //传数据
    delay(14);                //看时序图,数据需要稳定一段时间
    E = 1;                            //给一个高脉冲,发送命令
    delay(14);                    //如图,高脉冲延时一段时间,确保命令发送
    E = 0;                            //发送结束E置为低电平
}

void lcd_data(uchar s){
    RS = 1;
    P2 = s;
    delay(14);
    E = 1;
    delay(14);
    E = 0;
}

uchar DS_Read(uchar command){
        uchar value;
        RST = 0;
        SCLK = 0;
        RST = 1;
        value = 0x0;
        for(i = 0; i < 8; i++){
                IO = command & 0x01;  //写入控制字
                SCLK = 0;
                SCLK = 1;
                command >>= 1;
        }
        for(i = 0; i < 8; i++){
                SCLK = 1;
                SCLK = 0;
                if(IO)
                        value |= (0x01<<i);         //如果那位是1则value置1
        }
        RST = 0;
        value = value/16*10 + value%16;           //BCD码到十进制的转换
        return value;
}

void DS_Write(uchar command,uchar value){
        RST = 0;
        SCLK = 0;
        RST = 1;
        for(i = 0; i < 8; i++){                  //写控制字
                IO = command & 0x01;
                SCLK = 0;
                SCLK = 1;
                command >>= 1;
        }
        for(i = 0; i < 8; i++){                 //向IO引脚写数据
                IO = value & 0x01;
                SCLK = 0;
                SCLK = 1;
                value >>= 1;
        }
}

void Init_ds(){
        RST = 0;
        SCLK = 0;
        RST = 1;
        DS_Write(0x8E,0x00);  //打开写保护,WP位置0,这样就可以写数据了
        DS_Write(0x84,0x00);  //对日历时钟寄存器的初始化
        DS_Write(0x8c,0x10);
        DS_Write(0x8a,0x05);
        DS_Write(0x88,0x10);
        DS_Write(0x86,0x01);
        DS_Write(0x84,0x04);
        DS_Write(0x82,0x22);
        DS_Write(0x80,0x00);  //启动时钟
        DS_Write(0x8e,0x80);  //禁止寄存器写
}

void Init_lcd(){
         RS = 1;         //先发指令,在初始时刻RS是高,E和RW是低
    E = 0;
    RW = 0;
    lcd_com(0x38);           //设置为16*2显示,5*7点阵,8位数据接口
    lcd_com(0x0f);           //开显示,显示光标,光标闪烁
    lcd_com(0x06);           //读写一个字符后地址指针加一
    lcd_com(0x01);
}

void Display_lcd(uchar y, uchar x, uchar value){
        if(y)
                lcd_com(0x80+0x40+x);   //如果y为1,写在第二行
        else
                lcd_com(0x80+x);
        lcd_data(value);                        //写到LCD602上
}

void main(){
        Init_ds();
        Init_lcd();
        while(1){
                Display_lcd(0,0,'2');
                Display_lcd(0,1,'0');
                Display_lcd(0,2,Time_Data[DS_Read(0x8D)/10]);
                Display_lcd(0,3,Time_Data[DS_Read(0x8D)%10]);
                Display_lcd(0,4,'-');
                Display_lcd(0,5,Time_Data[DS_Read(0x89)/10]);
                Display_lcd(0,6,Time_Data[DS_Read(0x89)%10]);
                Display_lcd(0,7,'-');
                Display_lcd(0,8,Time_Data[DS_Read(0x87)/10]);
                Display_lcd(0,9,Time_Data[DS_Read(0x87)%10]);
                Display_lcd(0,10,'D');
                Display_lcd(0,11,'a');
                Display_lcd(0,12,'y');
                Display_lcd(0,13,':');
                Display_lcd(0,14,Time_Data[DS_Read(0x8b)/10]);
                Display_lcd(0,15,Time_Data[DS_Read(0x8b)%10]);
                Display_lcd(1,0,'C');
                Display_lcd(1,1,'a');
                Display_lcd(1,2,'n');
                Display_lcd(1,3,'u');
                Display_lcd(1,4,'t');
                Display_lcd(1,5,'e');
                Display_lcd(1,6,' ');
                Display_lcd(1,7,Time_Data[DS_Read(0x85)/10]);
                Display_lcd(1,8,Time_Data[DS_Read(0x85)%10]);
                Display_lcd(1,9,':');
                Display_lcd(1,10,Time_Data[DS_Read(0x83)/10]);
                Display_lcd(1,11,Time_Data[DS_Read(0x83)%10]);
                Display_lcd(1,12,':');
                Display_lcd(1,13,Time_Data[DS_Read(0x81)/10]);
                Display_lcd(1,14,Time_Data[DS_Read(0x81)%10]);
        }
}

//2010-10-1 Day:5
//Canute 04:22:00

DS1302中的RAM:



李万鹏

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top