马上又来放假了,继续再来写,关于RTC的驱动,这个可简单了.一来没103那个坑爹的,二来之前已经给板子加装过电池.
https://www.lijingquan.net/2015/09/01/add-vbat-for-f4-discovery/
首先要粗略说一下RTC的特性,他用电池供电时候,就可以工作,在主电源失效情况下都没什么压力,但是外部电池是给LSE供电,所以功耗敏感时候需要注意设计,RTC还能保持一些BKP寄存器的值不变,这个还是靠VBAT的电池啊.虽然只有那么几个寄存器,但也是很足够的了.另外RTC是靠32.768kHz进行分频,直到等于1Hz的.另外可以设置闹铃,定点起来工作.
首先初始化时候要把LSE打开,而LSE只要打开一次,只要你的电池还工作,然后设置分频.一般按照以下思路:
1)判断时钟打开情况.
2)进行相关设置或者直接跳过.
的程序应该是这样的的,切记初始化函数不能是RTC_Init()哦,因为...冲突,当然,你是C++,你可以实现重载是另一回事.
uint8_t IRTC_Init(void) { RTC_InitTypeDef RTC_InitStructure; uint16_t retry = 0X1FFF; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能PWR时钟 PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问 if(RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x5055) //是否第一次配置? { RCC_LSEConfig(RCC_LSE_ON);//LSE 开启 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待低速晶振就绪 { retry++; Delay(10); } if(retry == 0)return 1; //LSE 开启失败. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟 RCC_RTCCLKCmd(ENABLE); //使能RTC时钟 RTC_InitStructure.RTC_AsynchPrediv = 0x7F;//RTC异步分频系数(1~0X7F) RTC_InitStructure.RTC_SynchPrediv = 0xFF;//RTC同步分频系数(0~7FFF) RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;//RTC设置为,24小时格式 RTC_Init(&RTC_InitStructure); RTC_Set_Time(23, 59, 56, RTC_H12_AM); //设置时间 RTC_Set_Date(14, 5, 5, 1); //设置日期 RTC_WriteBackupRegister(RTC_BKP_DR0, 0x5055); //标记已经初始化过了 } return 0; }
只要把分频配置好,RTC就会自己一秒一秒的开始计时.当然,如果你的分频不是例子中的值,那可不是1秒哦,我们做实验时候,可以把这个值调整一下.另外F4闹钟设置也非常简单哦,只需要给RTC_AlarmTypeInitStructure填上合适的数值,就可以了,然后记得开中断,闹钟来了就中断了.大致如下:
EXTI_InitTypeDef EXTI_InitStructure; RTC_AlarmTypeDef RTC_AlarmTypeInitStructure; RTC_TimeTypeDef RTC_TimeTypeInitStructure; RTC_AlarmCmd(RTC_Alarm_A, DISABLE); //关闭闹钟A RTC_TimeTypeInitStructure.RTC_Hours = hour; //小时 RTC_TimeTypeInitStructure.RTC_Minutes = min; //分钟 RTC_TimeTypeInitStructure.RTC_Seconds = sec; //秒 RTC_TimeTypeInitStructure.RTC_H12 = RTC_H12_AM; RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDay = week; //星期 RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay; //按星期闹 RTC_AlarmTypeInitStructure.RTC_AlarmMask = RTC_AlarmMask_None; //精确匹配星期,时分秒 RTC_AlarmTypeInitStructure.RTC_AlarmTime = RTC_TimeTypeInitStructure; RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmTypeInitStructure); RTC_ClearITPendingBit(RTC_IT_ALRA);//清除RTC闹钟A的标志 EXTI_ClearITPendingBit(EXTI_Line17);//清除LINE17上的中断标志位 RTC_ITConfig(RTC_IT_ALRA, ENABLE); //开启闹钟A中断 RTC_AlarmCmd(RTC_Alarm_A, ENABLE); //开启闹钟A EXTI_InitStructure.EXTI_Line = EXTI_Line17;//LINE17 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE17 EXTI_Init(&EXTI_InitStructure);//配置 NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道 NVIC_Init(&NVIC_InitStructure);//配置
另外RTC的周期中断,相当于RTC_SetWakeUpCounter执行一下全OK了,所以也不介绍了.主要的,还是放个程序,一看就知道.
试验效果: