很多人只会使用瑞萨单片机自带的RTC日历,如果让它们用一个普通的定时器来实现RTC的功能,它们永远都实现不了,学不会!已经故步自封了。
本帖就是来给这些人扫盲的,就让我来用最普通的定时器实现软件万年历!!!
我的软件架构设计如下图所示

这里直接使用ARM CM3的systick定时器,所以不需要配置RA smart了,直接用我之前配好的串口工程即可。
直接上核心代码
#include "Systick.h"
#include "ebtn_app.h"
volatile uint32_t g_tick_count = 0;
volatile uint32_t g_20ms = 0;
void hal_systick_init(void)
{
SysTick_Config(SystemCoreClock / TICKS_PER_SECONDS);
}
uint32_t HAL_GetTick(void)
{
return g_tick_count;
}
void HAL_Delay(uint32_t Delay)
{
#define HAL_MAX_DELAY 0xFFFFFFFFU
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait++;
}
while ((HAL_GetTick() - tickstart) < wait)
{
}
}
TimeStamp datetime;
volatile uint32_t Timer_1s_Count;
/**
- [url=home.php?mod=space&uid=2666770]@Brief[/url] Set the time variable of the calendar function
- @param[in] Year: This parameter is year.
- @param[in] Month: This parameter is month.
- @param[in] Day: This parameter is day.
- @param[in] Hour: This parameter is hour.
- @param[in] Min: This parameter is min.
- @param[in] Second: This parameter is second.
- @retval Non.
*/
void Calendar_TimeVariable_Set(uint16_t Year,uint8_t Month,uint8_t Day,uint8_t Hour,uint8_t Min,uint8_t Second)
{
datetime.year = Year;
datetime.month = Month;
datetime.day = Day;
datetime.hour = Hour;
datetime.min = Min;
datetime.second = Second;
}
/**
- @brief Judge whether the number of days in the month is 31
- @param[in] month: This parameter is month.
- @retval Yes(1) or No(0).
*/
uint8_t BigMonth(uint8_t month)
{
if(month==1 || month==3 || month==5 || month==7 ||
month==8 || month==10 || month==12)
return 1;
return 0;
}
/**
-
@brief Judge whether the parameter is leap year
-
@param[in] year: This parameter is year.
-
@retval Yes(1) or No(0).
*/
uint8_t LeapYear(uint16_t year)
{
uint16_t y = year;
uint16_t remainder;
remainder = y%4;
if(!remainder)
{
remainder = y%100;
if(remainder) return 1;
else
{
remainder = y%400;
if(remainder) return 0;
}
return 1;
}
return 0;
}
/**
-
@brief Calendar time variable update.
-
@param[in] Non.
-
@retval Non.
*/
void TimeVariable_Processing(void)
{
uint8_t day;
day = datetime.day;
datetime.second += 1;
if(datetime.second>=60)
{
datetime.second -= 60;
datetime.min++;
if(datetime.min>=60)
{
datetime.min -= 60;
datetime.hour++;
if(datetime.hour>=24)
{
datetime.hour -= 24;
day = (++datetime.day);
if(BigMonth(datetime.month))
{
if(day>=32)
{
datetime.day-=31;
day=0xff;
}
}
else
{
if(datetime.month==2)
{
if(LeapYear(datetime.year))
{
if(day>=30)
{
datetime.day-=29;
day=0xff;
}
}
else if(day>=29)
{
datetime.day-=28;
day=0xff;
}
}
else if(day>=31)
{
datetime.day-=30;
day=0xff;
}
}
if(day==0xff)
{
datetime.month++;
if(datetime.month>=13)
{
datetime.month -= 12;
datetime.year++;
}
}
else datetime.day=day;
}
}
}
}
void SysTick_Handler(void)
{
g_tick_count++;
g_20ms++;
if(g_20ms == 20)
{
g_20ms = 0;
}
TimeVariable_Processing();
}

判断大小月

判断闰年

年月日时分秒进制


然后再定时器里调用

TimeVariable_Processing();
主函数核心代码
#include "hal_data.h"
#include "LED.h"
#include "Systick.h"
#include "usart0.h"
#include "usart9.h"
#include "shell.h"
//#include "ebtn_app.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER
/*******************************************************************************************************************//**
-
main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function
-
is called by main() when no RTOS is used.
*********************************************************************************************************************/
void hal_entry(void)
{
/ TODO: add your own code here */
hal_systick_init();
UART0_Init();UART9_Init();
//ebtn_APP_Key_INIT();
//shell_init();
/**** Set the time variable of the calendar ****/
Calendar_TimeVariable_Set(2025,8,31,19,33,00);
while(1)
{
//shell_process();
//printf("现在时间是: %d年%d月%d日%d时%d分%d秒\r\n",ptime.year,ptime.month,ptime.day,ptime.hour,ptime.min,ptime.second);
printf("现在时间是: %d年%d月%02d日%02d时%02d分%02d秒\r\n",datetime.year,datetime.month,datetime.day,datetime.hour,datetime.min,datetime.second);
HAL_Delay(1000);
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
/*******************************************************************************************************************//**
-
This function is called at various points during the startup process. This implementation uses the event that is
-
called right before main() to set up the pins.
-
@param[in] event Where at in the start up process the code is currently at
**********************************************************************************************************************/
void R_BSP_WarmStart (bsp_warm_start_event_t event)
{
if (BSP_WARM_START_RESET == event)
{
#if BSP_FEATURE_FLASH_LP_VERSION != 0
R_FACI_LP->DFLCTL = 1U;
#endif
}
if (BSP_WARM_START_POST_C == event)
{
R_IOPORT_Open(&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);
#if BSP_CFG_SDRAM_ENABLED
R_BSP_SdramInit(true);
#endif
}
}
#if BSP_TZ_SECURE_BUILD
FSP_CPP_HEADER
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();
/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{
}
FSP_CPP_FOOTER
#endif

烧录代码

打开串口助手


可以看到和网络时间一致,非常的准确
详情看视频