当前位置: 首页 > news >正文

【Mini-F5265-OB开发板试用测评】显示RTC日历时钟

一、前言

本章节承接上期的【Mini-F5265-OB开发板试用测评】硬件SPI方式驱动LCD屏帖子上。灵动微官方提供的“LibSamples_MM32F5260_V0.10.2”SDK中包含一个RTC日历的参考例程,因此将该功能移植到上期工程中,即可达成在LCD屏上显示RTC日历时钟。
官方提供的参考示例,基本上都是采用PA2复用为串口2的TX端,方便用户外接USB转TTL调试模块打印串口输出信息,上期咱使用PA2作为控制LCD的背光输出脚,因此如果想要工程既支持串口打印RTC日历时钟信息,又能将数据同步到LCD屏上,必须将PA2改成其它通用GPIO口。

二、移植说明

参考“RTC_Calendar”例程,将“rtc_calendar.c”与“rtc_calendar.h”添加到原工程路径中,并在“mm32f5260_it.c”中添加RTC_IRQHandler()中断函数。
由于这里使用LCD做为数据显示端,因此可将printf串口打印输出替换成LCD相关显示接口函数。

三、工程源码

main.c

#include "platform.h"
#include "gpio_led_toggle.h"
#include "main.h"
#include "lcd.h"
#include "rtc_calendar.h"int main(void)
{PLATFORM_Init();GPIO_LED_Toggle_Sample();LCDInit();RTC_Configure();PLATFORM_DelayMS(200U);LcdFill(0,0,LCD_W,LCD_H,WHITE);while (1){LCDTest();}
}

