1. 使用 CubeMx 创建 RTC 工程
打开 CubeMx 软件,选中我们此次使用的单片机型号 STM32G030F6P6 ,点击 StartProject.
先配置一下串口,用来打印相关信息
再来配置 RTC
配置时钟
ps:本实验使用内部低速时钟测试,未使用外部晶振.
配置工程相关选项
配置完成后点击右上角 GENERATE CODE完成工程的创建
2. 编程
2.1 熟悉一下 Hal 库中 RTC 使用到的相关 API 接口
- /*设置系统时间*/
- HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
- /*读取系统时间*/
- HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
- /*设置系统日期*/
- HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
- /*读取系统日期*/
- HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
- /*启动报警功能*/
- HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
- /*设置报警中断*/
- HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
- /*报警时间回调函数*/
- __weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
- /*写入后备储存器*/
- void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)
- /*读取后备储存器*/
- uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister
复制代码
2.2 串口相关的代码
因打印相关信息需要使用 printf ,需要包含 stdio.h 的头文件,且需要重新设 fputc 的函数
- /* Includes ------------------------------------------------------------------*/
- #include "main.h"
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
- #include "stdio.h"
- /* USER CODE END Includes */
- /* Private typedef -----------------------------------------------------------*/
- /* USER CODE BEGIN PTD */
- /* USER CODE END PTD */
- /* Private define ------------------------------------------------------------*/
- /* USER CODE BEGIN PD */
- /* USER CODE END PD */
- /* Private macro -------------------------------------------------------------*/
- /* USER CODE BEGIN PM */
- /* USER CODE END PM */
- /* Private variables ---------------------------------------------------------*/
- RTC_HandleTypeDef hrtc;
- UART_HandleTypeDef huart1;
- /* USER CODE BEGIN PV */
- RTC_DateTypeDef date; //读取日期
- RTC_TimeTypeDef time; //读取时间
- uint8_t RTCStatus = 0; //指示RTC状态
- /* USER CODE END PV */
- /* Private function prototypes -----------------------------------------------*/
- void SystemClock_Config(void);
- static void MX_GPIO_Init(void);
- static void MX_RTC_Init(void);
- static void MX_USART1_UART_Init(void);
- /* USER CODE BEGIN PFP */
- // fputc 函数重映射
- #ifdef __GNUC_
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #else
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #endif
- PUTCHAR_PROTOTYPE
- {
- HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 0xFFFF);
- return ch;
- }
- /* USER CODE END PFP */
复制代码
RTC 初始化
- static void MX_RTC_Init(void)
- {
- /* USER CODE BEGIN RTC_Init 0 */
- /* USER CODE END RTC_Init 0 */
- RTC_TimeTypeDef sTime = {0};
- RTC_DateTypeDef sDate = {0};
- RTC_AlarmTypeDef sAlarm = {0};
- /* USER CODE BEGIN RTC_Init 1 */
- /* USER CODE END RTC_Init 1 */
- /** Initialize RTC Only
- */
- hrtc.Instance = RTC;
- hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
- hrtc.Init.AsynchPrediv = 127;
- hrtc.Init.SynchPrediv = 255;
- hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
- hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
- hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
- hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
- hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
- if (HAL_RTC_Init(&hrtc) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN Check_RTC_BKUP */
- // //重启后判断该寄存器是否有值,判定是不是第丿次初始化,是否要装载初始倿
- // if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) == 0xAA)
- // {
- // //已经初始化过了,直接跳出初始化函
- // return;
- // }
- // //第一次初始化,将任意后备寄存器写任意值,做个标记,标记已经初始化过了,下次系统复位时不用初始匿
- // HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0xAA);
- /* USER CODE END Check_RTC_BKUP */
- /** Initialize RTC and set the Time and Date
- */
- sTime.Hours = 14;
- sTime.Minutes = 50;
- sTime.Seconds = 0;
- sTime.SubSeconds = 0;
- sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
- sTime.StoreOperation = RTC_STOREOPERATION_RESET;
- if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
- {
- Error_Handler();
- }
- sDate.WeekDay = RTC_WEEKDAY_THURSDAY;
- sDate.Month = RTC_MONTH_JANUARY;
- sDate.Date = 28;
- sDate.Year = 21;
- if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
- {
- Error_Handler();
- }
- /** Enable the Alarm A
- */
- sAlarm.AlarmTime.Hours = 14;
- sAlarm.AlarmTime.Minutes = 50;
- sAlarm.AlarmTime.Seconds = 10; //设置 10s 后产生闹钟中断
- sAlarm.AlarmTime.SubSeconds = 0;
- sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
- sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
- sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
- sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
- sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
- sAlarm.AlarmDateWeekDay = 28;
- sAlarm.Alarm = RTC_ALARM_A;
- if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN RTC_Init 2 */
- /* USER CODE END RTC_Init 2 */
- }
复制代码
此初始化函数中 设置了当前的时间和日期,并使能了闹钟中断在 10s 后产生.
配置 RTC 闹钟中断的回调函数及设置下次产生闹钟中断的时间函数
- /* 设置闹钟下次产生的时间 */
- void setalarm(int hours, int minutes, int seconds)
- {
- RTC_AlarmTypeDef sAlarm = {0};
- RTC_DateTypeDef sdate = {0};
- RTC_TimeTypeDef stime = {0};
- //读取当前时间
- HAL_RTC_GetTime(&hrtc, &stime, RTC_FORMAT_BIN);
- HAL_RTC_GetDate(&hrtc, &sdate, RTC_FORMAT_BIN);
- //获取设置中断时的时间
- sAlarm.Alarm = RTC_ALARM_A;
- sAlarm.AlarmTime.Hours = hours + stime.Hours;
- sAlarm.AlarmTime.Minutes = minutes + stime.Minutes;
- sAlarm.AlarmTime.Seconds = seconds + stime.Seconds;
- if(sAlarm.AlarmTime.Seconds >= 60)
- {
- sAlarm.AlarmTime.Seconds = sAlarm.AlarmTime.Seconds % 60;
- sAlarm.AlarmTime.Minutes += 1;
- if(sAlarm.AlarmTime.Minutes >= 60)
- {
- sAlarm.AlarmTime.Minutes = sAlarm.AlarmTime.Minutes % 60;
- sAlarm.AlarmTime.Hours += 1;
- if(sAlarm.AlarmTime.Hours >= 24)
- {
- sAlarm.AlarmTime.Hours = sAlarm.AlarmTime.Hours % 24;
- sdate.Date += 1;
- }
- }
- }
- sAlarm.AlarmTime.SubSeconds = 0;
- sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
- sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
- sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
- sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
- sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
- sAlarm.AlarmDateWeekDay = sdate.Date; //跨天数定时,需要注意
- if(HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
- {
- Error_Handler();
- }
- }
- /**
- * @brief Alarm callback 闹钟中断回调函数
- * @param hrtc : RTC handle
- * @retval None
- */
- void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
- {
- static uint16_t sEnterCnt = 0;
- setalarm(0,0,5); //设置 5s 后再次产生闹钟中断
- printf("Alarm A Interrupt Cnt:%d \r\n",sEnterCnt++);
- }
复制代码
main 函数
- /**
- * @brief The application entry point.
- * @retval int
- */
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- /* USER CODE END 1 */
- /* MCU Configuration--------------------------------------------------------*/
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
- /* USER CODE BEGIN Init */
- /* USER CODE END Init */
- /* Configure the system clock */
- SystemClock_Config();
- /* USER CODE BEGIN SysInit */
- /* USER CODE END SysInit */
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_RTC_Init();
- MX_USART1_UART_Init();
- /* USER CODE BEGIN 2 */
- printf("stm32g030f6 rtc & alarm demo start......\n");
- RTCStatus = 0x01;
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while(1)
- {
- HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
- HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
- printf("20%d-%02d-%02d %02d:%02d:%02d \r\n", date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds);
- HAL_Delay(1000);
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
- }
复制代码
主函数中每隔 1s 读取一次实时日期和时间,并打印出来.
3. 编译并下载测试
将程序下载到开发板中,连接串口助手并打开;
实验现象: 打印实时时间,10s 后,第一次进入中断,并打印进入中断的次数,而后每隔 5s 打印一次进入中断的次数.
|