【WCH】CH32F203基于内部RTC时钟+SSD1306 OLED显示
-
📌相关篇《STM32F103基于标准库+I2C SSD1306仿数码管RTC时钟显示》
-
✨CH32F203的内部时钟频率:40KHz
-
🔖基于Keil开发环境
-
📜基于SDK中的RTC示例修改为内部时钟源,串口打印:
-
🌼I2C SSD1306 OLED显示
⛳RTC内部时钟源修改注意事项
- RTC内部时钟源的频率为40KHz。
🛠RTC内部时钟源代码修改
/*********************************************************************
* @fn RTC_Init
*
* @brief Initializes RTC collection.
*
* @return 1 - Init Fail
* 0 - Init Success
*/
u8 RTC_Init(void)
{
u8 temp = 0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
/* Is it the first configuration */
BKP_DeInit();
RCC_LSICmd(ENABLE );//内部时钟使能
// RCC_LSEConfig(RCC_LSE_ON);//外部时钟
// while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && temp < 250)//外部
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET && temp < 250)//内部
{
temp++;
Delay_Ms(20);
}
if(temp >= 250)
{
return 1;
}
RCC_RTCCLKConfig( RCC_RTCCLKSource_LSI );//选择内部时钟源
RCC_RTCCLKCmd( ENABLE );
RTC_WaitForLastTask();
RTC_WaitForSynchro();
// RTC_ITConfig(RTC_IT_ALR, ENABLE);
RTC_ITConfig( RTC_IT_SEC, ENABLE );
RTC_WaitForLastTask();
RTC_EnterConfigMode();
RTC_SetPrescaler( 40000-1 );//内部40KHz
// RTC_SetPrescaler( 32767 );//外部32768HZ
RTC_WaitForLastTask();
RTC_Set( 2023, 4, 25, 16, 58, 55 ); /* Setup Time */
RTC_ExitConfigMode();
BKP_WriteBackupRegister( BKP_DR1, 0XA1A1 );//这里和STM32不一样不是0x5050
RTC_NVIC_Config();
RTC_Get();
return 0;
}
- 🌿RTC.C
#include "RTC.h"
#include "ch32f20x_rtc.h"
#include "ch32f20x_bkp.h"
#include "ch32f20x_pwr.h"
_calendar_obj calendar;
u8 const table_week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
const u8 mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/* Exported_Functions */
/*********************************************************************
* @fn RTC_NVIC_Config
*
* @brief Initializes RTC Int.
*
* @return none
*/
static void RTC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure = {0};
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*********************************************************************
* @fn RTC_Init
*
* @brief Initializes RTC collection.
*
* @return 1 - Init Fail
* 0 - Init Success
*/
u8 RTC_Init(void)
{
u8 temp = 0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
/* Is it the first configuration */
BKP_DeInit();
RCC_LSICmd(ENABLE );
// RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET && temp < 250)
{
temp++;
Delay_Ms(20);
}
if(temp >= 250)
{
return 1;
}
RCC_RTCCLKConfig( RCC_RTCCLKSource_LSI );//仅修改了此处
RCC_RTCCLKCmd( ENABLE );
RTC_WaitForLastTask();
RTC_WaitForSynchro();
// RTC_ITConfig(RTC_IT_ALR, ENABLE);
RTC_ITConfig( RTC_IT_SEC, ENABLE );
RTC_WaitForLastTask();
RTC_EnterConfigMode();
RTC_SetPrescaler( 40000-1 );//内部40KHz
// RTC_SetPrescaler( 32767 );//外部32768HZ
RTC_WaitForLastTask();
RTC_Set( 2023, 4, 25, 16, 58, 55 ); /* Setup Time */
RTC_ExitConfigMode();
BKP_WriteBackupRegister( BKP_DR1, 0XA1A1 );
RTC_NVIC_Config();
RTC_Get();
return 0;
}
/*********************************************************************
* @fn Is_Leap_Year
*
* @brief Judging whether it is a leap year.
*
* @param year
*
* @return 1 - Yes
* 0 - No
*/
u8 Is_Leap_Year(u16 year)
{
if(year % 4 == 0)
{
if(year % 100 == 0)
{
if(year % 400 == 0)
{
return 1;
}
else
{
return 0;
}
}
else
{
return 1;
}
}
else
{
return 0;
}
}
/*********************************************************************
* @fn RTC_Set
*
* @brief Set Time.
*
* @param Struct of _calendar_obj
*
* @return 1 - error
* 0 - success
*/
u8 RTC_Set(u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec)
{
u16 t;
u32 seccount = 0;
if(syear < 1970 || syear > 2099)
{
return 1;
}
for(t = 1970; t < syear; t++)
{
if(Is_Leap_Year(t))
{
seccount += 31622400;
}
else
{
seccount += 31536000;
}
}
smon -= 1;
for(t = 0; t < smon; t++)
{
seccount += (u32)mon_table[t] * 86400;
if(Is_Leap_Year(syear) && t == 1)
{
seccount += 86400;
}
}
seccount += (u32)(sday - 1) * 86400;
seccount += (u32)hour * 3600;
seccount += (u32)min * 60;
seccount += sec;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_SetCounter(seccount);
RTC_WaitForLastTask();
return 0;
}
/*********************************************************************
* @fn RTC_Alarm_Set
*
* @brief Set Alarm Time.
*
* @param Struct of _calendar_obj
*
* @return 1 - error
* 0 - success
*/
u8 RTC_Alarm_Set(u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec)
{
u16 t;
u32 seccount = 0;
if(syear < 1970 || syear > 2099)
{
return 1;
}
for(t = 1970; t < syear; t++)
{
if(Is_Leap_Year(t))
{
seccount += 31622400;
}
else
{
seccount += 31536000;
}
}
smon -= 1;
for(t = 0; t < smon; t++)
{
seccount += (u32)mon_table[t] * 86400;
if(Is_Leap_Year(syear) && t == 1)
{
seccount += 86400;
}
}
seccount += (u32)(sday - 1) * 86400;
seccount += (u32)hour * 3600;
seccount += (u32)min * 60;
seccount += sec;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_SetAlarm(seccount);
RTC_WaitForLastTask();
return 0;
}
/*********************************************************************
* @fn RTC_Get
*
* @brief Get current time.
*
* @return 1 - error
* 0 - success
*/
u8 RTC_Get(void)
{
static u16 daycnt = 0;
u32 timecount = 0;
u32 temp = 0;
u16 temp1 = 0;
timecount = RTC_GetCounter();
temp = timecount / 86400;
if(daycnt != temp)
{
daycnt = temp;
temp1 = 1970;
while(temp >= 365)
{
if(Is_Leap_Year(temp1))
{
if(temp >= 366)
{
temp -= 366;
}
else
{
temp1++;
break;
}
}
else
{
temp -= 365;
}
temp1++;
}
calendar.w_year = temp1;
temp1 = 0;
while(temp >= 28)
{
if(Is_Leap_Year(calendar.w_year) && temp1 == 1)
{
if(temp >= 29)
{
temp -= 29;
}
else
{
break;
}
}
else
{
if(temp >= mon_table[temp1])
{
temp -= mon_table[temp1];
}
else
{
break;
}
}
temp1++;
}
calendar.w_month = temp1 + 1;
calendar.w_date = temp + 1;
}
temp = timecount % 86400;
calendar.hour = temp / 3600;
calendar.min = (temp % 3600) / 60;
calendar.sec = (temp % 3600) % 60;
calendar.week = RTC_Get_Week(calendar.w_year, calendar.w_month, calendar.w_date);
return 0;
}
/*********************************************************************
* @fn RTC_Get_Week
*
* @brief Get the current day of the week.
*
* @param year/month/day
*
* @return week
*/
u8 RTC_Get_Week(u16 year, u8 month, u8 day)
{
u16 temp2;
u8 yearH, yearL;
yearH = year / 100;
yearL = year % 100;
if(yearH > 19)
{
yearL += 100;
}
temp2 = yearL + yearL / 4;
temp2 = temp2 % 7;
temp2 = temp2 + day + table_week[month - 1];
if(yearL % 4 == 0 && month < 3)
{
temp2--;
}
return(temp2 % 7);
}
/*********************************************************************
* @fn RTC_IRQHandler
*
* @brief This function handles RTC Handler.
*
* @return none
*/
void RTC_IRQHandler( void )
{
if( RTC_GetITStatus( RTC_IT_SEC ) != RESET ) /* Seconds interrupt */
{
RTC_Get();
}
if( RTC_GetITStatus( RTC_IT_ALR ) != RESET ) /* Alarm clock interrupt */
{
RTC_ClearITPendingBit( RTC_IT_ALR );
RTC_Get();
}
RTC_ClearITPendingBit( RTC_IT_SEC | RTC_IT_OW );
RTC_WaitForLastTask();
}
- 🌿RTC.H
#ifndef __RTC_H
#define __RTC_H
#include "debug.h"
typedef struct
{
vu8 hour;
vu8 min;
vu8 sec;
vu16 w_year;
vu8 w_month;
vu8 w_date;
vu8 week;
} _calendar_obj;
extern _calendar_obj calendar;
extern u8 const mon_table[12]; //月份日期数据表
u8 RTC_Init( void );
u8 Is_Leap_Year( u16 year );
u8 RTC_Alarm_Set( u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec );
u8 RTC_Get( void );
u8 RTC_Get_Week( u16 year, u8 month, u8 day );
u8 RTC_Set( u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec );
#endif
- main.c
/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Main program body.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*
*@Note
Calendar routine:
This routine demonstrates that the initial time is 13:58:55 on October 8, 2019, real-time timing,
every 1S through the serial port print the real-time clock value.
*/
#include "debug.h"
#include "RTC.h"
/* Global define */
/* Global Variable */
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main( void )
{
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 );
Delay_Init();
USART_Printf_Init( 115200 );
printf( "SystemClk:%d\r\n", SystemCoreClock );
printf( "RTC Test\r\n" );
if(RTC_Init()==0)
{
printf("Init Fail \r\n");
}else printf("Init Success \r\n");
while( 1 )
{
Delay_Ms( 1000 );
printf( "year/month/day/week/hour/min/sec:\r\n" );
printf( "%d-%d-%d %d %d:%d:%d\r\n", calendar.w_year, calendar.w_month, calendar.w_date,
calendar.week, calendar.hour, calendar.min, calendar.sec );
}
}
- 🌿基于内部时钟源,串口打印RTC时间源码
链接: https://pan.baidu.com/s/1affWjahgxh9seB-9bcxF8g
提取码: chiw
- 🌿基于STM32移植到CH32F203TC时钟+I2C SSD1306 OLED显示程序
链接: https://pan.baidu.com/s/1gMHbHdmvWhQqolOjeaLuZg
提取码: w9gc