[应用相关] STM32学习大团建-基于STM32F103的DS1302的时钟

[复制链接]
1001|0
 楼主| xyz549040622 发表于 2023-11-13 23:41 | 显示全部楼层 |阅读模式
本帖最后由 xyz549040622 于 2023-11-13 23:54 编辑

使用的DS1302模块:
1607355-20200927153134790-899922947.png 1607355-20200927153219098-662741220.png
  DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。工作电压宽达2.5~5.5V。采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。DS1302的外部引脚分配如下图所示。DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。
1607355-20200927152928530-1923218802.png
1607355-20200927152936611-51971453.png
  DS1302的一条指令一个字节8位,其中第七位(即最高位)是固定1,这一位如果是0的话,那写进去是无效的。第六位是选择RAM还是CLOCK的,我前边说过,我们这里主要讲CLOCK时钟的使用,它的RAM功能我们不用,所以如果选择CLOCK功能,第六位是0,如果要用RAM,那第六位就是1。从第五到第一位,决定了寄存器的5位地址,而第零位是读写位,如果要写,这一位就是0,如果要读,这一位就是1,如图15-9所示。
20180528220623239.png
        DS1302时钟的寄存器,其中8个和时钟有关的,5位地址分别是00000一直到00111这8个地址,还有一个寄存器的地址是01000,这是涓流充电所用的寄存器,我们这里不讲。在DS1302的数据手册里的地址,直接把第七位、第六位和第零位值给出来了,所以指令就成了80H、81H那些了,最低位是1,那么表示读,最低位是0表示写,如图15-10所示。
