当前位置: 首页 > news >正文

江科大RTC实时时钟hal库实现

首先,因为的LSE无法启振,所以我使用LSI当作RTCCLK,LSI无法由备用电源供电,故主电源掉电时,RTC走时会暂停。

hal库相关函数

时分秒

typedef struct
{uint8_t Hours;            /*!< Specifies the RTC Time Hour.This parameter must be a number between Min_Data = 0 and Max_Data = 23 */uint8_t Minutes;          /*!< Specifies the RTC Time Minutes.This parameter must be a number between Min_Data = 0 and Max_Data = 59 */uint8_t Seconds;          /*!< Specifies the RTC Time Seconds.This parameter must be a number between Min_Data = 0 and Max_Data = 59 */} RTC_TimeTypeDef;

闹钟结构体 

typedef struct
{RTC_TimeTypeDef AlarmTime;     /*!< Specifies the RTC Alarm Time members */uint32_t Alarm;                /*!< Specifies the alarm ID (only 1 alarm ID for STM32F1).This parameter can be a value of @ref RTC_Alarms_Definitions */
} RTC_AlarmTypeDef;

初始化结构体 

typedef struct
{uint32_t AsynchPrediv;    /*异步预分频器,对RTC时钟源进行分频*/uint32_t OutPut;          /*时钟输出*/} RTC_InitTypeDef;

 日期结构体

typedef struct
{uint8_t WeekDay;  /*!< Specifies the RTC Date WeekDay (not necessary for HAL_RTC_SetDate).This parameter can be a value of @ref RTC_WeekDay_Definitions */uint8_t Month;    /*!< Specifies the RTC Date Month (in BCD format).This parameter can be a value of @ref RTC_Month_Date_Definitions */uint8_t Date;     /*!< Specifies the RTC Date.This parameter must be a number between Min_Data = 1 and Max_Data = 31 */uint8_t Year;     /*!< Specifies the RTC Date Year.This parameter must be a number between Min_Data = 0 and Max_Data = 99 */} RTC_DateTypeDef;

句柄

#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
typedef struct __RTC_HandleTypeDef
#else
typedef struct
#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS) */
{RTC_TypeDef                 *Instance;  /*外设地址*/RTC_InitTypeDef             Init;       /*初始化结构体*/RTC_DateTypeDef             DateToUpdate;       /*初始化上电时间*/HAL_LockTypeDef             Lock;       /*配置锁存*/__IO HAL_RTCStateTypeDef    State;      /*当前状态*/#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)void (* AlarmAEventCallback)(struct __RTC_HandleTypeDef *hrtc);           /*!< RTC Alarm A Event callback         */void (* Tamper1EventCallback)(struct __RTC_HandleTypeDef *hrtc);          /*!< RTC Tamper 1 Event callback        */void (* MspInitCallback)(struct __RTC_HandleTypeDef *hrtc);               /*!< RTC Msp Init callback              */void (* MspDeInitCallback)(struct __RTC_HandleTypeDef *hrtc);             /*!< RTC Msp DeInit callback            */#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS) */} RTC_HandleTypeDef;

 初始化函数

HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc);
HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc);
void              HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc);
void              HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc);

设置日期时间

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);
HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm);
HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format);
void              HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc);
HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout);
void              HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc);

hal库实现江科大 

首先就是对RTC的初始化,得开启BKP和PWR先关时钟,CubeMx帮我们开启了。

开启RTC时钟源,在时钟树那边设置RTC的时钟源,我选择的是LSI.

 BKP的相关函数在RTC和RTC_EX里面,没有专门的hal_BKP文件。

读写BKP函数

void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)
uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)

对于江科大的相关函数,首先标准库里面很多的函数hal库里面都没有,所以得找个替换的方式,有些相关函数对于hal库是不起作用的,我们也得将他们删去。

//江科大RTC初始化函数
void MyRTC_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);//开启BKP,PWR时钟PWR_BackupAccessCmd(ENABLE);//使能通道if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)//判断BKP_DR1内容{RCC_LSICmd(ENABLE);//开启LSI时钟while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) != SET);//等待时钟就绪RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//配置LSI到RTC的时钟RCC_RTCCLKCmd(ENABLE);RTC_WaitForSynchro();//等待时钟同步RTC_WaitForLastTask();RTC_SetPrescaler(40000 - 1);//配置预分频值RTC_WaitForLastTask();//等待上个工作完成MyRTC_SetTime();//设置时间BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//写入BKP_DR1}else{RCC_LSICmd(ENABLE);				//即使不是第一次配置,也需要再次开启LSI时钟while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) != SET);RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);RCC_RTCCLKCmd(ENABLE);RTC_WaitForSynchro();RTC_WaitForLastTask();}
}

这段代码里面,对于LSI和RTC的时钟是不需要我们进行配置的,CubeMX里面已经直接帮我们配置好且开启时钟了,我们只需要先开启BKP和PWR时钟,再对BKP进行读写和设置时间即可。

