前言:

当AWTK界面被应用到嵌入式平台(如STM32中),需要提供并设置获取当前日期和时间的函数,否则相关的功能(如时钟控件)将无法正常工作。

一、函数

date_time_global_init_ex(&s_date_time_vtable);

 

 

二、代码实现:

平台:STM32

物联网操作系统:RT_Thread

编译:IAR

此处注册RTC设备:略

RTC获取时间部分

 RTC.c

/** @brief RTC设备的名称 */
#define RTC_DEVICE_NAME								"RTC"

/** @brief 配置RTC设备硬件时间直接存储、使用当地时间 */
#define CONFIG_RTC_TIME_IS_LOCAL					(0)

// Table of month length (in days) for the Un-leap-year
PRIVATE const bf_uint8_t s_mdaysUnleapYear[] =
{
	0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U
};

// Table of month length (in days) for the Leap-year
PRIVATE const bf_uint8_t s_mdaysLeapYear[] =
{
	0U, 31U, 29U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U
};

/**
 * @brief RTC时间数据的类型定义
 */
typedef struct st_rtc_time
{
	bf_uint16_t year;								/**< 年,例如2016 */
	bf_uint16_t month;								/**< 月, (1-12) */
	bf_uint16_t day;								/**< 日, (1-31) */
	bf_uint16_t hour;								/**< 小时, (0-23) */
	bf_uint16_t minute;								/**< 分钟, (0-59) */
	bf_uint16_t second;								/**< 秒, (0-59) */
} st_rtc_time_t, *pst_rtc_time_t;

