[【极海APM32F407】 1. 开箱啦](https://bbs.eeworld.com.cn/thread-1244122-1-1.html)
[【极海APM32F407】2. KEIL下实现printf和scanf对串口的重定向](https://bbs.eeworld.com.cn/thread-1244768-1-1.html)
[【极海APM32F407】 3. 极简方式集成FreeRTOS](https://bbs.eeworld.com.cn/thread-1245426-1-1.html)
[【极海APM32F407】 4. 程序下载问题以及解决方法](https://bbs.eeworld.com.cn/thread-1246321-1-1.html)
# 1 RTC说明
RTC是芯片内部自带的实时时钟芯片,用于精确的自动累计时间,用户字需要设置初始时间,RTC就会自动累计,减少了CPU参与,降低了CPU的负载率,而且RTC的精度很高。本帖将测试APM32F407的RTC。
关于RTC支持的功能,可以参考用户手册《APM32F4xxx用户手册_V1.6.pdf》19 实时时钟(RTC),下面的截图是关于APM32F407的RTC的特性。
# 2 软件实现
官方提供的示例并没有说明如何使用RTC,只是演示了RTC Alarm功能,所以本帖重点在于驱动RTC,讲解RTC的实际用法。
设置初始时间,并周期获取时间通过串口打印显示。
## 2.1 初始化
下面是RTC的初始化代码,初始化RTC时钟,并初始化模式为24小时制。
其中 `Rtc_dateTimeInit`是我自己实现的函数,用于设定RTC的初始化值。
```c
void Rtc_Init(void)
{
RTC_Config_T Struct;
/* Enable the PWR clock */
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);
/* Allow access to RTC */
PMU_EnableBackupAccess();
/* Enable the LSI OSC */
RCM_EnableLSI();
/* Wait till LSE is ready */
while(RCM_ReadStatusFlag(RCM_FLAG_LSIRDY) == RESET)
{
}
/* Select the RTC Clock Source */
RCM_ConfigRTCCLK(RCM_RTCCLK_LSI);
/* Enable RTC Clock*/
RCM_EnableRTCCLK();
/* Disable Write Proctection */
RTC_DisableWriteProtection();
/* Wait Synchro*/
RTC_WaitForSynchro();
RTC_ConfigStructInit(&Struct);
RTC_Config(&Struct);
Rtc_DateTimeInit();
}
```
# 2.2 设置初始时间日期
下面的代码用于设置初始时间和日期:
- 设置日期为2023年6月9日,星期五(星期必须设置,不然会默认为0,即星期天)
- 设定时间为22点58分59秒
- 使用BCD格式
- 使用 `RTC_ConfigTime`设置时间,使用 `RTC_ConfigDate`设置日期
```c
static void Rtc_DateTimeInit(void)
{
RTC_TimeConfig_T TimeStruct;
RTC_DateConfig_T DateStruct;
// BCD
// TimeStruct.h12 = RTC_H12_AM;
TimeStruct.hours = 0x22;
TimeStruct.minutes = 0x58;
TimeStruct.seconds = 0x59;
DateStruct.year = 0x23;
DateStruct.month = RTC_MONTH_JUNE;
DateStruct.date = 0x09;
DateStruct.weekday = RTC_WEEKDAY_FRIDAY;
RTC_ConfigTime(RTC_FORMAT_BCD, &TimeStruct);
RTC_ConfigDate(RTC_FORMAT_BCD, &DateStruct);
}
```
# 2.3 显示时间
下面的代码用于串口打印时间和日期.
首先调用 `RTC_ReadTime`和 `RTC_ReadDate`分别获取当前的时间和日期,然后通过串口打印出来。
```c
void Rtc_ShowTime(void)
{
RTC_TimeConfig_T TimeStruct;
RTC_DateConfig_T DateStruct;
static const char *week[7] = {"Sun.", "Mon.", "Tue.", "Wed.", "Thu.", "Fri.", "Sat."};
RTC_ReadTime(RTC_FORMAT_BCD, &TimeStruct);
RTC_ReadDate(RTC_FORMAT_BCD, &DateStruct);
printf ("DateTime:20%02x-%02x-%02x(%s) %02x:%02x:%02x\r\n", DateStruct.year,
DateStruct.month,
DateStruct.date,
week[(uint8_t)DateStruct.weekday],
TimeStruct.hours,
TimeStruct.minutes,
TimeStruct.seconds);
}
```
## 2.4 主函数
主函数中调用Rtc_init进行初始化,调用Rtc_ShowTime打印时间日期。
其中使用了 `for (int i=0; i< 10000; i++) for (int j = 0; j< 3000; j++); `来进行延时,所以并不是每一秒钟打印一次。
关于串口如何使用 `printf`打印,可以参考我之前帖子:[【极海APM32F407】2. KEIL下实现printf和scanf对串口的重定向](https://bbs.eeworld.com.cn/thread-1244768-1-1.html)
```c
int main(void)
{
APM_TINY_LEDInit(LED2);
APM_TINY_LEDInit(LED3);
USART_Init();
Rtc_Init();
printf ("aaaa\r\n");
/** SysTick Initialization */
SysTick_Init();
APM_TINY_LEDOn(LED2);
APM_TINY_LEDOn(LED3);
while(1)
{
Rtc_ShowTime();
for (int i=0; i< 10000; i++)
for (int j = 0; j< 3000; j++);
}
}
```
# 3 试验效果
下面是打印效果,测试成功,可以正常使用RTC。