对于时分秒的计算,RTC的相关函数HAL_RTC_GetTime在函数里面对时间戳进行计算得到对应的时分秒,我们开启秒中断让他的时间戳一秒自增一次就行了。(内部自动进行自增)

秒中断 __HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC);也在rtc_ex文件里面

hal库的日期读写则是通过读取RTC内部的寄存器内容来获取日期,日期也是在外面写入之后RTC内部自己进行维护的。

  RTC_DateTypeDef GetData;  //获取日期结构体RTC_TimeTypeDef GetTime;   //获取时间结构体
int main(void)
{HAL_Init();SystemClock_Config();OLED_Init();MX_GPIO_Init();MX_RTC_Init();OLED_ShowString(1, 1, "Date:XXXX-XX-XX");OLED_ShowString(2, 1, "Time:XX:XX:XX");
//    OLED_ShowString(3, 1, "CNT :");
//    OLED_ShowString(4, 1, "DIV :");while (1){HAL_RTC_GetTime(&hrtc,&GetTime,RTC_FORMAT_BIN);HAL_RTC_GetDate(&hrtc,&GetData,RTC_FORMAT_BIN);OLED_ShowNum(1, 6,(2000+GetData.Year), 4);		//显示MyRTC_Time数组中的时间值,年OLED_ShowNum(1, 11,GetData.Month, 2);		//月OLED_ShowNum(1, 14, GetData.Date, 2);		//日OLED_ShowNum(2, 6, GetTime.Hours, 2);		//时OLED_ShowNum(2, 9, GetTime.Minutes, 2);		//分OLED_ShowNum(2, 12, GetTime.Seconds, 2);		//秒HAL_Delay(1000);//    OLED_ShowNum(3, 6, RTC_GetCounter(), 10);	//显示32位的秒计数器,没有相关函数,但是可以通过读写寄存器,或者对时间进行逻辑推导来实现
//    OLED_ShowNum(4, 6, RTC_GetDivider(), 10);	//显示余数寄存器}
}

日期的存入读取有问题,我们把日期存入BKP里面,第一次上电初始化的时候写入,其他时间上电从BKP里面读取,这样也能实现日期的正常读写。

void MX_RTC_Init(void)
{RTC_TimeTypeDef sTime = {0};RTC_DateTypeDef DateToUpdate = {0};__HAL_RCC_BKP_CLK_ENABLE();       //开启后备区域时钟__HAL_RCC_PWR_CLK_ENABLE();		  //开启电源时钟hrtc.Instance = RTC;hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;if (HAL_RTC_Init(&hrtc) != HAL_OK){Error_Handler();}if(HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR1) != 0xA5A5){sTime.Hours = 15;sTime.Minutes = 51;sTime.Seconds = 0;if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}__HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC);HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR1, 0xA5A5);//写入DR1的判断数据DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY;DateToUpdate.Month = RTC_MONTH_JUNE;DateToUpdate.Date = 02;DateToUpdate.Year = 25;if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, (uint16_t)DateToUpdate.Year);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, (uint16_t)DateToUpdate.Month);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, (uint16_t)DateToUpdate.Date);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, (uint16_t)DateToUpdate.WeekDay);}else{DateToUpdate.Year    = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);DateToUpdate.Month   = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3);DateToUpdate.Date    = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);DateToUpdate.WeekDay = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR5);if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}__HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC);	 //开启RTC时钟秒中断	}
}

代码参考了小璇的相关代码

这样也能实现江科大的RTC时钟了 

http://www.xdnf.cn/news/775531.html

相关文章:

  • 模块二:C++核心能力进阶(5篇)第三篇:《异常安全:RAII与异常传播的最佳实践》
  • 性能测试的概念和场景设计
  • 【LLM】AI Agents vs. Agentic AI(概念应用挑战)
  • 污痕圣杯:阿瓦隆的陨落 整合包 离线版
  • vite构建工具
  • Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String
  • 基于springboot的家政服务预约系统
  • LINUX62软链接;核心目录;错题:rpm -qa |grep<包名> 、rpm -ql<包名>;rm -r rm -rf;合并 cat
  • Ubuntu安装遇依赖包冲突解决方法
  • Flex 布局基础
  • svg与Three.js对比
  • 295. 数据流的中位数
  • DAY01:【ML 第三弹】基本概念和建模流程
  • GNURadio实现MIMO OFDM文件传输
  • 17.进程间通信(三)
  • ps可选颜色调整
  • 每日一道面试题---ArrayList的自动扩容机制(口述版本)
  • LLM模型量化从入门到精通:Shrink, Speed, Repeat
  • Java线程生命周期详解
  • 【数据分析】第三章 numpy(1)
  • 第二十一章 格式化输出
  • 制作开发AI试衣换装小程序系统介绍
  • URP - 水效果Shader
  • 类和对象(二)
  • 《Pytorch深度学习实践》ch3-反向传播
  • 使用ArcPy批量处理矢量数据
  • 力扣刷题Day 67:N 皇后(51)
  • 树莓派实验
  • 使用Bambi包进行贝叶斯混合效应模型分析
  • 强化学习-深度学习和强化学习领域