ds1302时钟模块的工作原理_ds8201说明书

ds1302时钟模块的工作原理_ds8201说明书【单片机自学】ds1302时钟芯片DS1302实时时钟实验现象将程序烧录到单片机中后,lcd1602显示屏将从预设时间开始进行时钟功能。在lcd1602显示屏第一行分别显示年,月,日,星期;在第二行显示时,分,秒。DS1302介绍ds130

【单片机自学】ds1302时钟芯片   DS1302实时时钟   实验现象   将程序烧录到单片机中后,lcd1602显示屏将从预设时间开始进行时钟功能。   在lcd1602显示屏第一行分别显示年,月,日,星期;在第二行显示时,分,秒。   
ds1302时钟模块的工作原理_ds8201说明书
ds1302时钟模块的工作原理_ds8201说明书   DS1302介绍   ds1302简介   DS1302 是 DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和 31 字节静态 RAM,通过简单的串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整。   DS1302 与单片机之间可以通过三根数据线进行同步串行的方式进行通信:RES,IO数据,SCLK串行时钟。实时时钟具有能计算 2100 年之前的秒、分、时、日、星期、月、年的能力,还有闰年调整的能力。   引脚   
ds1302时钟模块的工作原理_ds8201说明书   Vcc2 主电源   Vcc1 备用电源   X 32.768khz晶振引脚   SCLK串行时钟   I/O 数据   CE(res) 复位引脚   GND 接地   工作流程   将预设的时间以bcd码形式写入ds1302的寄存器中,单片机开启后ds1302将从这个时间开始运作   ds1302开始运作后,寄存器里的值会自己按时间变化。不断地取出其中的值,并由bcd码转化成十进制   取到的十进制按一定格式打印在1602显示屏上   从工作流程可知要使ds1302运转,首先要了解ds1302中的寄存器,然后设计写入数据与读取数据函数,最后进行调用。   寄存器   控制寄存器   在对ds1302进行读写操作的时候,第一步要向ds1302发送控制命令,用于后续对应的操作。在ds1302中,有这么一种寄存器,用于存放控制命令,这样ds1302就可以根据我们发送的指令,进行对应的操作。   一个控制命令有8位,输入一个八位的命令就可以进行操作。例如想要读取秒寄存器,就需要向ds1302发送命令,例如想要写秒寄存器,就需要向ds1302发送命令。   详情见以下表格:
ds1302时钟模块的工作原理_ds8201说明书   时间寄存器
ds1302时钟模块的工作原理_ds8201说明书
ds1302时钟模块的工作原理_ds8201说明书   在ds1302中有着以上这些寄存器,用于保存时间或者其他数据。在秒,分,时,日,月,星期,年寄存器中,用bcd码保存着数据,高四位用于保存十进制的十位,低四位用于保存十进制的个位。例如想保存12月21日,就分别向日寄存器写0x21(00,高四位2,低四位1),向月寄存器写0x12。   秒的范围是0-59,因此对于高四位,其实用三位就足够了(最大为5,101),最高的那一位是ds1302的开关,为0时才能工作。   小时有12与24两种。最高位为0时表示24进制,此时剩下的位全是表示时间的数据;最高位为1时,表示12进制,此时上图的A/P表示上午或者下午。   写保存寄存器的最高位WP是写入寄存器的通路的开关。当WP为0时,才可以向ds1302中写入数据。   读写与时序   写   前面提到,ds1302使用三根通信线CE,IO,SCLK。如何使用这三根线写入芯片呢?   IO用于接收一位数据,低电平为0,高电平为1。要向ds1302写数据,要做以下操作:   将CE至高,SCLK置低   将要写入的数据的最低位存入IO   将SCLK置高,这样产生一个上升沿,上升沿会使IO数据写入芯片,置高一段时间后置低   将数据右移一位(使次低位变成最低位)   重复2-4,直到数据写完   要写数据,首先要用2-5步骤写入对应的控制命令,再用相同的方法写要写的数据   完成命令与数据输入后,CE置低   读   与写不同,在输入了读的执行命令后,会在SCLK的下降沿将对应寄存器的值从低位开始传给IO,因此,读寄存器的操作是:   按照写数据的方法,将执行指令写入芯片   传完8位指令后,在SCLK为低电平时使用变量保存IO的状态,然后置高电平   循环读取八次,会读取到从低到高八位数据。将这八次得到的数据做成一个八位的变量   返回得到的这个八位变量(是bcd码)   ds1302的GPIO   由图可知,IO,CE,SCLK分别连接着P34,35,36接口,因此要操作IO,CE,SCLK,在代码层仅需要对P34,35,36进行操作就行。   代码   ds1302.c   涉及到的操作最核心的部分是对ds1302的读与写,思路已在上文提及,读函数与写函数代码如下:   #include <REGX52.H>   #include “intrins.h”   //封装GPIO   #define CE P3_5   #define IO P3_4   #define SCLK P3_6   /*   * @brief  向ds1302芯片的寄存器写一个字节数据   * @details     提供控制指令与数据,将数据按位赋给IO,在SCLK出现上升沿的时候,   IO的值会发送给ds1302,先将控制命令用八次循环按位写入IO,经历   SCLK八次上升沿后命令送达,再用同样的方式将数据送入DS1302。   在整个期间,CE(RST)置高电平   * @param addr 写入的控制指令   * @param dat   向对应的寄存器要写的数据   * @retval  无   */   void ds1302_write_byte(unsigned char addr,unsigned char dat){   unsigned char i;   CE = 0;   _nop_();   CE = 1;//将CE从低电平改为高电平   _nop_();   SCLK = 0;//SCLK置低电平   _nop_();   for (i = 0;i<8;i++){//输入指令   IO = addr&0x01; //取出最低位   addr = addr>>1; //右移一位,次低位变最低位   SCLK = 1;   //产生上升沿,数据传入后再置低电平   _nop_();   SCLK = 0;   _nop_();   }   for (i = 0;i<8;i++){//输入数据   IO = dat&0x01;   dat = dat>>1;   SCLK = 1;   _nop_();   SCLK = 0;   _nop_();   }   CE = 0;   _nop_();   }   /*   * @brief  读取ds1302寄存器数据.   * @details     提供控制指令选择要读的寄存器之后,先将控制命令写入芯片,   此时sclk会完成八个上升沿,七个下降沿。   读的数据会在第八个下降沿开始返回,因此在将最后一个控制命令   的位数据写入后,置低电平时就要从IO开始读。   读到的时间数据是BCD码   * @param addr 写入的控制指令   * @retval  读出的寄存器数据   */   unsigned char ds1302_read_byte(unsigned char addr){   unsigned char i=0,temp=0,value=0;   CE = 0;   _nop_();   CE = 1;   _nop_();   SCLK = 0;   _nop_();   for (i = 0;i<8;i++){ //输入指令   IO = addr&0x01;   addr = addr>>1;   SCLK = 1;   _nop_();   SCLK = 0;   _nop_();   }   for (i = 0;i<8;i++){ //下降沿读取数据   temp = IO;   /*先将 value 右移 1 位,然后 temp 左移 7 位, 最后或运算   这样可以将按低位拿到的数据变成八位数据   例如寄存器里为,那么value在循环中的值是00000000,   00000000,00000000,,0……*/   value=(temp<<7)|(value>>1);   SCLK=1;   _nop_();   SCLK=0;   _nop_();   }   CE = 0;   _nop_();   /*   下面的代码在写函数里面没有,看官方教程解释也没搞明白,   删掉运行测试也没有异常…   */   SCLK=1;   _nop_();   IO = 0;   _nop_();   IO = 1;   _nop_();   return value;   }   不仅需要读写操作的函数,还需要有调用这些函数的调用者。上文说过最开始要初始化时间,初始化后再继续不断读取。初始化的时间是以bcd码的形式保存在数组中的,得到的数据也是bcd码的形式。因此,还要写一个初始化函数,将初始值数组的值依次写入秒,分,时,日,月,星期,年寄存器;还要一个读取函数,依次读取这七个寄存器的值到数组。   代码如下:   //—DS1302 写入和读取时分秒的地址命令   //—秒分时日月周年 最低位读写位;   unsigned char gREAD_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};   unsigned char gWRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};   //—DS1302 时钟初始化 2022 年 8 月 31 日星期三 17 点 22 分 25 秒。   //—存储顺序是秒分时日月周年,存储格式是用 BCD 码—//   unsigned char gDS1302_TIME[7] = {0x25, 0x22, 0x17, 0x31, 0x08, 0x03,  0x22};   /*   * @brief  初始化时钟时间   * @details     将时间数组保存的值用写函数写入ds1302   * @param  无   * @retval  无   */   void ds1302_init(){   unsigned char i;   ds1302_write_byte(0x8E,0X00);//在写寄存器之前,关闭写寄存器保护   for (i = 0;i<7;i++){   ds1302_write_byte(gWRITE_RTC_ADDR[i],gDS1302_TIME[i]);   }   ds1302_write_byte(0x8E,0X80);//重新开启保护   }   /*   * @brief  将寄存器中的时间写入数组   * @details     将时间数组保存的值用写函数写入ds1302   * @param  无   * @retval  无   */   void ds1302_read_time(void){   unsigned char i=0;   for(i=0;i<7;i++) {   gDS1302_TIME[i]=ds1302_read_byte(gREAD_RTC_ADDR[i]);   }   }   整个ds1302.c代码如下:   #include <REGX52.H>   #include “intrins.h”   //封装GPIO   #define CE P3_5   #define IO P3_4   #define SCLK P3_6   //—DS1302 写入和读取时分秒的地址命令   //—秒分时日月周年 最低位读写位;   unsigned char gREAD_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};   unsigned char gWRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};   //—DS1302 时钟初始化 2022 年 8 月 31 日星期三 17 点 22 分 25 秒。   //—存储顺序是秒分时日月周年,存储格式是用 BCD 码—//   unsigned char gDS1302_TIME[7] = {0x25, 0x22, 0x17, 0x31, 0x08, 0x03,  0x22};   /*   * @brief  向ds1302芯片的寄存器写一个字节数据   * @details     提供控制指令与数据,将数据按位赋给IO,在SCLK出现上升沿的时候,   IO的值会发送给ds1302,先将控制命令用八次循环按位写入IO,经历   SCLK八次上升沿后命令送达,再用同样的方式将数据送入DS1302。   在整个期间,CE(RST)置高电平   * @param addr 写入的控制指令   * @param dat   向对应的寄存器要写的数据   * @retval  无   */   void ds1302_write_byte(unsigned char addr,unsigned char dat){   unsigned char i;   CE = 0;   _nop_();   CE = 1;//将CE从低电平改为高电平   _nop_();   SCLK = 0;//SCLK置低电平   _nop_();   for (i = 0;i<8;i++){//输入指令   IO = addr&0x01; //取出最低位   addr = addr>>1; //右移一位,次低位变最低位   SCLK = 1;   //产生上升沿,数据传入后再置低电平   _nop_();   SCLK = 0;   _nop_();   }   for (i = 0;i<8;i++){//输入数据   IO = dat&0x01;   dat = dat>>1;   SCLK = 1;   _nop_();   SCLK = 0;   _nop_();   }   CE = 0;   _nop_();   }   /*   * @brief  读取ds1302寄存器数据.   * @details     提供控制指令选择要读的寄存器之后,先将控制命令写入芯片,   此时sclk会完成八个上升沿,七个下降沿。   读的数据会在第八个下降沿开始返回,因此在将最后一个控制命令   的位数据写入后,置低电平时就要从IO开始读。   读到的时间数据是BCD码   * @param addr 写入的控制指令   * @retval  读出的寄存器数据   */   unsigned char ds1302_read_byte(unsigned char addr){   unsigned char i=0,temp=0,value=0;   CE = 0;   _nop_();   CE = 1;   _nop_();   SCLK = 0;   _nop_();   for (i = 0;i<8;i++){ //输入指令   IO = addr&0x01;   addr = addr>>1;   SCLK = 1;   _nop_();   SCLK = 0;   _nop_();   }   for (i = 0;i<8;i++){ //下降沿读取数据   temp = IO;   /*先将 value 右移 1 位,然后 temp 左移 7 位, 最后或运算   这样可以将按低位拿到的数据变成八位数据   例如寄存器里为,那么value在循环中的值是00000000,   00000000,00000000,,0……*/   value=(temp<<7)|(value>>1);   SCLK=1;   _nop_();   SCLK=0;   _nop_();   }   CE = 0;   _nop_();   SCLK=1;   _nop_();   IO = 0;   _nop_();   IO = 1;   _nop_();   return value;   }   /*   * @brief  初始化时钟时间   * @details     将时间数组保存的值用写函数写入ds1302   * @param  无   * @retval  无   */   void ds1302_init(){   unsigned char i;   ds1302_write_byte(0x8E,0X00);//在写寄存器之前,关闭写寄存器保护   for (i = 0;i<7;i++){   ds1302_write_byte(gWRITE_RTC_ADDR[i],gDS1302_TIME[i]);   }   ds1302_write_byte(0x8E,0X80);//重新开启保护   }   /*   * @brief  将寄存器中的时间写入数组   * @details     将时间数组保存的值用写函数写入ds1302   * @param  无   * @retval  无   */   void ds1302_read_time(void){   unsigned char i=0;   for(i=0;i<7;i++) {   gDS1302_TIME[i]=ds1302_read_byte(gREAD_RTC_ADDR[i]);   }   }   main.c   main程序中要做的是初始化,不断读取得到bcd码形式的时间值,转换成十进制后打印在LCD1602上。代码如下:   /*   实验名称:ds1302时钟   实现现象:从起点时间开始进行实时时钟   首先将保存在数组中的bcd码形式的起始时间值发送到ds1302,然后再在主函数中不断读取   ds1302寄存器中的时间数值,ds1302会不断进行时间增长。主函数读取到实时的时间后,通过   将bcd转换成10进制后打印在lcd1602上。   */   #include “ds1302.h”   #include “LCD1602.h”   extern unsigned char gDS1302_TIME[7];   void main(){   unsigned char time_buf[7];   unsigned char i;   ds1302_init();//初始化 DS1302   LCD_Init();//初始化1602   while(1){   ds1302_read_time();//读取时间到数组   for (i = 0 ; i< 7 ; i++){   time_buf[i]=(gDS1302_TIME[i]/16)*10+gDS1302_TIME[i]%16;//将数组中的bcd形式的值转换成10进制并保存在其他数组中   }   //打印时间   LCD_ShowNum(1,1,20,2);   LCD_ShowNum(1,3,time_buf[6],2);   LCD_ShowChar(1,5,’-‘);   LCD_ShowNum(1,6,time_buf[4],2);   LCD_ShowChar(1,8,’-‘);   LCD_ShowNum(1,9,time_buf[3],2);   LCD_ShowNum(1,15,time_buf[5],1);   LCD_ShowNum(2,1,time_buf[2],2);   LCD_ShowChar(2,3,’:’);   LCD_ShowNum(2,4,time_buf[1],2);   LCD_ShowChar(2,6,’:’);   LCD_ShowNum(2,7,time_buf[0],2);   }   }   其中lcd1602操作的相关代码并不是本人所打,是使用的网络资源因此不在此放出。   备注   本人为51单片机学习者,本文是自己学习的总结。自己水平十分有限。若有错误望请大家多多指教!   本文的截图是在普中科技官方在开发攻略中截的,代码也是跟着官方教程打的,经自己测试没有问题。

2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/62658.html

(0)
上一篇 2024年 8月 28日
下一篇 2024年 8月 28日

相关推荐

关注微信