rtc_calendar.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "platform.h"
#include "rtc_calendar.h"
#include "lcd.h"const uint8_t RTC_DayOfMonth[12] =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};RTC_CalendarTypeDef RTC_Calendar;uint8_t RTC_LeapYear(uint16_t Year)
{if ((((Year % 400) == 0)) ||   /* Century Leap Year */(((Year % 100) != 0) && ((Year % 4) == 0)) /* Normal  Leay Year */){return (1);}else{return (0);}
}uint8_t RTC_GetWeek(uint16_t Year, uint8_t Month, uint8_t Day)
{int w, c, y;/* Month 1 Or 2 of This Year Must Be As Last Month 13 Or 14 */if ((Month == 1) || (Month == 2)){Month += 12;Year  -= 1;}w = 0;                             /* Weekday */c = Year / 100;                    /* Century */y = Year % 100;                    /* Year    */w = y + (y / 4) + (c / 4) - (2 * c) + (26 * (Month + 1) / 10) + Day - 1;while (w < 0){w += 7;}w %= 7;return (w);
}void RTC_UpdateCalendar(void)
{static uint32_t PreTotalDay = 0;uint32_t TotalSecond = 0;uint32_t TotalDay    = 0;uint16_t Year  = 1970;uint8_t  Month = 0;TotalSecond = RTC_GetCounter();TotalDay    = TotalSecond / 86400;if (PreTotalDay != TotalDay){PreTotalDay = TotalDay;while (TotalDay >= 365){if (RTC_LeapYear(Year) == 1){if (TotalDay >= 366){TotalDay -= 366;}else{break;}}else{TotalDay -= 365;}Year++;}RTC_Calendar.year = Year;while (TotalDay >= 28){if ((Month == 1) && (RTC_LeapYear(RTC_Calendar.year) == 1)){if (TotalDay >= 29){TotalDay -= 29;}else{break;}}else{if (TotalDay >= RTC_DayOfMonth[Month]){TotalDay -= RTC_DayOfMonth[Month];}else{break;}}Month++;}RTC_Calendar.month = Month + 1;RTC_Calendar.day   = TotalDay + 1;RTC_Calendar.week  = RTC_GetWeek(RTC_Calendar.year, RTC_Calendar.month, RTC_Calendar.day);}RTC_Calendar.hour   = (TotalSecond % 86400) / 3600;RTC_Calendar.minute = ((TotalSecond % 86400) % 3600) / 60;RTC_Calendar.second = ((TotalSecond % 86400) % 3600) % 60;
}void RTC_SetDateTime(uint16_t Year, uint8_t Month, uint8_t Day, uint8_t Hour, uint8_t Minute, uint8_t Second)
{uint32_t TotalSecond = 0;uint16_t y = 0;uint8_t  m = 0;if ((Year >= 1970) && (Year <= 2099)){for (y = 1970; y < Year; y++){if (RTC_LeapYear(y) == 1){TotalSecond += 31622400; /* Total Seconds Of Leap   Year */}else{TotalSecond += 31536000; /* Total Seconds Of Normal Year */}}for (m = 0; m < (Month - 1); m++){TotalSecond += RTC_DayOfMonth[m] * 86400; /* Total Seconds Of Month */if ((RTC_LeapYear(Year) == 1) && (m == 1)){TotalSecond += 86400;}}TotalSecond += (uint32_t)(Day - 1) * 86400; /* Total Seconds Of Day    */TotalSecond += (uint32_t)Hour * 3600;       /* Total Seconds Of Hour   */TotalSecond += (uint32_t)Minute * 60;       /* Total Seconds Of Minute */TotalSecond += Second;RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWRDBG | RCC_APB1Periph_BKP, ENABLE);PWR_BackupAccessCmd(ENABLE);RTC_SetCounter(TotalSecond);RTC_WaitForLastTask();RTC_UpdateCalendar();}else{printf("\r\nError Date & Time!!!\r\n");}
}void RTC_PrintDateTime(void)
{LcdShowIntNum(8,118,RTC_Calendar.year,4,WHITE,RED,16);LcdShowString(40,118,"-",WHITE,RED,16);if(RTC_Calendar.month < 10){LcdShowIntNum(48,118,0,1,WHITE,RED,16);LcdShowIntNum(56,118,RTC_Calendar.month,1,WHITE,RED,16);}else{LcdShowIntNum(48,118,RTC_Calendar.month,2,WHITE,RED,16);}LcdShowString(64,118,"-",WHITE,RED,16);if(RTC_Calendar.day < 10){LcdShowIntNum(72,118,0,1,WHITE,RED,16);LcdShowIntNum(80,118,RTC_Calendar.day,1,WHITE,RED,16);}else{LcdShowIntNum(72,118,RTC_Calendar.day,2,WHITE,RED,16);}switch (RTC_Calendar.week){case 0:LcdShowString(88,118," SUN ",WHITE,RED,16);break;case 1:LcdShowString(88,118," MON ",WHITE,RED,16);break;case 2:LcdShowString(88,118," TUE ",WHITE,RED,16);break;case 3:LcdShowString(88,118," WED ",WHITE,RED,16);break;case 4:LcdShowString(88,118," THU ",WHITE,RED,16);break;case 5:LcdShowString(88,118," FRI ",WHITE,RED,16);break;case 6:LcdShowString(88,118," SAT ",WHITE,RED,16);break;default:break;}if(RTC_Calendar.hour < 10){LcdShowIntNum(8,140,0,1,WHITE,RED,16);LcdShowIntNum(16,140,RTC_Calendar.hour,1,WHITE,RED,16);}else{LcdShowIntNum(8,140,RTC_Calendar.hour,2,WHITE,RED,16);}LcdShowString(24,140,":",WHITE,RED,16);if(RTC_Calendar.minute < 10){LcdShowIntNum(32,140,0,1,WHITE,RED,16);LcdShowIntNum(40,140,RTC_Calendar.minute,1,WHITE,RED,16);}else{LcdShowIntNum(32,140,RTC_Calendar.minute,2,WHITE,RED,16);}LcdShowString(48,140,":",WHITE,RED,16);if(RTC_Calendar.second < 10){LcdShowIntNum(56,140,0,1,WHITE,RED,16);LcdShowIntNum(64,140,RTC_Calendar.second,1,WHITE,RED,16);}else{LcdShowIntNum(56,140,RTC_Calendar.second,2,WHITE,RED,16);}
}void RTC_LoadDefault(void)
{char    Date[20], Time[20];char    Text[6][5];uint8_t i = 0, Index = 0, Month = 0;char *MonthTable[12] ={"Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec",};char *str;memset(Date, 0, sizeof(Date));memset(Time, 0, sizeof(Time));memset(Text, 0, sizeof(Text));memcpy(Date, __DATE__, sizeof(__DATE__));memcpy(Time, __TIME__, sizeof(__TIME__));str = strtok(Date, " ");while (str != NULL){memcpy(Text[Index++], str, strlen(str));str = strtok(NULL, " ");}str = strtok(Time, ":");while (str != NULL){memcpy(Text[Index++], str, strlen(str));str = strtok(NULL, ":");}for (i = 0; i < 12; i++){if (0 == strcmp(Text[0], MonthTable[i])){Month = i + 1;}}RTC_Calendar.day    = atoi(Text[1]);RTC_Calendar.month  = Month;RTC_Calendar.year   = atoi(Text[2]);RTC_Calendar.hour   = atoi(Text[3]);RTC_Calendar.minute = atoi(Text[4]);RTC_Calendar.second = atoi(Text[5]);RTC_SetDateTime(RTC_Calendar.year, RTC_Calendar.month, RTC_Calendar.day, RTC_Calendar.hour, RTC_Calendar.minute, RTC_Calendar.second);
}void RTC_Configure(void)
{NVIC_InitTypeDef NVIC_InitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWRDBG | RCC_APB1Periph_BKP, ENABLE);PWR_BackupAccessCmd(ENABLE);BKP_DeInit();if (BKP_ReadBackupRegister(BKP_DR1) != 0x5D5D){RCC_LSEConfig(RCC_LSE_ON);while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){}RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);RCC_RTCCLKCmd(ENABLE);RTC_WaitForSynchro();RTC_WaitForLastTask();RTC_ITConfig(RTC_IT_SEC, ENABLE);RTC_WaitForLastTask();RTC_SetPrescaler(32767);RTC_WaitForLastTask();printf("\r\n%s", __FUNCTION__);BKP_WriteBackupRegister(BKP_DR1, 0x5D5D);}else{printf("\r\nNeed't to configure RTC...");RTC_WaitForSynchro();RTC_ITConfig(RTC_IT_SEC, ENABLE);RTC_WaitForLastTask();}NVIC_InitStruct.NVIC_IRQChannel = RTC_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);RTC_LoadDefault();
}

