> 文章列表 > STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

文章目录

    • 一、基础知识点
    • 二、开发环境
    • 三、STM32CubeMX相关配置
    • 四、Vscode代码讲解
    • 五、结果演示
      • 串口显示乱码解决方案

一、基础知识点

本实验通过stm32片内资源RTC实现实时时钟,通过数码管显示时间。设定闹钟,实现准点报时。
数码管相关知识点:
1、数码管 TM1620芯片手册 解析
2、数码管显示
RTC相关知识点:
1、RTC特点
(1)可编程的预分频系数:分频系数最高为2^20。
(2)32位的可编程计数器,可用于较长时间段的测量。
(3)2个分离的时钟:用于APB1接口的PCLK1和RTC时钟(RTC时钟的频率必须小于PCLK1时钟频率的四分之一以上)。
(4)可以选择以下三种RTC的时钟源:

  • HSE时钟除以128
  • LSE振荡器时钟;
  • LSI振荡器时钟

(5)2个独立的复位类型:

  • APB1接口由系统复位;
  • RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位。

(6)3个专门的可屏蔽中断:

  • 闹钟中断,用来产生一个软件可编程的闹钟中断。
  • 秒中断,用来产生一个可编程的周期性中断信号(最长可达1秒)。
  • 溢出中断,指示内部可编程计数器溢出并回转为0的状态

2、RTC内部框图
STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

灰色部分是后备区域,在设备断电后,可由纽扣电池供电。
后备区域包括(RTC时钟预分配器、计数器),这里注意的是闹钟,RTC溢出,秒中断在断电之后不起作用。

3、当断电之后CLK时钟是怎么产生的? ———— LSE时钟(纽扣电池供电)
STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解


二、开发环境

1、硬件开发准备
主控:STM32F103ZET6
芯片内部RTC

2、软件开发准备
软件开发使用虚拟机 + VScode + STM32Cube 开发STM32,在虚拟机中直接完成编译下载。
该部分可参考:软件开发环境构建


三、STM32CubeMX相关配置

1、STM32CubeMX基本配置
本实验基于CubeMX详解构建基本框架 进行开发。

2、STM32CubeMX RTC相关配置
(1)时钟配置
STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

(2)RTC参数配置
STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

(3)中断开启并配置
STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解


四、Vscode代码讲解

1、RTC相关结构体定义以及初始化

typedef struct
{RTC_TimeTypeDef *pMyrtc_current_time;RTC_DateTypeDef *pMyrtc_current_date;void (*Myrtc_Set_Alarm_Time_Date)(void);              // 设置闹钟时间void (*Myrtc_Set_Current_Time_Date)(void);            // 设置当前时间和日期void (*Myrtc_Get_Current_Time_Date)(void);            // 获取当前时间和日期void (*Myrtc_Disp_Current_Time_Date)(void);            // 打印当前时间和日期
} Myrtc_t;extern Myrtc_t Myrtc;Myrtc_t Myrtc ={&RTC_TimeStruct_CurrentValue,&RTC_DateStruct_CurrentValue,Myrtc_Set_Alarm_Time_Date,        // 设置闹钟时间Myrtc_Set_Current_Time_Date,      // 设置当前时间和日期Myrtc_Get_Current_Time_Date,      // 获取当前时间和日期Myrtc_Disp_Current_Time_Date      // 数码管打印当前时间和日期
};

2、函数具体实现

(1)获取当前时间和日期

static void Myrtc_Get_Current_Time_Date(void)
{// 获取当前时间HAL_RTC_GetTime(&hrtc, Myrtc.pMyrtc_current_time, RTC_FORMAT_BIN);// 获取当前日期HAL_RTC_GetDate(&hrtc, Myrtc.pMyrtc_current_date, RTC_FORMAT_BIN);
}

(2)数码管打印当前时间和日期

static void Myrtc_Disp_Current_Time_Date(void)
{//串口打印日期printf("当前时间为: %02u年%02d月%02d日(星期%s)  ", 2000+Myrtc.pMyrtc_current_date->Year,Myrtc.pMyrtc_current_date->Month,Myrtc.pMyrtc_current_date->Date,Week_Str[Myrtc.pMyrtc_current_date->WeekDay]);//串口打印时间printf("%02u:%02u:%02u\\r\\n",Myrtc.pMyrtc_current_time->Hours,Myrtc.pMyrtc_current_time->Minutes,Myrtc.pMyrtc_current_time->Seconds);// 数码管显示Display.Disp(Disp_NUM_GRID1, Myrtc.pMyrtc_current_time->Hours/10, Disp_DP_OFF);Display.Disp(Disp_NUM_GRID2, Myrtc.pMyrtc_current_time->Hours%10, Disp_DP_ON);Display.Disp(Disp_NUM_GRID3, Myrtc.pMyrtc_current_time->Minutes/10, Disp_DP_OFF);Display.Disp(Disp_NUM_GRID4, Myrtc.pMyrtc_current_time->Minutes%10, Disp_DP_ON);Display.Disp(Disp_NUM_GRID5, Myrtc.pMyrtc_current_time->Seconds/10, Disp_DP_OFF);Display.Disp(Disp_NUM_GRID6, Myrtc.pMyrtc_current_time->Seconds%10, Disp_DP_ON);
}

