STM32G030F6使用CubeMx配置RTC及闹钟实验

本文详细指导如何使用CubeMx创建STM32G030F6的RTC工程,包括配置时钟、设置时间和日期、启用闹钟中断,并通过串口打印实时时间和闹钟触发情况。一步步教你完成从工程创建到编译下载的全过程。

1. 使用 CubeMx 创建 RTC 工程

  • 打开 CubeMx 软件,选中我们此次使用的单片机型号 STM32G030F6P6 ,点击 StartProject.

  • 先配置一下串口,用来打印相关信息
    配置串口

  • 再来配置 RTC
    配置RTC日历
    配置闹钟中断A

  • 配置时钟
    配置时钟
    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 打印一次进入中断的次数.
实验现象

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

荻夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值