函数LCDTest更改成如下:

uint8_t number = 0;
void LCDTest(void)
{LcdShowIntNum(8,10,2025,4,BLUE,GREEN,16);LcdShow16x16Hz(40,10,0, BLUE,GREEN);LcdShow16x16Hz(56,10,1, BLUE,GREEN);LcdShow16x16Hz(72,10,2, BLUE,GREEN);LcdShow16x16Hz(88,10,3, BLUE,GREEN);LcdShow16x16Hz(104,10,4,BLUE,GREEN);LcdShow16x16Hz(8,30,5,  BLUE,GREEN);LcdShow16x16Hz(24,30,6, BLUE,GREEN);LcdShowString(40,30," ",BLUE,GREEN,16);LcdShowString(44,30,"MM32F5260",BLUE, GREEN,16);LcdShow16x16Hz(8,50,7,  BLUE,GREEN);LcdShow16x16Hz(24,50,8, BLUE,GREEN);LcdShow16x16Hz(40,50,9, BLUE,GREEN);LcdShowImage(0,70, 128, 40, gImage_2);number++;if(number > 100)number = 0;LcdShowIntNum(80,140,number,3,WHITE,RED,16);
}

mm32f5260_it.c文件中增加RTC_IRQHandler()中断函数如下:

void RTC_IRQHandler(void)
{if (RESET != RTC_GetITStatus(RTC_IT_SEC)){RTC_UpdateCalendar();RTC_PrintDateTime();RTC_ClearITPendingBit(RTC_IT_SEC);RTC_WaitForLastTask();}
}

四、日历时钟显示

由上述源码可知,RTC的初始值是由工程编译时产生的Text文本时间属性所定义的,因此无需手动输入,编译完下载自动重启后便与电脑端同步时钟了。这里为了显示更标准化,将月份、日期、时、分、秒固定输出两位数字,采用24小时制,显示的效果呈现如下视频。
https://www.youku.com/video/XNjQ1MDM3OTU2NA==
在这里插入图片描述

相关文章:

  • EasyRTC嵌入式音视频通信SDK助力物联网/视频物联网音视频打造全场景应用
  • 简约商务年终工作总结报告PPT模版分享
  • ingress-nginx 开启 Prometheus 监控 + Grafana 查看指标
  • 基于Selenium+Python的web自动化测试框架
  • 【Auto.js例程】华为备忘录导出到其他手机
  • leetcode sql50题
  • grafana-mcp-analyzer:基于 MCP 的轻量 AI 分析监控图表的运维神器!
  • PLSQLDeveloper配置OracleInstantClient连接Oracle数据库
  • F5 – TCP 连接管理:会话、池级和节点级操作
  • vue3:十五、管理员管理-页面搭建
  • MongoDB学习和应用(高效的非关系型数据库)
  • STM32实战: CAN总线数据记录仪设计方案
  • AndroidR车机TextToSpeech音频焦点异常问题分析
  • LLM Agent 如何颠覆股价预测的传统范式
  • 添加训练噪声以改进检测——去噪机制
  • C# WPF 左右布局实现学习笔记(1)
  • c语言 头文件封装跨平台线程
  • 视频的分片上传,断点上传
  • day48 python通道注意力
  • 云原生玩法三问:构建自定义开发环境
  • 自动推广工具/seo优化教学视频
  • 百度收录网站但首页快照不更新/时事新闻最新
  • 企业营销型网站类型/软文有哪些推广渠道
  • 廊坊网站搜索优化/外链吧怎么使用
  • 南宁电商网络推广/优化seo哪家好
  • 用三权重的网站做友链有好处没/东莞关键词优化平台