在调试rtc时,通过hal库函数设置date,time后,读取的时间总是年不对,月日时分秒是对的,
如图:
通过这个连接中的问题http://www.openedv.com/thread-231322-1-22.html?/news/guonei/97663746655/h
找到一位网友的解决方法:
按照这个方法确实解决了我的问题,将星期填上后,年份读取就正确了:
代码实现:
void platform_rtc_set_time(struct tm *time)
{
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
RTC_TimeStructure.TimeFormat = RTC_HOURFORMAT12_AM;
RTC_TimeStructure.Hours = time->tm_hour;
RTC_TimeStructure.Minutes = time->tm_min;
RTC_TimeStructure.Seconds = time->tm_sec;
RTC_DateStructure.WeekDay = 0; //这里必须要设置星期,否则读取年份不对
RTC_DateStructure.Year = time->tm_year - 100;
RTC_DateStructure.Month = time->tm_mon + 1;
RTC_DateStructure.Date = time->tm_mday;
HAL_RTC_SetTime(&hrtc, &RTC_TimeStructure,RTC_FORMAT_BIN);
HAL_RTC_SetDate(&hrtc,&RTC_DateStructure,RTC_FORMAT_BIN);
}
void platform_rtc_get_time(struct tm *time)
{
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
HAL_RTC_GetTime(&hrtc,&RTC_TimeStructure,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc,&RTC_DateStructure,RTC_FORMAT_BIN);
time->tm_year = RTC_DateStructure.Year + 100;
time->tm_mon = RTC_DateStructure.Month - 1;
time->tm_mday = RTC_DateStructure.Date;
time->tm_wday = RTC_DateStructure.WeekDay;
time->tm_hour = RTC_TimeStructure.Hours;
time->tm_min = RTC_TimeStructure.Minutes;
time->tm_sec = RTC_TimeStructure.Seconds;
}
long set_time(uint32_t year, uint32_t month, uint32_t day, uint32_t hour, uint32_t minute, uint32_t second)
{
time_t now_time;
struct tm tm_new;
struct tm *p_tm;
rt_device_t device;
rt_err_t ret = -RT_ERROR;
tm_new.tm_year = year - 1900;
tm_new.tm_mon = month - 1;
tm_new.tm_mday = day;
tm_new.tm_hour = hour;
tm_new.tm_min = minute;
tm_new.tm_sec = second;
now_time = mktime(&tm_new);
device = rt_device_find("rtc");
if (device == RT_NULL)
{
return -RT_ERROR;
}
ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &now_time);
return ret;
}
//获取时间的函数,获取返回的是时间戳
time_t time(time_t *t)
{
static rt_device_t device = RT_NULL;
time_t time_now = 0;
if (device == RT_NULL) {
device = rt_device_find("rtc");
}
if (device != RT_NULL) {
if (rt_device_open(device, 0) == RT_EOK) {
rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time_now);
rt_device_close(device);
}
}
if (t != RT_NULL) {
*t = time_now;
}
return time_now;
}
通过rtthread的device实现的控制函数rt_device_control, rtc的device实现如下:
#include <rtthread.h>
#include <time.h>
#include "stm32f0xx_hal.h"
#include "rtc.h"
#define DEVICE_NAME "rtc"
static struct rt_device rtc;
static rt_err_t drv_rtc_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
static rt_err_t drv_rtc_close(rt_device_t dev)
{
return RT_EOK;
}
static rt_size_t drv_rtc_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size)
{
struct tm ti;
platform_rtc_get_time(&ti);
rt_kprintf("%04d-%02d-%02d %02d:%02d:%02d\r\n", ti.tm_year + 1900, ti.tm_mon + 1, ti.tm_mday, ti.tm_hour, ti.tm_min, ti.tm_sec);
rt_sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", ti.tm_year + 1900, ti.tm_mon + 1, ti.tm_mday, ti.tm_hour, ti.tm_min, ti.tm_sec);
return 0;
}
static rt_tick_t init_tick;
static time_t init_time;
static rt_err_t drv_rtc_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
time_t *time;
struct tm ti;
struct tm *p_tm;
RT_ASSERT(dev != RT_NULL);
switch (cmd) {
case RT_DEVICE_CTRL_RTC_GET_TIME:
time = (time_t *) args;
platform_rtc_get_time(&ti);
*time = mktime(&ti);
break;
case RT_DEVICE_CTRL_RTC_SET_TIME:
time = (time_t *) args;
p_tm = localtime(time);
platform_rtc_set_time(p_tm);
break;
}
/* rtthread中rtc的实现方法
// time_t *time;
// struct tm time_temp;
// RT_ASSERT(dev != RT_NULL);
// memset(&time_temp, 0, sizeof(struct tm));
// switch (cmd)
// {
// case RT_DEVICE_CTRL_RTC_GET_TIME:
// time = (time_t *) args;
// *time = init_time + (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND;
// break;
// case RT_DEVICE_CTRL_RTC_SET_TIME:
// {
// time = (time_t *) args;
// init_time = *time - (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND;
// break;
// }
// }
*/
return RT_EOK;
}
int drv_rtc_init(void)
{
platform_rtc_init();
rtc.init = RT_NULL;
rtc.open = drv_rtc_open;
rtc.close = drv_rtc_close;
rtc.read = drv_rtc_read;
rtc.write = RT_NULL;
rtc.control = drv_rtc_control;
rtc.user_data = RT_NULL;
rt_device_register(&rtc, DEVICE_NAME, RT_DEVICE_FLAG_RDWR);
return 0;
}
INIT_BOARD_EXPORT(drv_rtc_init);