1607355-20200927153034145-1788690258.png
        寄存器一:最高位CH是一个时钟停止标志位。如果我们的时钟电路有备用电源部分,上电后,我们要先检测一下这一位,如果这一位是0,那说明我们的时钟在系统掉电后,由于备用电源的供给,时钟是持续正常运行的;如果这一位是1,那么说明我们的时钟在系统掉电后,时钟部分不工作了。若我们的Vcc1悬空或者是电池没电了,当我们下次重新上电时,读取这一位,那这一位就是1,我们可以通过这一位判断时钟在单片机系统掉电后是否持续运行。剩下的7位高3位是秒的十位,低4位是秒的个位,这里注意再提一次,DS1302内部是BCD码,而秒的十位最大是5,所以3个二进制位就够了。
        寄存器二:bit7没意义,剩下的7位高3位是分钟的十位,低4位是分钟的个位。
        寄存器三:bit7是1的话代表是12小时制,是0的话代表是24小时制,bit6固定是0,bit5在12小时制下0代表的是上午,1代表的是下午,在24小时制下和bit4一起代表了小时的十位,低4位代表的是小时的个位。
        寄存器四:高2位固定是0,bit5和bit4是日期的十位,低4位是日期的个位。
        寄存器五:高3位固定是0,bit4是月的十位,低4位是月的个位。
        寄存器六:高5位固定是0,低3位代表了星期。
        寄存器七:高4位代表了年的十位,低4位代表了年的个位。这里特别注意,这里的00到99年指的是2000年到2099年。
        寄存器八:bit7是一个保护位,如果这一位是1,那么是禁止给任何其他的寄存器或者那31个字节的RAM写数据的。因此在写数据之前,这一位必须先写成0。
  1. #include"DS1302.h"

  2. /*****************************************
  3. * 函数名:void DS1302_GPIOInit(void)
  4. * 描述  :    DS1302 GPIO配置
  5. * 输入  :
  6. * 输出  :无
  7. * 调用  :
  8.         CLK---PB5,
  9.         IO--->PB6,
  10.         RES--->PB7,
  11. *************************************/
  12. void DS1302_GPIOInit(void)
  13. {
  14.   GPIO_InitTypeDef GPIO_InitStructre;
  15.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);            /*open GPIO  clock*/
  16.   GPIO_InitStructre.GPIO_Pin= GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
  17.   GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz;
  18.   GPIO_InitStructre.GPIO_Mode=GPIO_Mode_Out_PP;
  19.   GPIO_Init(DS1302_PORT, &GPIO_InitStructre);
  20. }
  21. /*****************************************
  22. * 函数名:void DS1302_IO_GPIO(void)
  23. * 描述  :    DS1302 之 IO GPIO 输入输出配置
  24. * 输入  :FLAG标志位
  25. * 输出  :无
  26. * 调用  :OUT:表示输出,IN:表示输入
  27.           FLAG:
  28. *************************************/
  29. void DS1302_IO_GPIO(uchar FLAG)
  30. {
  31.   GPIO_InitTypeDef GPIO_InitStructre;
  32.   //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);            /*open GPIO  clock*/
  33.     /**********配置数据IO端口 输出 **********/
  34.     if(FLAG==0x01)
  35.   {
  36.     GPIO_InitStructre.GPIO_Pin= GPIO_Pin_6;//配置IO_GPIO
  37.   GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz;
  38.   GPIO_InitStructre.GPIO_Mode=GPIO_Mode_Out_PP;
  39.   GPIO_Init(DS1302_PORT, &GPIO_InitStructre);
  40.   }
  41.     /**********配置数据IO端口 输入**********/
  42.     else if(FLAG==0x00)
  43.   {
  44.      GPIO_InitStructre.GPIO_Pin= GPIO_Pin_6;//配置IO_GPIO
  45.    GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz;
  46.    GPIO_InitStructre.GPIO_Mode=GPIO_Mode_IPU;  //配置上拉输入
  47.    GPIO_Init(DS1302_PORT, &GPIO_InitStructre);
  48.    }
  49. }
  50.   /*****************************************
  51. * 函数名:void DS1302_delay(u8 dd)
  52. * 描述  :简单延时
  53. * 输入  :
  54. * 输出  :无
  55. * 调用  :
  56. *************************************/
  57. void DS1302_delay(u8 dd)
  58. {
  59.     u8 i;
  60.     for(;dd>0;dd--)
  61.   for(i=110;i>0;i--);
  62. }

  63.   /*****************************************
  64. * 函数名:void DS1302_Write(uchar add,uchar dat)
  65. * 描述  :DS1302写指令和数据
  66. *  输入  :add:发送地址,dat:所在数据
  67. * 输出  :无
  68. * 调用  :
  69. *************************************/
  70. void DS1302_Write(uchar add,uchar dat)
  71. {
  72. uchar i,temp1,temp2;
  73. temp1=add;
  74. temp2=dat;
  75. RES_Set_1;//RET=1;
  76. //发送地址
  77. for(i=0;i<8;i++)
  78. {
  79.         if(temp1&0x01)
  80.          {IO_Set_1;  }     //IO=1;
  81.         else
  82.         { IO_Reset_0;}   //IO=0;
  83.         temp1=temp1>>1;
  84.         CLK_Set_1;            //CLK=1;
  85.         DS1302_delay(2);
  86.         CLK_Reset_0;    //CLK=0;
  87.   }

  88. //发送数据
  89. for(i=0;i<8;i++)
  90.     {
  91.         /*IO=(temp2>>i)&0x01;这一句代替下面屏蔽的内容  */
  92.         if(temp2&0x01)
  93.          {IO_Set_1;  }     //IO=1;
  94.         else
  95.          { IO_Reset_0;}    //IO=0;
  96.             temp2=temp2>>1;
  97.             CLK_Set_1;            //CLK=1;
  98.             DS1302_delay(2);
  99.             CLK_Reset_0;    //CLK=0;
  100.     }
  101. RES_Reset_0;// RET=0;
  102. }




  103. /*****************************************
  104. * 函数名:uchar DS1302_Read(uchar add)
  105. * 描述  :DS1302读数据
  106. *  输入  :add:发送所在地址
  107. * 输出  :
  108. * 调用  :
  109. *************************************/
  110. uchar DS1302_Read(uchar add)
  111. {
  112.   uchar i,suf,temp,mm,nn,value;
  113.    temp=add;
  114.    RES_Set_1;//RET=1;
  115.     //写地址
  116.   for(i=0;i<8;i++)
  117.       {
  118.        if(temp&0x01)
  119.        {IO_Set_1;  }     //IO=1;
  120.       else
  121.          { IO_Reset_0;}    //IO=0;
  122.       temp=temp>>1;
  123.         CLK_Set_1;            //CLK=1;
  124.         DS1302_delay(2);
  125.         CLK_Reset_0;    //CLK=0;
  126.       }
  127. //读数据

  128. DS1302_IO_GPIO(IN);//配置IO为输入
  129.   for(i=0;i<8;i++)
  130.     {
  131.      suf=suf>>1;//读数据变量
  132.      if(IO_Read)    //IO=1
  133.      {
  134.          suf=suf|0x80;
  135.      }
  136.      else     //IO=0
  137.      {
  138.      suf=suf&0x7f;
  139.      }

  140.         CLK_Set_1;            //CLK=1;
  141.         DS1302_delay(2);
  142.         CLK_Reset_0;    //CLK=0;
  143.     }
  144.     RES_Reset_0;    // RET=0;

  145. DS1302_IO_GPIO(OUT);//配置IO为输出,恢复正常状态
  146. //数据处理转化十进制
  147. mm=suf/16;
  148. nn=suf%16;
  149. value=mm*10+nn;
  150. return value;
  151. }
  152. /*****************************************
  153. * 函数名:void DS1302_SetTime(uchar *ad)
  154. * 描述  :DS1302 写入设置时间
  155. *  输入  :add:发送所在地址
  156. * 输出  :
  157. * 调用  :
  158. *************************************/
  159. void DS1302_SetTime(uchar *ad)
  160.   {
  161.    DS1302_Write(0x8e,0x00);   //WP=0 允许数据写入DS1302
  162. /**********以下对时分秒的初始化*************/
  163.         DS1302_Write(ds1302_sec_addr,ad[5]);  //秒
  164.         DS1302_Write(ds1302_min_addr,ad[4]);   //分
  165.         DS1302_Write(ds1302_hour_addr,ad[3]);   //时
  166.       /**********以下对年月日的初始化*************/
  167.      DS1302_Write(ds1302_day_addr,ad[2]);
  168.    DS1302_Write(ds1302_month_addr,ad[1]);
  169.       DS1302_Write(ds1302_year_addr,ad[0]);

  170.      DS1302_Write(0x8e,0x80);   //0x8e控制字节地址,bit7=WP WP=1 禁止数据写入DS1302
  171.   }


  172. /*****************************************
  173. * 函数名: void DS1302_OFF(void)
  174. * 描述  :DS1302时间禁止走时
  175. *  输入  :
  176. * 输出  :
  177. * 调用  :
  178. *************************************/
  179.   void DS1302_OFF(void)
  180.   {
  181.    uchar temp;
  182.    temp=DS1302_Read(0x81);//读取表地址时间
  183.    DS1302_Write(0x8e,0x00);//WP=0 允许数据写入DS1302
  184.    temp=temp|(1<<7);
  185.    DS1302_Write(0x80,temp);//WP=1 禁止数据写入DS1302

  186.   }
  187. /*****************************************
  188. * 函数名: void DS1302_ON(void)
  189. * 描述  :DS1302时间开始运行,走时
  190. *  输入  :
  191. * 输出  :
  192. * 调用  :
  193. *************************************/
  194.   void DS1302_ON(void)
  195.   {
  196.    uchar temp;
  197.    temp=DS1302_Read(0x81);
  198.    DS1302_Write(0x8e,0x00);//WP=0 允许数据写入DS1302
  199.    temp=temp|(0<<7);
  200.    DS1302_Write(0x80,temp);//WP=0 允许数据写入DS1302

  201.   }






  202. /*****************************************
  203. * 函数名:void DS1302_init(uchar *time)
  204. * 描述  :    DS1302初始化
  205. * 输入  :无
  206. * 输出  :无
  207. * 调用  :
  208. *************************************/
  209. void DS1302_init(uchar *time)
  210. {
  211.     DS1302_GPIOInit();//GPIO初始化配置
  212.     DS1302_delay(2);
  213.   RES_Reset_0; //RET=0;
  214.   CLK_Reset_0;// CLK=0;
  215.     //下面是对DS1302启动电池,不掉电   设置时间
  216.     DS1302_Write(0x8e,0x00);//WP=0 允许数据写入DS1302
  217.     DS1302_Write(0x90,0xA7);//充电(1个二极管+8K电阻)
  218.     DS1302_Write(0x8E,0X80);//开启保护 WP=1
  219.     if(DS1302_Read(0X81)&0X80)//查询DS302时钟是否启动,如果时钟停止走动:启动时钟+初始化时钟
  220.     {
  221.         DS1302_SetTime(time);//设置设置初始时钟
  222.     }
  223.     //否则跳过

  224. }
  225. /*****************************************
  226. * 函数名:void DS1302_Readtime(void)
  227. * 描述  :    DS1302时间读出
  228. * 输入  :无
  229. * 输出  :无
  230. * 调用  :
  231. *************************************/
  232. void DS1302_Readtime(void)
  233. {
  234.     label2[0]=DS1302_Read( 0x8D)/10;      //年:十位
  235.     label2[1]=DS1302_Read( 0x8D)%10;      //年:个位
  236.     label2[2]='/';
  237.     label2[3]=DS1302_Read( 0x89)/10;     //月 :
  238.     label2[4]=DS1302_Read( 0x89)%10;     //月 :
  239.     label2[5]='/';
  240.     label2[6]=DS1302_Read( 0x87)/10;     //日
  241.     label2[7]=DS1302_Read( 0x87)%10;     //日
  242.     label2[8]=DS1302_Read( 0x85)/10;     //时
  243.     label2[9]=DS1302_Read( 0x85)%10;     //时
  244.     label2[10]=':';
  245.     label2[11]=DS1302_Read( 0x83)/10;     //读分
  246.     label2[12]=DS1302_Read( 0x83)%10;     //读分
  247.     label2[13]=':';
  248.     label2[14]=DS1302_Read( 0x81)/10;     //读秒
  249.     label2[15]=DS1302_Read( 0x81)%10;     //读秒
  250. }
  1. #ifndef __DS1302_H__
  2. #define __DS1302_H__
  3. #include <stm32f10x.h>
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6. /***DS1302时钟芯片****************************/
  7. //CLK--->PB5
  8. //IO---->PB6
  9. //RES--->PB7
  10. /****************************/

  11. #define OUT   0x01
  12. #define IN    0x00
  13. extern uchar label2[16];//时间存放数组
  14. //extern uchar Settime[6]={0x17,0x04,0x18,0x16,0x57,0x30}; //设置时间函数
  15. #define DS1302_PORT   GPIOB

  16. #define CLK_Reset_0  GPIOB->BRR=GPIO_Pin_5
  17. #define CLK_Set_1    GPIOB->BSRR=GPIO_Pin_5

  18. #define IO_Reset_0   GPIOB->BRR=GPIO_Pin_6
  19. #define IO_Set_1     GPIOB->BSRR=GPIO_Pin_6

  20. #define RES_Reset_0  GPIOB->BRR=GPIO_Pin_7
  21. #define RES_Set_1    GPIOB->BSRR=GPIO_Pin_7

  22. #define IO_Read   GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)
  23. /*************************/
  24. #define Time_24_Hour    0x00    //24小时制
  25. #define Time_Start     0x00    //开始走时
  26. //DS1302寄存器操作指令定义时间地址
  27. #define ds1302_sec_addr   0x80       //秒
  28. #define ds1302_min_addr   0x82       //分
  29. #define ds1302_hour_addr  0x84       //时
  30. #define ds1302_day_addr   0x86       //日
  31. #define ds1302_month_addr 0x88       //月
  32. #define ds1302_year_addr  0x8c       //年
  33. /********************/
  34. void DS1302_GPIOInit(void);
  35. void DS1302_IO_GPIO(uchar FLAG);//配置IO的方向
  36. void DS1302_delay(u8 dd);
  37. void DS1302_Write(uchar add,uchar dat);
  38. uchar DS1302_Read(uchar add);
  39. void DS1302_SetTime(uchar *ad);
  40. void DS1302_OFF(void);
  41. void DS1302_ON(void);
  42. void DS1302_init(uchar *time);
  43. void DS1302_Readtime(void);



  44. #endif
  1. #include "stm32f10x.h"
  2. #include "led.h"
  3. #include "key.h"
  4. #include "usart1.h"
  5. #include "delay.h"
  6. #include "DS1302.h"

  7. #define AHB_INPUT 72

  8. unsigned char uart1_buf[11]={0};
  9. volatile u32 time; // ms 计时变量

  10. u16    t=0,mode=0,flag=0;
  11. u8 label2[16]; //时间存放数组显示格式
  12. u8 Settime[6]={0x20,0x09,0x16,0x20,0x59,0x50};  // 初始时间设置: 年 月 日  时 分 秒

  13. int main(void)
  14. {
  15.     int tt = 0;

  16.     SystemInit();    // 配置系统时钟为72M
  17.     delay_init();
  18.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);            //配置完中断向量表以后才能初始化其他东西
  19.     uart_init(9600);

  20.     TIM2_NVIC_Configuration();                                                     // TIM2 定时配置
  21.     TIM2_Configuration();
  22.     START_TIME;                                                                                     // TIM2 开始计时

  23.     DS1302_init(Settime);                                                                //时间初始化
  24.   DS1302_SetTime(Settime);                                                        //设置初始时间


  25.     while(1)
  26.   {
  27.         tt++;
  28.         if(tt>=3200000)
  29.         {
  30.                 tt = 0;
  31.             DS1302_Readtime();
  32.         printf("%lld,",num);
  33.                 printf("20");
  34.                 printf("%d",label2[0]);
  35.                 printf("%d",label2[1]);
  36.                 printf("%c",label2[2]);
  37.                 printf("%d",label2[3]);
  38.                 printf("%d",label2[4]);
  39.                 printf("%c",label2[5]);
  40.                 printf("%d",label2[6]);
  41.                 printf("%d, ",label2[7]);

  42.                 printf("%d",label2[8]);
  43.                 printf("%d",label2[9]);
  44.                 printf("%c",label2[10]);
  45.                 printf("%d",label2[11]);
  46.                 printf("%d",label2[12]);
  47.                 printf("%c",label2[13]);
  48.                 printf("%d",label2[14]);
  49.                 printf("%d, ",label2[15]);
  50.                 printf("%.2f, %.2f ",PM25,PM10);
  51.                 printf("%c",0x0d);
  52.                 printf("%c",0x0a);
  53.         }

  54.   }
  55. }

您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群: 嵌入式系统arm初学者 224636155←← +→→点击-->小 i 精品课全集,21ic公开课~~←←→→点击-->小 i 精品课全集,给你全方位的技能策划~~←←

2841

主题

19330

帖子

110

粉丝
快速回复 在线客服 返回列表 返回顶部