#define ReturnValIfFail(expr, val) 		do 													\
										{ 																\
											if (CONFIG_GLOBAL_ENABLE_CHECKS && (!(expr))) 				\
											{ 															\
												LOG_WarningLine("expr: ("#expr") failed.");				\
												return (val);											\
											} 															\
										}																\
										while (0)


pq_bool_t RTC_CheckDateTimeValid(pst_rtc_time_t datetime)
{
	pq_uint_t mdays;
	
	if (PQ_NULL == datetime)
		return PQ_FALSE;
	
    if ((datetime->month > 12U) || (datetime->month < 1U)
		|| (datetime->day > 31U) || (datetime->day < 1U)
		|| (datetime->hour >= 24U) || (datetime->minute >= 60U) || (datetime->second >= 60U))
    {
		return PQ_FALSE;
    }

	if ((datetime->year & 3U))
	{
		mdays = s_mdaysUnleapYear[datetime->month];
	}
	else
	{
		mdays = s_mdaysLeapYear[datetime->month];
	}

	if (datetime->day > mdays)
		return PQ_FALSE;

	return PQ_TRUE;
}

/*******************************************************************************
 * Private Functions
 ******************************************************************************/

PRIVATE void RtcConvertDatetimeToNewtm(pst_rtc_time_t datetime, bf_int_t secondsToAdjust, struct tm *newtm)
{
	// NOTE: The 32-bit interface supports years from 1900 up to 2035 and uses a 32-bit integer for time_t, 
	//			The 64-bit interface supports years from -9999 up to 9999 and uses a signed
	//			long long for time_t. The type and function have names like __time64_t,
	//			__time64, etc.
	//			pls see IAR docs for more details.
	time_t timestamp;
	
	struct tm timeInstance;
	struct tm *timeInstancePtr;

	memzero(&timeInstance, sizeof(timeInstance));
	timeInstance.tm_year = datetime->year - 1900;
	timeInstance.tm_mon = datetime->month - 1;
	timeInstance.tm_mday = datetime->day;
	timeInstance.tm_hour = datetime->hour;
	timeInstance.tm_min = datetime->minute;
	timeInstance.tm_sec = datetime->second;

	timestamp = mktime(&timeInstance);
	
	// TIP: 目前我们并未定制IAR的库,因此以下的处理仍为非线程安全函数,需要进入调度临界区
	rt_enter_critical();
	{
		bf_uint_t diffSeconds;

		diffSeconds = abs(secondsToAdjust);
		if (secondsToAdjust > 0)
		{
			timestamp += diffSeconds;
		}
		else
		{
			timestamp -= diffSeconds;
		}
		
		timeInstancePtr = gmtime(&timestamp);
		memcpy(newtm, timeInstancePtr, sizeof(*timeInstancePtr));
	}
	rt_exit_critical();
}

PRIVATE void RtcConvertTmToRtctime(struct tm *oldtm, pst_rtc_time_t datetime)
{
	datetime->year = oldtm->tm_year + 1900;
	datetime->month = oldtm->tm_mon + 1;
	datetime->day = oldtm->tm_mday;
	datetime->hour = oldtm->tm_hour;
	datetime->minute = oldtm->tm_min;
	datetime->second = oldtm->tm_sec;
}


PRIVATE void RtcAdjustDateTime(pst_rtc_time_t datetime, bf_int_t secondsToAdjust)
{
	struct tm newtm;

	if (0 == secondsToAdjust)
		return;

	RtcConvertDatetimeToNewtm(datetime, secondsToAdjust, &newtm);

	RtcConvertTmToRtctime(&newtm, datetime);
}


/*******************************************************************************
 * Private Functions
 ******************************************************************************/

PQ_bool_t RTC_GetLocalTime(pst_rtc_time_t localTime, pst_rtc_time_t knownUtcTime)
{
	st_rtc_time_t rtcTime;
	bf_int_t secondsToAdjust;
	
	ReturnValIfFail(PQ_NULL != localTime, PQ_FALSE);

	if (PQ_NULL == knownUtcTime)
	{
		rt_device_t dev;

		dev = rt_device_find(RTC_DEVICE_NAME);
		rt_device_open(dev, RT_DEVICE_FLAG_RDWR);

		memzero(&rtcTime, sizeof(rtcTime));
		rt_device_control(dev, RTC_IOCTL_GET_TIME, &rtcTime);

		rt_device_close(dev);
	}
	else
	{
		memcpy(&rtcTime, knownUtcTime, sizeof(*knownUtcTime));
	}
		
	if (!RTC_CheckDateTimeValid(&rtcTime))
		return PQ_FALSE;

	memcpy(localTime, &rtcTime, sizeof(rtcTime));

#if CONFIG_RTC_TIME_IS_LOCAL
	if (PQ_NULL == knownUtcTime)
	{
		// 从RTC硬件读取时间,在此模式下,已经是当地时间了,无需调整
		secondsToAdjust = 0;
	}
	else
	{
		// 用户主动传入的时间,属于UTC时间,仍需要进行转换
		rt_enter_critical();
		secondsToAdjust = s_rtcCorePrivInfo.secondsToAdjust;
		rt_exit_critical();
	}
#else
	rt_enter_critical();
	secondsToAdjust = s_rtcCorePrivInfo.secondsToAdjust;
	rt_exit_critical();
#endif

	RtcAdjustDateTime(localTime, secondsToAdjust);

	return PQ_TRUE;
}

AWTK设置时间部分!! 

AWTK设置时间部分:


static ret_t date_time_get_now_impl(date_time_t* dt) 
{
  	st_rtc_time_t rtcTime;      //rtc时间
  	st_rtc_time_t localTime;    //local时间
  	static rt_device_t device;

    //读取设备当前时间
	device = rt_device_find(RTC_DEVICE_NAME);
	if (device != RT_NULL)
	{
		rt_device_open(device, RT_DEVICE_FLAG_RDWR);
		memzero(&rtcTime, sizeof(rtcTime));
		rt_device_control(device, RTC_IOCTL_GET_TIME, &rtcTime);
		memzero(&localTime, sizeof(localTime));
		RTC_GetLocalTime(&localTime, &rtcTime);
		rt_device_close(device);
	}

    //将当前时间赋值给awtk内部时间管理,
	dt->year = localTime.year;
	dt->month = localTime.month;
	dt->day = localTime.day;
	dt->hour = localTime.hour;
	dt->minute = localTime.minute;
	dt->second = localTime.second;
    dt->wday =  date_time_get_wday(dt->year, dt->month, dt->day);  //此处需要自己计算星期时间
  return RET_OK;
}

static ret_t date_time_set_now_impl(date_time_t* dt) 
{
//此处添加在界面设置的新时间,即ATWK的日期时间,更新到单片机stm32上的时间
   
  return RET_OK;
}

static ret_t date_time_from_time_impl(date_time_t* dt, uint64_t timeval) {
  	//此处获取单片机stm32上的时间,让其能更新到awtk内部时间

  return RET_OK;
}

static uint64_t date_time_to_time_impl(date_time_t* dt) {

  //此处添加在界面设置的新时间,即ATWK的日期时间,更新到单片机stm32上的时间
   
  return 1;
}

//设置日期和时间的相关函数的实现
static const date_time_vtable_t s_date_time_vtable = {
    date_time_get_now_impl,
    date_time_set_now_impl,
    date_time_from_time_impl,
    date_time_to_time_impl,
};

 

成功!LCD屏上的时间控件不再是00 00 了。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