找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6460|回复: 0
收起左侧

stm32--RTC程序

[复制链接]
ID:72519 发表于 2015-1-23 01:31 | 显示全部楼层 |阅读模式
  1. //程序中的时间(normal time)是根据国际标准时间戳转换为东八区的北京时间(NORMALTIME)。
  2. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3. #ifndef _RTC_H_
  4. #define _RTC_H_
  5. #include "driver_about.h"
  6. #include <time.h>
  7. #include <stdio.h>
  8. #include <string.h>

  9. typedef struct tm NORMALTIME;//时间类型;把不是很友好的西方时间表示形式,转换为我们习惯的表示方式
  10.                       //如:1-12月的表示由原来的0-11改为1-12,0表示星期天改为7表示,国际时间改为东八区时间
  11. typedef time_t    TIMESTAMP;//时间戳类型
  12. void              RTC_Init(NORMALTIME t);
  13. void              RTC_Rst(TIMESTAMP ts);//RTC复位
  14. TIMESTAMP         Time_GetTimeStamp(void); //获取RTC中的时间戳
  15. void              Time_SetTimeStamp(TIMESTAMP ts);//设置RTC中的时间
  16. NORMALTIME        Time_GetTime(void);
  17. void              Time_SetTime(NORMALTIME t);
  18. #endif


  19. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  20. #include "Rtc.h"
  21. /*******************************************************************************
  22. * Function Name  : NVIC_Configuration
  23. * Description    : Configures the RTC.
  24. * Input          : None
  25. * Output         : None
  26. * Return         : None
  27. * Attention : None
  28. *******************************************************************************/
  29. static void RTC_Configuration(void)//RTC的初始化的基本配置(包括RTC的时钟源选择和分频,及秒中断的使能);为RTC_Init(void)做准备
  30. {
  31.   /* Enable PWR and BKP clocks */
  32.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//开启PWR和BKP的时钟
  33.   /* Allow access to BKP Domain */
  34.   PWR_BackupAccessCmd(ENABLE);//允许访问BKP,对PWR_CR中的DBP位进行写1,以允许对BKP和RTC模块的操作
  35.   /* Reset Backup Domain */
  36.   BKP_DeInit();//复位BKP
  37.   /* Enable LSE */
  38.   RCC_LSEConfig(RCC_LSE_ON); //外部低速时钟使能
  39.   /* Wait till LSE is ready */
  40.   while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){}//等待时钟准备好  
  41.   /* Select LSE as RTC Clock Source */
  42.   RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择外部低速时钟外RTC的时钟源
  43.   /* Enable RTC Clock */
  44.   RCC_RTCCLKCmd(ENABLE); //使能RTC的时钟 ,是通过对RCC_BDCR中的RTCEN位的操作来开启RTC的时钟的
  45.   /* Wait for RTC registers synchronization */
  46.   RTC_WaitForSynchro();
  47.   /* Wait until last write operation on RTC registers has finished */
  48.   RTC_WaitForLastTask();
  49.   /* Enable the RTC Second */
  50.   //RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC的秒中断
  51.   /* Wait until last write operation on RTC registers has finished */
  52.   RTC_WaitForLastTask();
  53.   /* Set RTC prescaler: set RTC period to 1sec */
  54.   RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) *///RTC为32767+1分频,每秒一次溢出中断
  55.   /* Wait until last write operation on RTC registers has finished */
  56.   RTC_WaitForLastTask();
  57. }

  58. /*******************************************************************************
  59. * Function Name  : NVIC_Configuration
  60. * Description    : Configures the nested vectored interrupt controller.
  61. * Input          : None
  62. * Output         : None
  63. * Return         : None
  64. * Attention : None
  65. *******************************************************************************/
  66. // void NVIC_Configuration(void) //RTC模块的中断配置
  67. // {
  68. //   NVIC_InitTypeDef NVIC_InitStructure;
  69. //   /* Configure one bit for preemption priority */
  70. //   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  71. //   /* Enable the RTC Interrupt */
  72. //   NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
  73. //   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  74. //   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  75. //   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  76. //   NVIC_Init(&NVIC_InitStructure);
  77. // }
  78. ///////////////////时间形式的转换/////////////////////////////////
  79. TIMESTAMP TimeConv_Nomal2Stamp(NORMALTIME t)//正常(北京)时间转换为时间戳
  80. {
  81. t.tm_year-=1900;//虽然时间戳是以1970年(正数部分0x00000000)开始计时,但时间转换是转成1900年(负数第32bit决定)的相对时间
  82. t.tm_mon -=1;
  83. if(t.tm_wday>=7)
  84. t.tm_wday=0;
  85. t.tm_hour-=8;
  86. return mktime(&t);
  87. }
  88. NORMALTIME TimeConv_Stamp2Nomal(TIMESTAMP ts)//时间戳转换为正常(北京)时间
  89. {
  90. NORMALTIME *pt,t;
  91. pt = localtime(&ts);//函数为把时间戳转换成从1900开始的相对时间值,需要加上开始的时间
  92. t=*pt;
  93. t.tm_year+=1900;
  94. t.tm_mon +=1;
  95. if(t.tm_wday==0)
  96. t.tm_wday=7;
  97. t.tm_hour+=8;//转为北京时间
  98. return t;
  99. }
  100. //////////////////时间戳方式获取时间和设置时间///////////////////////
  101. TIMESTAMP Time_GetTimeStamp(void) //获取RTC中的时间戳
  102. {
  103. return (TIMESTAMP)RTC_GetCounter();
  104. }

  105. void Time_SetTimeStamp(TIMESTAMP ts)//设置RTC中的时间(时间戳的形式)
  106. {
  107. RTC_Configuration();
  108. RTC_WaitForLastTask();
  109. RTC_SetCounter((u32)ts);
  110. BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//把0xA5A5写入BKP_DR1寄存器中
  111. RTC_WaitForLastTask();
  112. }

  113. /////////////////常规时间方式获取和设置时间/////////////////////////
  114. NORMALTIME Time_GetTime(void) //获取正常(北京)时间
  115. {
  116.   return TimeConv_Stamp2Nomal((TIMESTAMP)RTC_GetCounter());
  117. }

  118. void Time_SetTime(NORMALTIME t)//设置正常(北京)时间
  119. {
  120. Time_SetTimeStamp(TimeConv_Nomal2Stamp(t));
  121. }

  122. //////////////////RTC模块复位//////////////////////////////////////
  123. void RTC_Rst(TIMESTAMP ts)//RTC复位
  124. {
  125. RTC_Configuration();//如果没有配置,则进行相应的初始化基本配置
  126. Time_SetTimeStamp(ts);
  127. /* Adjust time by values entred by the user on the hyperterminal */
  128. BKP_WriteBackupRegister(BKP_DR1, 0x0000);//把0x0000写入BKP_DR1寄存器中
  129. }
  130. //   RTC_EnterConfigMode();
  131. //   /* Set RTC COUNTER MSB word */
  132. //   RTC->CNTH = CounterValue >> 16;
  133. //   /* Set RTC COUNTER LSB word */
  134. //   RTC->CNTL = (CounterValue & RTC_LSB_MASK);
  135. //   RTC_ExitConfigMode();
  136. /*******************************************************************************
  137. * Function Name  : RTC_Init
  138. * Description    : RTC Initialization
  139. *******************************************************************************/
  140. void RTC_Init(NORMALTIME t)//RTC初始化
  141. {
  142.   if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)//判断RTC模块是否进行了配置
  143.   {
  144.     RTC_Configuration();//如果没有配置,则进行相应的初始化基本配置
  145. Time_SetTime(t);//写入最初的RTC时间
  146. /* Adjust time by values entred by the user on the hyperterminal */
  147.     BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//把0xA5A5写入BKP_DR1寄存器中
  148.   }
  149.   /*
  150.   else
  151.   {
  152.    //Check if the Power On Reset flag is set
  153.     if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)//判断是否发生了电源上电复位
  154.     {
  155.       printf("Power On Reset occurred....\r\n");
  156.     }
  157.     // Check if the Pin Reset flag is set
  158.     else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)//判断是否发生了引脚复位
  159.     {
  160.       printf("External Reset occurred....\r\n");
  161.     }

  162.     printf("No need to configure RTC....\r\n");
  163.     // Wait for RTC registers synchronization
  164.     RTC_WaitForSynchro();

  165.     // Enable the RTC Second
  166.     RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
  167.     // Wait until last write operation on RTC registers has finished
  168.     RTC_WaitForLastTask();
  169.   }

  170.    // NVIC configuration
  171.    NVIC_Configuration();//RTC的嵌套向量中断配置

  172. #ifdef RTCClockOutput_Enable
  173.   // Enable PWR and BKP clocks
  174.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  175.   // Allow access to BKP Domain
  176.   PWR_BackupAccessCmd(ENABLE);

  177.   // Disable the Tamper Pin
  178.   BKP_TamperPinCmd(DISABLE); // To output RTCCLK/64 on Tamper pin, the tamper functionality must be disabled

  179.   // Enable RTC Clock Output on Tamper Pin
  180.   BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
  181. #endif

  182.    // Clear reset flags
  183.   RCC_ClearFlag(); //清除各种复位标志*/
  184.   return;
  185. }

  186. // /*******************************************************************************
  187. // * Function Name  : Time_GetCalendarTime
  188. // * Description    : 从RTC取当前时间的日历时间(struct tm)
  189. // * Input          : None
  190. // * Output         : None
  191. // * Return         : struct tm
  192. // * Attention : None
  193. // *******************************************************************************/
  194. // struct tm Time_GetCalendarTime(void) //获取RTC中的日历时间
  195. // {
  196. // time_t t_t;
  197. // struct tm t_tm;

  198. // t_t = (time_t)RTC_GetCounter();
  199. // t_tm = Time_ConvUnixToCalendar(t_t);
  200. // return t_tm;
  201. // }

  202. /******************************************************************************************************************************
  203. 以下函数为设置RTC时钟
  204. ******************************************************************************************************************************/
  205. // /*******************************************************************************
  206. // * Function Name  : Time_SetCalendarTime
  207. // * Description    : 将给定的Calendar格式时间转换成UNIX时间戳写入RTC
  208. // * Input          : - t: struct tm
  209. // * Output         : None
  210. // * Return         : None
  211. // * Attention : None
  212. // *******************************************************************************/
  213. // void Time_SetCalendarTime(struct tm t)//以日历的形式设置RTC中的时间
  214. // {
  215. // Time_SetUnixTime(Time_ConvCalendarToUnix(t));
  216. // return;
  217. // }

  218. // /******************************************************************************************************************************
  219. // 以下两个函数为时间戳和日历时间之间的转换(日历时间为从1900-1-1开始的)
  220. // ******************************************************************************************************************************/
  221. // /*******************************************************************************
  222. // * Function Name  : Time_ConvUnixToCalendar
  223. // * Description    : 转换UNIX时间戳为日历时间
  224. // * Input          : - t: 当前时间的UNIX时间戳
  225. // * Output         : None
  226. // * Return         : struct tm
  227. // * Attention : None
  228. // *******************************************************************************/
  229. // struct tm Time_ConvUnixToCalendar(time_t t)//把时间戳转换为日历时间(前提是时间戳开始时间和日历开始计算的时间相同,都是从1900年开始计算)
  230. // {
  231. // struct tm *t_tm;
  232. // t_tm = localtime(&t);//t_tm = localtime(&t);函数为把时间戳转换成从1900开始的相对时间值,需要加上开始的时间
  233. // t_tm->tm_year += 1900;/* localtime转换结果的tm_year是相对值,需要转成绝对值 */
  234. //
  235. // return *t_tm;
  236. // }

  237. // /*******************************************************************************
  238. // * Function Name  : Time_ConvCalendarToUnix
  239. // * Description    : 写入RTC时钟当前时间
  240. // * Input          : - t: struct tm
  241. // * Output         : None
  242. // * Return         : time_t
  243. // * Attention : None
  244. // *******************************************************************************/
  245. // time_t Time_ConvCalendarToUnix(struct tm t)//把日历时间转换为时间戳
  246. // {
  247. // t.tm_year -= 1900;  /* 外部tm结构体存储的年份为2008格式*/
  248. // /* 而time.h中定义的年份格式为1900年开始的年份 */
  249. // /* 所以,在日期转换时要考虑到这个因素。*/
  250. // return mktime(&t);
  251. // }

  252. // /*******************************************************************************
  253. // * Function Name  : Time_Regulate
  254. // * Description    : None
  255. // * Input          : None
  256. // * Output         : None
  257. // * Return         : None
  258. // * Attention : None
  259. // *******************************************************************************/
  260. // void Time_Regulate(void)
  261. // {
  262. //   struct tm time;
  263. //     memset(&time, 0 , sizeof(time) );/* 清空结构体 */
  264. //     
  265. //     time.tm_year =2012;//设定年1970-2037
  266. //   
  267. //     time.tm_mon=1-1;//设定月(1-12)-1

  268. //     time.tm_mday = 1;//设定日1-31

  269. //     time.tm_hour =1;//设定小时0-23

  270. //     time.tm_min = 1;//设定分0-59

  271. //     time.tm_sec =1;//设定秒0-59

  272. //   /* Return the value to store in RTC counter register */
  273. //   Time_SetCalendarTime(time);//根据以上设定对RTC进行设置  
  274. // }
  275. // /*******************************************************************************
  276. // * 本文件实现基于RTC的日期功能,提供年月日的读写。(基于ANSI-C的time.h)
  277. // *
  278. // * RTC中保存的时间格式,是UNIX时间戳格式的。即一个32bit的time_t变量(实为u32)
  279. // *
  280. // * ANSI-C的标准库中,提供了两种表示时间的数据  型:
  281. // * time_t:   UNIX时间戳(从19xx-1-1起到某时间经过的秒数)
  282. // * typedef unsigned int time_t;
  283. // *
  284. // * struct tm:Calendar格式(年月日形式)
  285. // *   tm结构如下:
  286. // *   struct tm {
  287. // *   int tm_sec;   // 秒 seconds after the minute, 0 to 60(0 - 60 allows for the occasional leap second)
  288. // *   int tm_min;   // 分 minutes after the hour,   0 to 59
  289. // *  int tm_hour;  // 时 hours since midnight, 0 to 23
  290. // *  int tm_mday;  // 日 day of the month, 1 to 31
  291. // *  int tm_mon;   // 月 months since January, 0 to 11
  292. // *  int tm_year;  // 年 years since 1900
  293. // *  int tm_wday;  // 星期 days since Sunday, 0 to 6
  294. // *  int tm_yday;  // 从元旦起的天数 days since January 1, 0 to 365
  295. // * int tm_isdst; // 夏令时??Daylight Savings Time flag
  296. // * ...
  297. // * }
  298. // * 其中wday,yday可以自动产生,软件直接读取
  299. // * mon的取值为0-11
  300. // ****注意***:
  301. // *tm_year:在time.h库中定义为1900年起的年份,即2008年应表示为2008-1900=108
  302. // * 这种表示方法对用户来说不是十分友好,与现实有较大差异。
  303. // * 所以在本文件中,屏蔽了这种差异。
  304. // * 即外部调用本文件的函数时,tm结构体类型的日期,tm_year即为2008
  305. // * 注意:若要调用系统库time.c中的函数,需要自行将tm_year-=1900
  306. // *
  307. // * 成员函数说明:
  308. // * struct tm Time_ConvUnixToCalendar(time_t t);
  309. // * 输入一个Unix时间戳(time_t),返回Calendar格式日期
  310. // * time_t Time_ConvCalendarToUnix(struct tm t);
  311. // * 输入一个Calendar格式日期,返回Unix时间戳(time_t)
  312. // * time_t Time_GetUnixTime(void);
  313. // * 从RTC取当前时间的Unix时间戳值
  314. // * struct tm Time_GetCalendarTime(void);
  315. // * 从RTC取当前时间的日历时间
  316. // * void Time_SetUnixTime(time_t);
  317. // * 输入UNIX时间戳格式时间,设置为当前RTC时间
  318. // * void Time_SetCalendarTime(struct tm t);
  319. // * 输入Calendar格式时间,设置为当前RTC时间
  320. // *
  321. // * 外部调用实例:
  322. // * 定义一个Calendar格式的日期变量:
  323. // * struct tm now;
  324. // * now.tm_year = 2008;
  325. // * now.tm_mon = 11;//12月
  326. // * now.tm_mday = 20;
  327. // * now.tm_hour = 20;
  328. // * now.tm_min = 12;
  329. // * now.tm_sec = 30;
  330. // *
  331. // * 获取当前日期时间:
  332. // * tm_now = Time_GetCalendarTime();
  333. // * 然后可以直接读tm_now.tm_wday获取星期数
  334. // *
  335. // * 设置时间:
  336. // * Step1. tm_now.xxx = xxxxxxxxx;
  337. // * Step2. Time_SetCalendarTime(tm_now);
  338. // *
  339. // * 计算两个时间的差
  340. // * struct tm t1,t2;
  341. // * t1_t = Time_ConvCalendarToUnix(t1);
  342. // * t2_t = Time_ConvCalendarToUnix(t2);
  343. // * dt = t1_t - t2_t;
  344. // * dt就是两个时间差的秒数
  345. // * dt_tm = mktime(dt);//注意dt的年份匹配,ansi库中函数为相对年份,注意超限
  346. // * 另可以参考相关资料,调用ansi-c库的格式化输出等功能,ctime,strftime等
  347. // *
  348. //*******************************************************************************/
复制代码


回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表