STM32 TouchGFX【六】实现时间显示
使用TouchGFX显示当前时间
TouchGFX配置
拖入文本框
更改通配符选项 先修改年
填入默认数字和字符缓冲大小 大于显示字符即可
TouchGFX中时间的字体类型一定要设置范围 否则显示不正常
Cubemx配置
打开RTC添加 日历
添加一个TIM用来刷新时间
添加代码
app_user.c
gTask_MarkEN gTaskEnMark; //系统任务使能标识
//系统时间
RTC_DateTypeDef gSystemDate; //获取日期结构体
RTC_TimeTypeDef gSystemTime; //获取时间结构体
/* The sensors can be mounted onto the board in any orientation. The mounting
* matrix seen below tells the MPL how to rotate the raw data from thei
* driver(s).
* TODO: The following matrices refer to the configuration on an internal test
* board at Invensense. If needed, please modify the matrices to match the
* chip-to-body matrix for your particular set up.
*/
static signed char gyro_orientation[9] = {-1, 0, 0,
0,-1, 0,
0, 0, 1};
/*********************************************************************/
void (* g_OSTsakList[OS_TASKLISTCNT])(void);
//系统时间初始化,编译时间
void System_Time_init(void)
{
int32_t lYear = OS_YEAR ,lMonth = OS_MONTH,lDate =OS_DAY;
int32_t lweek = 0, weekBuff = 0;
//
uint32_t p_BKUPReadDRx = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0);
//基姆拉尔森计算公式,根据输入的年月日输出星期几
if(lMonth==1||lMonth==2)
{
lMonth += 12;
lYear--;
}
weekBuff=(lDate+2*lMonth+3*(lMonth+1)/5+lYear+lYear/4-lYear/100+lYear/400)%7;
//
switch(weekBuff)
{
case 0: lweek=RTC_WEEKDAY_MONDAY; break;
case 1: lweek=RTC_WEEKDAY_TUESDAY; break;
case 2: lweek=RTC_WEEKDAY_WEDNESDAY; break;
case 3: lweek=RTC_WEEKDAY_THURSDAY; break;
case 4: lweek=RTC_WEEKDAY_FRIDAY; break;
case 5: lweek=RTC_WEEKDAY_SATURDAY; break;
case 6: lweek=RTC_WEEKDAY_SUNDAY; break;
}
//备份域数据读取,是否更新与保存编译时间
if ((p_BKUPReadDRx & 0xFFFF) != RTC_BKP0RL_VAULE)
{
/** Initialize RTC and set the Time and Date
*/
gSystemTime.Hours = OS_HOUR;
gSystemTime.Minutes = OS_MINUTE;
gSystemTime.Seconds = OS_SECOND;
gSystemTime.SubSeconds = 0x0;
gSystemTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
gSystemTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &gSystemTime, RTC_FORMAT_BIN) != HAL_OK) {Error_Handler();}
gSystemDate.WeekDay = lweek;
gSystemDate.Month = OS_MONTH;
gSystemDate.Date = OS_DAY;
gSystemDate.Year = OS_YEAR - 2000;
if (HAL_RTC_SetDate(&hrtc, &gSystemDate, RTC_FORMAT_BIN) != HAL_OK) {Error_Handler();}
//备份寄存器DR0用于存储时间是否设置
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, (p_BKUPReadDRx & 0xFFFF0000) | RTC_BKP0RL_VAULE);
//
HAL_Delay(100);
}
}
/*
**********************************************************************
* @fun :Update_System_Time
* @brief :系统时间更新,并通过核心板USB转串口打印
* @param :None
* @return :None
* @remark :周期性调用-1S运行一次
**********************************************************************
*/
void Update_System_Time(void)
{
HAL_RTC_GetTime(&hrtc, &gSystemTime, RTC_FORMAT_BIN);//获取时间
/* Get the RTC current Date */
HAL_RTC_GetDate(&hrtc, &gSystemDate, RTC_FORMAT_BIN);//获取日期
//
gTaskEnMark.UPDATE_TIME_EN = 0; //系统时间更新
//输出系统时间
#ifdef DEBUG_MODE
printf("sys_date:%04d%02d%02d\n\r", gSystemDate.Year+2000, gSystemDate.Month, gSystemDate.Date);
printf("sys_time:%02d%02d%02d\n\r", gSystemTime.Hours, gSystemTime.Minutes, gSystemTime.Seconds);
#endif // DEBUG
}
app_user.h
typedef struct
{
uint32_t UPDATE_TIME_EN:1; //系统时间任务使能
}gTask_MarkEN;
#define OS_TASKLISTCNT 8
// Retrieve year info
#define OS_YEAR ((((__DATE__ [7] - '0') * 10 + (__DATE__ [8] - '0')) * 10 \
+ (__DATE__ [9] - '0')) * 10 + (__DATE__ [10] - '0'))
// Retrieve month info
#define OS_MONTH (__DATE__ [2] == 'n' ? (__DATE__ [1] == 'a' ? 1 : 6) \
: __DATE__ [2] == 'b' ? 2 \
: __DATE__ [2] == 'r' ? (__DATE__ [0] == 'M' ? 3 : 4) \
: __DATE__ [2] == 'y' ? 5 \
: __DATE__ [2] == 'l' ? 7 \
: __DATE__ [2] == 'g' ? 8 \
: __DATE__ [2] == 'p' ? 9 \
: __DATE__ [2] == 't' ? 10 \
: __DATE__ [2] == 'v' ? 11 : 12)
// Retrieve day info
#define OS_DAY ((__DATE__ [4] == ' ' ? 0 : __DATE__ [4] - '0') * 10 \
+ (__DATE__ [5] - '0'))
// Retrieve hour info
#define OS_HOUR ((__TIME__ [0] - '0') * 10 + (__TIME__ [1] - '0'))
// Retrieve minute info
#define OS_MINUTE ((__TIME__ [3] - '0') * 10 + (__TIME__ [4] - '0'))
// Retrieve second info
#define OS_SECOND ((__TIME__ [6] - '0') * 10 + (__TIME__ [7] - '0'))
#define RTC_BKP0RL_VAULE 0x1A1B
在gui文件夹里
model.cpp
#if defined LINK_HARDWARE //TuchGFX仿真与实际硬件操作隔离
//头文件包含
extern "C"
{
#include "app_user.h"
}
extern RTC_DateTypeDef gSystemDate; //获取日期结构体
extern RTC_TimeTypeDef gSystemTime; //获取时间结构体
extern gTask_MarkEN gTaskEnMark; //系统任务使能标识
extern volatile uint8_t gLastTimeSeconds; //上一次的时间
volatile uint8_t gLastTimeSeconds = 0; //上一次的时间
#endif
void Model::tick()
{
static uint8_t tickCount = 0; //减少数据上传的次数,优化界面刷新
tickCount++;
#if defined LINK_HARDWARE
//更新日期与时间
if(gSystemTime.Seconds != gLastTimeSeconds) //每秒同步一次界面时间
{
modelListener->updateDate(gSystemDate.Year,gSystemDate.Month,gSystemDate.Date,gSystemDate.WeekDay);
modelListener->updateTime(gSystemTime.Hours, gSystemTime.Minutes, gSystemTime.Seconds);
//更新新值
gLastTimeSeconds = gSystemTime.Seconds;
}
#endif
}
keil添加一个宏来实现前后端的分离 ,这样TouchGFX软件仿真不会报错
presenter.cpp
//更新日期
void screenPresenter::updateTime(uint8_t newHours, uint8_t newMinutes, uint8_t newSeconds)
{
view.updateTime(newHours, newMinutes, newSeconds);
}
void screenPresenter::updateDate(uint8_t newYear, uint8_t newMonth, uint8_t newDate, uint8_t newWeekDay)
{
view.updateDate(newYear, newMonth, newDate, newWeekDay);
}
View.cpp
void screenView::updateTime(uint8_t newHours, uint8_t newMinutes, uint8_t newSeconds)
{
Unicode::snprintf(TimeClockBuffer1, TIMECLOCKBUFFER1_SIZE, "%02d", newHours);
Unicode::snprintf(TimeClockBuffer2, TIMECLOCKBUFFER2_SIZE, "%02d", newMinutes);
TimeClock.invalidate();
Unicode::snprintf(TimeSecondBuffer, TIMESECOND_SIZE, "%02d", newSeconds);
TimeSecond.invalidate();
}
//更新日期
void screenView::updateDate(uint8_t newYear, uint8_t newMonth, uint8_t newDate, uint8_t newWeekDay)
{
Unicode::snprintf(TimeyearBuffer, TIMEYEAR_SIZE, "%04d", newYear + 2000);
Timeyear.invalidate();
//
Unicode::snprintf(TimeDataBuffer1, TIMEDATABUFFER1_SIZE, "%02d", newMonth);
Unicode::snprintf(TimeDataBuffer2, TIMEDATABUFFER2_SIZE, "%02d", newDate);
TimeData.invalidate();
//
}
实验结果
注意事项 下载后要重新上电否则 时间不更新 并且下载需要重新编译来获取当前时间
作者:cat_milk