第九章 添加RTC[align=center]Wlof摘要:本文首先介绍如何将RTC组件添加到RTT_Nano3上使用,针对在MDK下无法正常使用mktime的问题,重写了mktime函数,也是抄过来的。
9.1 起源
之前SD卡上我们为了写入时间,将gettime这个函数进行了替换,主要还是那个time函数没有去弄它,为了尽可能少地修改提供的代码,这里使用了RTC组件进行操作,实现time函数。在调试过程中发现,mktime这个函数不对,不知道怎么回事,为此在网上找了一些文章,正在好发现有个linux下的源码,直接改写过来。至于那个自带的函数为什么会有问题,俺也不清楚,网上很多人说可以用,但我实际测试就是不能用呢。
9.2 复制文件
位于rt-thread-master\components\drivers tc,全部搞过来也行,这里只用以了rtc.c,对应的头文件也复制过来,在rt-thread-master\components\drivers\include\drivers里面。然后找个参考复制文件,我这里参考了STM32F429的,把文件drv_rtc.c 和.h复制过来。这4个文件,统一放到一个目录下,添加到工程,添加include到包含目录。
9.3 修改drv_rtc.c**9.3.1 头文件
去除drv_rtc.c #include “board.h”,添加#include “LPC17xx.h”。
9.3.2 删除函数
保留rt开头的函数,保留RTC_Init,SetRTCTimeStamp,GetRTCTimeStamp函数,其的函数全部干掉。然后清空RTC_Init,SetRTCTimeStamp,GetRTCTimeStamp这3个函数的内容,因为我们要添加到LPC1768上来。所有的驱动代码要用LPC1768上的代码,周立功网上可以下载到参考代码。
9.3.3 添加函数*
然后把周立功里面的代码复制过来,先不管它用不用,先搞去再说,那个初始化,放到RTC_Init里去,时间读取和设置函数先不要。
```void RTC_IRQHandler (void)
{
LPC_RTC->ILR |= ILR_RTCCIF; / clear interrupt flag */
return;
}
void RTC_Init(void)
{
uint32_t calibration_register = 0;
//==================================//
}
void RTCStart( void )
{
/—- Start RTC counters —-/
LPC_RTC->CCR |= CCR_CLKEN;
LPC_RTC->ILR = ILR_RTCCIF;
return;
}
void RTCStop( void )
{
/—- Stop RTC counters —-/
LPC_RTC->CCR &= ~CCR_CLKEN;
return;
}
void RTC_CTCReset( void )
{
/—- Reset CTC —-/
LPC_RTC->CCR |= CCR_CTCRST;
return;
}
void RTCSetAlarmMask( uint32_t AlarmMask )
{
/—- Set alarm mask —-/
LPC_RTC->AMR = AlarmMask;
return;
}```
9.3.4 修改读写时间函数
这里都是按原来的那个文件进行改写的,应改不会出太大的问题。
9.3.5 修改初始化函数int rt_hw_rtc_init(void)
{
RTC_Init();
NVIC_EnableIRQ(RTC_IRQn);
RTCSetAlarmMask(AMRSEC | AMRMIN | AMRHOUR | AMRDOM | AMRDOW | AMRDOY | AMRMON | AMRYEAR);
LPC_RTC->CIIR = IMMIN | IMYEAR;
RTCStart();
/* register rtc device */
rt_hw_rtc_register(&rtc, RT_RTC_NAME, 0);
return RT_EOK;
}
INIT_BOARD_EXPORT(rt_hw_rtc_init);
这里发现一个好东东,以前没有注意,这个**INIT_BOARD_EXPORT**可以让系统自动执行初始化函数。
9.4 dfs_elm.c的函数还原
这里主要是因为在上一节中我们自己写了一个函数进行了替换,现在将它还原回去。如果没有看上节也没有关系,这里提到这个函数的主要目的就是对这个函数地进行测试,看一下最后结是不是我们想要的。```DWORD get_fattime(void)
{
time_t now;
struct tm *p_tm;
struct tm tm_now;
DWORD fat_time;
}```
9.5 编译测试
编译有错的话,记得把头文件的宏定义复制来过。编译没有错了,发现转换的时间死活就是不对。我不知道别人有没有这事,反正我里那mktime这个函数就是不对,不仅不对还将传入的参数都改了!!!
9.6 mktime抄过来
按理说,它应改可以正常工作的,但是这是为什么呢?不知道,我用的是MDK5.23。这个代码的原版本是从Linux中搞出来的,我按头文件的写法重新搞一下,其实就是得到utc时间。time_t mktime(struct tm * timeptr)
{
uint32_t y,m,d,h,n,s;
y = timeptr->tm_year;
m = timeptr->tm_mon;
d = timeptr->tm_mday;
h = timeptr->tm_hour;
n = timeptr->tm_min;
s = timeptr->tm_sec;
if(0 >= (int) (m -= 2)){//1...12 --> 11,12,1...10
m += 12;
y -= 1;
}
return (((
(time_t)(y/4 - y/100 + y/400 + 367*m/12 +d) +
y*365 - 719499
)*24 + h
)*60 + n
)*60 + s;
}
9.7 测试 {
time_t x = 0; //2017-10-16 14214
x = time(RT_NULL);//x=1508163664
x = x;
get_fattime(); //里面的tm_now 117-9-1614:22:52(加了断点抄数造成的延时)
rt_thread_delay(1);
SetRTCTimeStamp(1508163664);//2017-10-16 14214
}
值得一提的是,那个localtime这个函数,使用时要注意,它返回的是一个指针,应该是一个静态变量,只是值不一样而已,调用一次用一次,不然会悲剧,好像是传说中的不可重入函数。
文档下载: