zoukankan      html  css  js  c++  java
  • DS1302基本的读写

    DS1302DALLAS公司的一个时钟芯片,能设置秒、分钟、小时、月、星期、年,且年可以设置到2100年。有时钟/日历寄存器还有31*8位的额外数据暂存寄存器(RAM),可以存储对时间的修正参数或者初始化的标志(前提是DS1302要外接备用电源),如果主机掉电后重新上电时读取RAM中的初始化标志为1的话就不对DS1302初始化了。

     

    说到备用电源,可以用3.3v的锂电池或者电源掉电时间短的话(几小时或一天)则可以使用大电容(0.1F以上)供电,只是貌似电容体积太大。

     

    DS1302是通过三根线控制读写数据的,RST/SCL/IO.

    RST:复位线,所有数据的读写,都需要保持RST1,为0时就会终止当前的数据操作。

    SCL:时钟线,提供数据操作的同步时钟。

         写入数据时,写入数据在SCL=0时可以改变而在SCL=1时要保持不变,即数据会在SCL的上升沿写入到DS1302。数据传输是低位在前,高位在后。

         读取数据时,在SCL=1变为SCL=0之后就可以读取数据(注:在写完寄存器后的一个下降沿就可以读取数据),即数据会在SCL的下降沿出现到IO数据线上。同样数据也是低位在前高位在后。

    IO:数据线,要发送的八位数据,要从最低位一次移到IO数据线上。

            

    时钟/日历寄存器:

    :

         1000..R/W是寄存器地址和读写控制位,R/W1为读,为0为写。后面是寄存器里的读写数据,均是以二进制的BCD码存在的。BCD码,0-9对应0000-1001,十位对应10sec,如59对应数据为,CH1011001。下面几个寄存器数据格式亦是如此。CH=1,代表晶振停振,CH=0,代表晶振起振,时钟要工作的话都需要起振的。

    :

    小时 :

           bit7控制是112小时制,为024小时制,bit51则选择12小时下的PM,为0则是选择24小时的20-23小时段。

    :

    :

    星期 :

    :

    CONTROL :

              WP写保护位,写入时要置WP=0

    还有涓流充电器寄存器,控制锂电池的充电电流。

             DS1302的突发模式是连续读写寄存器,时钟/日历的7个寄存器是必须一下读完的,而其他的寄存器没必要一下读完。

            

             读写时序,贴张图,详见DS1302的资料手册。

     

    突发模式的读写没写,连续读写和普通读写就是控制指令的bit5-bit1全为1bit6控制连续读写时钟/日历或RAM

     

    控制器:stc89c52

    88段共阴数码管,78LS138控制位,74HC573控制数码管的各段,贴上电路图。

     

    下面贴上DS1302的普通读写程序:

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

    *********** Name: DS1302

    ***********               Date: 2014/12/25

    ***********               Com: FairSun

    ***********  LOL

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

     

    #include <reg51.h>

    #include <intrins.h>  //使用_nop_();

     

    sbit SCL = P1^6;

    sbit IO  = P3^5;

    sbit RST = P1^7;

     

    #define H12_24 0x80              //0b1000 0000 bit7112小时

    #define AM_PM 0x20  //12小时模式下,bit51则选中了PM,在24小时模式下,为1则选中了20-24小时段

    #define CH 0x00  //sec设置的最高位,为0则晶振起振,为1则晶振不起振

     

    const unsigned char smg_dp_yin[ 16 ] = {0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef,

                                                                                                                                                0xf7, 0xfc, 0xb9, 0xde, 0xfb, 0xf1};//0. 1. 2. 3......f.

                                                                                                                                                //共阴极,显示小数点

                                                                                                                                                //不显示小数点:  smg_dp_yin[x] | 0x80

                                                                                                                                  //共阳极显示小数点: ~smg_dp_yin[x]

                                                                                                                      //共阳极不显示小数点: ~(smg_dp_yin[x] | 0x80)

     

    const unsigned char smg_8_pos[ 8 ] = { 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; //对应P20,P21,P22,高位都为1,则与的时候P2的其他位不变

    const unsigned char smg_sum = 8;  //8位数码管

     

    unsigned char smg_8_data[ 8 ] = { 0 };

     

    struct HMS{

                  unsigned char hour;

                  unsigned char min;

                  unsigned char sec;

    };

     

    struct MD{

                  unsigned char month;

                  unsigned char date;  //一月的几日

    };

     

    struct YD{

                  unsigned char year;

                  unsigned char day;  //星期几

    };

     

    struct ALLDATE{

                  struct YD yd;

                  struct MD md;

                  struct HMS hms;        

    };

     

    void per_init( void );

    void delay_xms( unsigned int );

    //void Timer0_init( void );

    //void Timer0_server( void );

    void ds1302_delay( void );

    void Display_Time( struct ALLDATE allDate );

    unsigned char DecToBCD(unsigned char mData);

    unsigned char BCDToDec(unsigned char mData);

    struct ALLDATE convertToSetTime(struct ALLDATE allDate);

    struct ALLDATE convertToDisplayTime(struct ALLDATE allDate);

    void ds1302_setTime(struct ALLDATE allDate);

    struct ALLDATE ds1302_readTime( void );

    void ds1302_writeByte(unsigned char mCommand, unsigned char mData);

    unsigned char ds1302_readByte(unsigned char mCommand);

     

    void main(void)

    {

                  struct ALLDATE allDate = { {99, 4}, {12, 14}, {23, 59, 55} };  //设置时间:2099-12-14 星期4 23:59:55

                  per_init();

                  ds1302_setTime(allDate);

                  while( 1 )

                  {

                                allDate = ds1302_readTime();

                                Display_Time(allDate);

                  }

    }

     

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

    **函数名:void delay_xms( unsigned int x )

    **  功能:延时xms

    **  参数:

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

    void delay_xms( unsigned int x )

    {

                  unsigned char j = 0;

                  while( x-- )

                  {

                                while( (j++) < 100 );

                                j = 0;

                  }

    }

     

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

    **函数名:void Per_init( void )

    **  功能:各个外设初始配置

    **  参数:

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

    void per_init( void )

    {

                  P0 = 0xff;

                  P1 = 0xff;

                  P2 = 0xff;

                  P3 = 0xff;         

    }

     

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

    **函数名:void Timer0_init( void )

    **  功能:定时器0初始配置

    **  参数:

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

    /*void Timer0_init( void )

    {

                               

                  TMOD |= 0x01; //设置定时器0的模式为16

                  TH0 = ( 65536-46000 ) / 256;

                  TL0 = (65536-46000) % 256;

                  if( EA != 1 )

                                EA = 1;

                  ET0 = 1;  //打开定时器0的中断

                  TR0 = 0;  //定时器0暂停

    }

     */

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

    **函数名:定时器0的中断服务函数

    **  功能:装初值

    **  参数:

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

    /*void Timer0_server( void ) interrupt 1

    {

                                TH0 = (65536-46000) / 256;

                                TL0 = (65536-46000) % 256;

    }  */

     

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

    **函数名:void Display_Time(void)

    **  功能:显示时间

    **  参数:

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

    void Display_Time(struct ALLDATE allDate)  //显示分钟

    {

                  unsigned char pos;

                  unsigned char *pallDate = (unsigned char *)&allDate;

                  for(pos = 0; pos <= 7; pos+=2)

                  {

                                smg_8_data[pos] = *(pallDate+(pos>>1)) / 10 % 10;

                                smg_8_data[pos+1] = *(pallDate+(pos>>1))%10;

                  }

                  /*smg_8_data[0] = allDate.yd.year / 10 % 10;

                  smg_8_data[1] = allDate.yd.year%10;

                  smg_8_data[2] = allDate.hms.hour / 10 % 10;

                  smg_8_data[3] = allDate.hms.hour%10;

                  smg_8_data[4] = allDate.hms.min / 10 % 10;

                  smg_8_data[5] = allDate.hms.min%10;

                  smg_8_data[6] = allDate.hms.sec / 10 % 10;

                  smg_8_data[7] = allDate.hms.sec%10;          */

                  for( pos = 0; pos < smg_sum; pos++ )

                  {            

                                P2 &= 0xf8;

                                P2 |= smg_8_pos[pos];

                                P0 = smg_dp_yin[smg_8_data[pos]]&0x7f;

                                delay_xms(1);                           

                  }            

    }

     

    void ds1302_delay( void )

    {

                  int i;

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

                  {

                                _nop_();

                  }

    }

     

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

    **函数名:unsigned char DecToBCD(unsigned char mData)

    **  功能:10进制转为BCD

    **  参数: unsigned char mData

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

    unsigned char DecToBCD(unsigned char mData)

    {

                  unsigned char BCD = 0;

                  while(mData >= 10)

                  {

                                mData -= 10;

                                BCD ++;            

                  }

                  BCD <<= 4;

                  BCD |= mData;

                  return BCD;

    }

     

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

    **函数名:unsigned char BCDToDec(unsigned char mData)

    **  功能:BCD码转为10进制

    **  参数: unsigned char mData

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

    unsigned char BCDToDec(unsigned char mData)

    {

                  unsigned char Dec = 0;

                  Dec = mData & 0x0f;  //取得最低位

                  mData = mData & 0x70;  //剔除最高位和最低四位

                  Dec += mData>>1; //先左移1代表*2

                  Dec += mData>>3; //再左移3代表*8,所以总的相当于乘以10

                  return Dec;

    }

     

    /*

    struct ALLDATE convertToSetTime(struct ALLDATE allDate)

    {

                  struct ALLDATE mAllDate;

                  mAllDate.yd.year = ((allDate.yd.year/10)<<4) + (allDate.yd.year%10);

                  mAllDate.yd.day = allDate.yd.day;

                  mAllDate.md.month = ((allDate.md.month/10)<<4) + (allDate.md.month%10);

                  mAllDate.md.date = ((allDate.md.date/10)<<4)  + (allDate.md.date%10);

                  mAllDate.hms.hour = H12_24 + AM_PM + ((allDate.hms.hour/10)<<4) + (allDate.hms.hour%10);

                  mAllDate.hms.min = ((allDate.hms.min/10)<<4) + (allDate.hms.min%10);

                  mAllDate.hms.sec = CH + ((allDate.hms.sec/10)<<4) + (allDate.hms.sec%10);

                  return mAllDate;

    }

     

    struct ALLDATE convertToDisplayTime(struct ALLDATE allDate)

    {

                  struct ALLDATE mAllDate;

                  mAllDate.yd.year = ((allDate.yd.year/10)>>4)*10 + (allDate.yd.year%10);

                  mAllDate.yd.day = allDate.yd.day;

                  mAllDate.md.month = ((allDate.md.month/10)<<4) + (allDate.md.month%10);

                  mAllDate.md.date = ((allDate.md.date/10)<<4)  + (allDate.md.date%10);

                  mAllDate.hms.hour = H12_24 + AM_PM + ((allDate.hms.hour/10)<<4) + (allDate.hms.hour%10);

                  mAllDate.hms.min = ((allDate.hms.min/10)<<4) + (allDate.hms.min%10);

                  mAllDate.hms.sec = CH + ((allDate.hms.sec/10)<<4) + (allDate.hms.sec%10);

                  return mAllDate;      

    } */

     

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

    **函数名:struct ALLDATE convertToSetTime(struct ALLDATE allDate)

    **  功能:将设置的时间转为BCD

    **  参数: struct ALLDATE allDate

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

    struct ALLDATE convertToSetTime(struct ALLDATE allDate)

    {

                  unsigned char loop;

                  struct ALLDATE mAllDate;

                  unsigned char *pallDate = (unsigned char *)&allDate;

                  unsigned char *pmAllDate = (unsigned char *)&mAllDate;

                  for(loop = 0; loop <= 7; loop++)

                  {

                                *(pmAllDate+loop) = DecToBCD(*(pallDate+loop));            

                  }

                  /*mAllDate.yd.year = DecToBCD(allDate.yd.year);

                  mAllDate.yd.day = DecToBCD(allDate.yd.day);

                  mAllDate.md.month = DecToBCD(allDate.md.month);      //((allDate.md.month/10)<<4) + (allDate.md.month%10);

                  mAllDate.md.date = DecToBCD(allDate.md.date);              //((allDate.md.date/10)<<4)  + (allDate.md.date%10);

                  mAllDate.hms.hour = DecToBCD(allDate.hms.hour);//H12_24 + AM_PM +   H12_24 + AM_PM + ((allDate.hms.hour/10)<<4) + (allDate.hms.hour%10);

                  mAllDate.hms.min = DecToBCD(allDate.hms.min);             //((allDate.hms.min/10)<<4) + (allDate.hms.min%10);

                  mAllDate.hms.sec = CH + DecToBCD(allDate.hms.sec);//CH + ((allDate.hms.sec/10)<<4) + (allDate.hms.sec%10); */

                  return mAllDate;

    }

     

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

    **函数名:struct ALLDATE convertToDisplayTime(struct ALLDATE allDate)

    **  功能:将读取的BCD码转为10进制要显示的数据

    **  参数: struct ALLDATE allDate

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

    struct ALLDATE convertToDisplayTime(struct ALLDATE allDate)

    {

                  unsigned char loop;

                  struct ALLDATE mAllDate;

                  unsigned char *pallDate = (unsigned char *)&allDate;

                  unsigned char *pmAllDate = (unsigned char *)&mAllDate;

                  for(loop = 0; loop <= 7; loop ++)

                  {

                                *(pmAllDate+loop) = BCDToDec(*(pallDate+loop));

                  }

                  /*mAllDate.yd.year = (((allDate.yd.year&0x80)>>4)*10) + BCDToDec(allDate.yd.year);           //(((allDate.yd.year&0x80)>>4)*10) +

                  mAllDate.yd.day = BCDToDec(allDate.yd.day);

                  mAllDate.md.month = BCDToDec(allDate.md.month);      //((allDate.md.month/10)<<4) + (allDate.md.month%10);

                  mAllDate.md.date = BCDToDec(allDate.md.date);              //((allDate.md.date/10)<<4)  + (allDate.md.date%10);

                  mAllDate.hms.hour = BCDToDec(allDate.hms.hour);//0x1f&   H12_24 + AM_PM + ((allDate.hms.hour/10)<<4) + (allDate.hms.hour%10);

                  mAllDate.hms.min = BCDToDec(allDate.hms.min);             //((allDate.hms.min/10)<<4) + (allDate.hms.min%10);

                  mAllDate.hms.sec = BCDToDec(allDate.hms.sec);//CH + ((allDate.hms.sec/10)<<4) + (allDate.hms.sec%10); */

                  return mAllDate;       

    }

     

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

    **函数名:void ds1302_setTime(struct ALLDATE allDate)

    **  功能:把时间写入到DS1302

    **  参数: struct ALLDATE allDate

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

    void ds1302_setTime(struct ALLDATE allDate)

    {

                  unsigned char loop;

                  unsigned char *pallDate = (unsigned char *)&allDate;

                  allDate = convertToSetTime(allDate);

                  ds1302_writeByte(0x8e, 0x00);  //control为的最高位wp

                  for(loop = 0; loop <= 6; loop++)

                  {

                                ds1302_writeByte(0x8c-(loop<<1), *(pallDate+loop));  //sec                  

                  }

                  /*ds1302_writeByte(0x8e, 0x00);  //control为的最高位wp

                  ds1302_writeByte(0x8c, allDate.yd.year);  //year

                  ds1302_writeByte(0x8a, allDate.yd.day);  //day

                  ds1302_writeByte(0x88, allDate.md.month);  //month

                  ds1302_writeByte(0x86, allDate.md.date);  //date

                  ds1302_writeByte(0x84, allDate.hms.hour);  //hour

                  ds1302_writeByte(0x82, allDate.hms.min);  //min

                  ds1302_writeByte(0x80, allDate.hms.sec);  //sec            */

    }

     

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

    **函数名:struct ALLDATE ds1302_readTime( void )

    **  功能:从DS1302读取时间信息

    **  参数: struct ALLDATE allDate

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

    struct ALLDATE ds1302_readTime( void )

    {

                  unsigned char loop;

                  struct ALLDATE allDate;

                  unsigned char *pallDate = (unsigned char *)&allDate;

                  for(loop = 0; loop <= 6; loop++)

                  {

                                *(pallDate+loop) = ds1302_readByte(0x8d-(loop<<1));                

                  }

                  /*allDate.yd.year =  ds1302_readByte(0x8d);  //year

                  allDate.yd.day =   ds1302_readByte(0x8b);  //day

                  allDate.md.month = ds1302_readByte(0x89);  //month

                  allDate.md.date =  ds1302_readByte(0x87);  //date

                  allDate.hms.hour = ds1302_readByte(0x85);  //hour

                  allDate.hms.min =  ds1302_readByte(0x83);  //min

                  allDate.hms.sec =  ds1302_readByte(0x81);  //sec  */

                  allDate = convertToDisplayTime(allDate);

                  return allDate;            

    }

     

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

    **函数名:void ds1302_writeByte(unsigned char mCommand, unsigned char mData)

    **  功能:往DS1302写入一个字节

    **  参数: unsigned char mCommand, unsigned char mData

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

    void ds1302_writeByte(unsigned char mCommand, unsigned char mData)

    {

                  int loop;

                  RST = 0;

                  SCL = 0;

                  ds1302_delay();

                  RST = 1;

                  ds1302_delay();

                  for(loop = 0; loop < 8; loop++)

                  {

                                IO = (mCommand>>loop)&0x01;

                                ds1302_delay();

                                SCL = 1;

                                ds1302_delay();

                                SCL = 0;

                                ds1302_delay();                       

                  }

                  for(loop = 0; loop < 8; loop++)

                  {

                                IO = (mData>>loop)&0x01;

                                ds1302_delay();

                                SCL = 1;

                                ds1302_delay();

                                SCL = 0;

                                ds1302_delay();                       

                  }

                  RST = 0; //拉低停止数据传输                                    

    }

     

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

    **函数名:unsigned char ds1302_readByte(unsigned char mCommand)

    **  功能:从DS1302读取一个字节

    **  参数: unsigned char mCommand

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

    unsigned char ds1302_readByte(unsigned char mCommand)

    {

                  unsigned char loop = 0;

                  unsigned char readData = 0;

                  unsigned char temp = 0;

                  RST = 1; //必须置高

                  for(loop = 0; loop < 8; loop++)

                  {

                                IO = (mCommand>>loop)&0x01;

                                SCL = 1;

                                ds1302_delay();

                                SCL = 0;                          

                  }

                  for(loop = 0; loop < 8; loop++)

                  {

                               

                                temp = IO;

                                SCL = 1;

                                ds1302_delay();         

                                SCL = 0;

                                readData += (temp<<loop); 

                  }

                  RST = 0; //拉低停止数据传输

                  return readData;                                   

    }

     

     

     

    不负自己
  • 相关阅读:
    Netty源码解析 -- 内存对齐类SizeClasses
    Netty源码解析 -- 零拷贝机制与ByteBuf
    Netty源码解析 -- ChannelOutboundBuffer实现与Flush过程
    Netty源码解析 -- ChannelPipeline机制与读写过程
    Oracle体系结构概述与SQL解析剖析
    SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理|前后端分离(下)----筑基后期
    SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理(上)----筑基中期
    shiro入门学习--授权(Authorization)|筑基初期
    shiro入门学习--使用MD5和salt进行加密|练气后期
    Shiro入门学习---使用自定义Realm完成认证|练气中期
  • 原文地址:https://www.cnblogs.com/v-BigdoG-v/p/7398658.html
Copyright © 2011-2022 走看看