常用函数
1 | void BKP_DeInit(void); |
BKP_DeInit恢复缺省配置,手动清空BKP所有的数据寄存器。
1 | void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel); |
用于配置TAMPER侵入检测功能,配置TAMPER引脚有效电平,高电平触发还是低电平触发。
1 | void BKP_TamperPinCmd(FunctionalState NewState); |
用于配置TAMPER侵入检测功能,是否开启侵入检测功能。
1 | void BKP_ITConfig(FunctionalState NewState); |
中断配置,是否开启中断。
1 | void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource); |
时钟输出功能,可以选择在RTC引脚上输出时钟信号,输出RTC校准时钟,RTC闹钟脉冲或秒脉冲。
1 | void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue); |
设置RTC校准值,写入RTC校准寄存器。
1 | void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data); |
写备份寄存器,第一个参数指定,写在哪个DR里,第二个参数指定要写入的数据。
1 | uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR); |
读备份寄存器,参数指定要读哪个DR。
1 | FlagStatus BKP_GetFlagStatus(void); |
获取BKP状态
1 | void BKP_ClearFlag(void); |
清除BKP侵入检测寄存器状态。
1 | ITStatus BKP_GetITStatus(void); |
获取侵入检测的中断状态。
1 | void BKP_ClearITPendingBit(void); |
清除侵入检测的中断挂起位。
1 | void PWR_BackupAccessCmd(FunctionalState NewState); |
备份寄存器访问使能。设置PWR_CR的DBP,使能对BKP和RTC的访问。
1 | void RCC_LSEConfig(uint8_t RCC_LSE); |
配置LSE外部低速时钟
1 | void RCC_LSICmd(FunctionalState NewState); |
配置LSI内部低速时钟
1 | void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource); |
RTCCLK配置,选择RTCCLK时钟源
1 | void RCC_RTCCLKCmd(FunctionalState NewState); |
RTCCLK使能,调用上面函数选择时钟之后,使能。
1 | FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG); |
获取RCC标志位,调用启动时钟函数之后,要等待标志位,LSERDY置1后,才算启动完成。
1 | void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState); |
配置RTC中断输出
1 | void RTC_EnterConfigMode(void); |
进入配置模式,CNF位置1。
1 | void RTC_ExitConfigMode(void); |
RTC退出配置模式,把CNF位置0。
1 | uint32_t RTC_GetCounter(void); |
RTC获取CNT计数器的值。用于读取时钟。
1 | void RTC_SetCounter(uint32_t CounterValue); |
写入CNT计数器的值。用于设置时间。
1 | void RTC_SetPrescaler(uint32_t PrescalerValue); |
写入预分频器,写入到预分频的PRL重装寄存器中,配置预分频器的分频系数。
1 | void RTC_SetAlarm(uint32_t AlarmValue); |
写入闹钟值,用于配置闹钟。
1 | uint32_t RTC_GetDivider(void); |
获取预分频器中的DIV余数寄存器。余数寄存器是一个自减计数器,获取这个值,一般是为了获取更细致的时间。
1 | void RTC_WaitForLastTask(void); |
等待上次操作完成。
1 | void RTC_WaitForSynchro(void); |
等待同步。清除RSF标志位,然后循环,直到RSF为1。
1234 | FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);void RTC_ClearFlag(uint16_t RTC_FLAG);ITStatus RTC_GetITStatus(uint16_t RTC_IT);void RTC_ClearITPendingBit(uint16_t RTC_IT); |
RTC标志位相关函数。
读写备份寄存器
main.c
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 | uint16_t ArrayWrite[] = {0x1234,0x5678};//存放写入数据的数组uint16_t ArrayRead[2];//存放读取数据的数组uint8_t KeyNum; int main(void){ OLED_Init(); KEY_Init(); OLED_ShowString(1,1,"W:"); OLED_ShowString(2,1,"R:"); RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//开启APB1的PWR外设时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//开启APB1的BKP外设时钟 PWR_BackupAccessCmd(ENABLE);//使能PWR //BKP_WriteBackupRegister(BKP_DR1,0x1234);//BKP写入,在BKPDR1中写入了0x1234 //OLED_ShowHexNum(1,1,BKP_ReadBackupRegister(BKP_DR1),4);//OLED显示写入的值 while(1) { KeyNum = Key_GetNum();//获取按钮状态 if(KeyNum == 1) { ArrayWrite[0]++;//写入的数据自增1 ArrayWrite[1]++; BKP_WriteBackupRegister(BKP_DR1,ArrayWrite[0]);//把ArrayWrite[0]的数据写入到DR1中 BKP_WriteBackupRegister(BKP_DR2,ArrayWrite[1]);//把ArrayWrite[1]的数据写入到DR2中 OLED_ShowHexNum(1,3,ArrayWrite[0],4); OLED_ShowHexNum(1,8,ArrayWrite[1],4); } ArrayRead[0] = BKP_ReadBackupRegister(BKP_DR1);//读取BKPDR1的值,放到ArrayRead[0]中 ArrayRead[1] = BKP_ReadBackupRegister(BKP_DR2);//读取BKPDR2的值,放到ArrayRead[1]中 OLED_ShowHexNum(2,3,ArrayRead[0],4); OLED_ShowHexNum(2,8,ArrayRead[1],4); }} |
实时时钟
main.c
123456789101112131415161718192021222324252627 | int main(void){ OLED_Init(); MyRTC_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) { MyRTC_ReadTime(); OLED_ShowNum(1,6,MyRTC_Time[0],4); OLED_ShowNum(1,11,MyRTC_Time[1],2); OLED_ShowNum(1,14,MyRTC_Time[2],2); OLED_ShowNum(2,6,MyRTC_Time[3],2); OLED_ShowNum(2,9,MyRTC_Time[4],2); OLED_ShowNum(2,12,MyRTC_Time[5],2); OLED_ShowNum(3,6,RTC_GetCounter(),10); OLED_ShowNum(4,6,RTC_GetDivider(),10); }} |
MyRTC.c
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 | uint16_t MyRTC_Time[] = {2023,1,1,23,59,55}; void MyRTC_SetTime(void){ time_t time_cnt; struct tm time_date; //把数组指定的时间填充到结构体中 time_date.tm_year = MyRTC_Time[0] - 1900; time_date.tm_mon = MyRTC_Time[1] - 1; time_date.tm_mday = MyRTC_Time[2]; time_date.tm_hour = MyRTC_Time[3]; time_date.tm_min = MyRTC_Time[4]; time_date.tm_sec = MyRTC_Time[5]; time_cnt = mktime(&time_date) - 8*60*60;//得到秒数,偏移8小时 RTC_SetCounter(time_cnt);//秒数写入到RTC的CNT中 RTC_WaitForLastTask();//等待写入时间完成} void MyRTC_Init(void){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//开启PWR时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//开启BKP时钟 PWR_BackupAccessCmd(ENABLE); if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)//判断DR1中的值是否为0xA5A5,用于判断是否完全断电 { //开启LSE时钟,并等待LSE时钟启动完成 RCC_LSEConfig(RCC_LSE_ON);//LSE振荡器打开 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);//获取标志位,LSE时钟启动完成 //选择RTCCLK时钟源 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RTCCLK时钟源选择LSE时钟 RCC_RTCCLKCmd(ENABLE);//使能RTCCLK时钟 //等待同步和等待上一次写入操作完成 RTC_WaitForSynchro();//等待同步 RTC_WaitForLastTask();//等待上一次操作完成 //配置预分频器 RTC_SetPrescaler(32768-1); RTC_WaitForLastTask();//等待写入预分频值完成 //RTC_SetCounter(1672588795);//设置初始时间 //RTC_WaitForLastTask();//等待写入时间完成 MyRTC_SetTime(); BKP_WriteBackupRegister(BKP_DR1,0xA5A5); } else { //等待同步和等待上一次写入操作完成 RTC_WaitForSynchro();//等待同步 RTC_WaitForLastTask();//等待上一次操作完成 }} void MyRTC_ReadTime(void){ time_t time_cnt; struct tm time_date; //得到秒数 time_cnt = RTC_GetCounter() + 8*60*60;//偏移8小时 time_date = *localtime(&time_cnt); MyRTC_Time[0] = time_date.tm_year + 1900; MyRTC_Time[1] = time_date.tm_mon + 1; MyRTC_Time[2] = time_date.tm_mday; MyRTC_Time[3] = time_date.tm_hour; MyRTC_Time[4] = time_date.tm_min; MyRTC_Time[5] = time_date.tm_sec; } |