(3)设置当前时间和日期

// 设置时间
static void Myrtc_Set_Current_Date(void)
{RTC_DateTypeDef RTC_DateStruct_SetValue;uint8_t SetValue;printf("=========================DWB日期设置==================\\n");printf("请输入年份(00-99): 20\\n");SetValue = 0xFF;while (SetValue == 0xFF){SetValue = Input_RTC_SetValue(99);}printf("年份被设置为:  20%02u\\n", SetValue);RTC_DateStruct_SetValue.Year = SetValue;getchar();printf("请输入月份(01-12):  \\n");SetValue = 0xFF;while (SetValue == 0xFF){SetValue = Input_RTC_SetValue(12);if(SetValue == 0x00){printf("月份不能设置为0,请重新输入月份:\\r\\n");SetValue = 0xFF;}}printf("月份被设置为:  %02u\\n", SetValue);RTC_DateStruct_SetValue.Month = SetValue;getchar();printf("请输入日期(01-31):  \\n");SetValue = 0xFF;while (SetValue == 0xFF){SetValue = Input_RTC_SetValue(31);if(SetValue == 0x00){printf("日期不能设置为0,请重新输入日期:\\r\\n");    SetValue = 0xFF;}}printf("日期被设置为:  %02u\\r\\n", SetValue);RTC_DateStruct_SetValue.Date = SetValue;getchar();//设置日期HAL_RTC_SetDate(&hrtc,&RTC_DateStruct_SetValue,RTC_FORMAT_BIN);
}// 设置日历
static void Myrtc_Set_Current_Time(void)
{RTC_TimeTypeDef RTC_TimeStruct_SetValue;uint8_t SetValue;printf("=========================DWB时间设置==================\\n");printf("请输入时钟(00-23):  \\n");SetValue = 0xFF;while (SetValue == 0xFF){SetValue = Input_RTC_SetValue(23);}printf("时钟被设置为:  %02u\\n", SetValue);RTC_TimeStruct_SetValue.Hours = SetValue;getchar();printf("请输入分钟(00-59):  \\n");SetValue = 0xFF;while (SetValue == 0xFF){SetValue = Input_RTC_SetValue(59);}printf("分钟被设置为:  %02u\\n", SetValue);RTC_TimeStruct_SetValue.Minutes = SetValue;getchar();printf("请输入秒钟(00-59):  \\n");SetValue = 0xFF;while (SetValue == 0xFF){SetValue = Input_RTC_SetValue(59);}printf("秒钟被设置为:  %02u\\n", SetValue);RTC_TimeStruct_SetValue.Seconds = SetValue;getchar();//设置时间HAL_RTC_SetTime(&hrtc,&RTC_TimeStruct_SetValue,RTC_FORMAT_BIN);
}static void Myrtc_Set_Current_Time_Date(void)
{Myrtc_Set_Current_Date();Myrtc_Set_Current_Time();
}

(4)设置闹钟时间

// 设置闹钟
static void Myrtc_Set_Alarm_Time_Date(void)
{RTC_AlarmTypeDef RTC_AlarmStruct_SetValue;uint8_t SetValue;printf("=========================DWB闹钟时间设置==================\\n");printf("请输入时钟(00-23):  \\n");SetValue = 0xFF;while (SetValue == 0xFF){SetValue = Input_RTC_SetValue(23);}printf("时钟被设置为:  %02u\\n", SetValue);RTC_AlarmStruct_SetValue.AlarmTime.Hours = SetValue;getchar();printf("请输入分钟(00-59):  \\n");SetValue = 0xFF;while (SetValue == 0xFF){SetValue = Input_RTC_SetValue(59);}printf("分钟被设置为:  %02u\\n", SetValue);RTC_AlarmStruct_SetValue.AlarmTime.Minutes = SetValue;getchar();printf("请输入秒钟(00-59):  \\n");SetValue = 0xFF;while (SetValue == 0xFF){SetValue = Input_RTC_SetValue(59);}printf("秒钟被设置为:  %02u\\n", SetValue);RTC_AlarmStruct_SetValue.AlarmTime.Seconds = SetValue;getchar();HAL_RTC_SetAlarm_IT(&hrtc, &RTC_AlarmStruct_SetValue, RTC_FORMAT_BIN);
}

五、结果演示

STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

串口显示乱码解决方案

现象:实验过程中出现与串口通讯中文乱码现象,如下图所示

STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

原因: vscode 编写代码默认是以UTF-8格式编写的,但是SSCOM串口工具是以GBK格式显示的。
因此代码里的需要在串口中显示的中文,会以UTF-8的形式编码。由于SSCOM串口工具只能用GBK格式译码显示,则出现乱码现象。

解决方案:
在编写代码的时候用GBK格式编写,这样就和SSCOM译码格式相符合
STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解