STM32F4DiscoveryRTC调试手记
完成功用:装备RTC完成计时功用,并经过唤醒中止输出当时时刻。
一、硬件改动
本次调试运用32768Hz晶振,而STM32F4Discovery上并未焊接该晶振,所以硬件需求作出几个改动:
1.
2013-8-20 17:05 上传
下载附件(19.52 KB)
焊接晶振X3 32768Hz(负载%&&&&&%为6pF)C16、C27 6pF
2.
因VBAT直接接到VDD上了,而RTC需求电池供电支撑,因此需求拆掉R26,并在VBAT那个焊盘接电池正极
硬件改动效果图:
二、所运用的库函数
在本次试验中,首要运用了stm32f4xx_pwr.c,stm32f4xx_rcc.c, stm32f4xx_rtc.c中的函数,下面临部分函数进行简略的介绍:
stm32f4xx_pwr.c:
PWR_BackupAccessCmd:经过位带完成设置PWR_CR[8] DBP,该位用于使能/失能RTC、RTC备份寄存器及备份SRAM的拜访。
stm32f4xx_rcc.c:
RCC_LSEConfig:完成对RCC_BDCR寄存器的设置,首要是对[2]LSEBYP和[0]LSEON进行设置。这儿用于发动32768Hz晶振。
RCC_RTCCLKConfig:完成对RCC_BDCR[9:8]RTCSEL设置,用于挑选RTC时钟的时钟源。一起,可能对RCC_CFGR[20:16]RTCPRE设置(运用HSE作为RTC时钟时设置)。
RCC_RTCCLKCmd:位带操作完成对RCC_BDCR[15]RTCEN设置,用于使能/失能RTC。
stm32f4xx_rtc.c:
首要先看三个结构体:
typedef struct
{
uint32_t RTC_HourFormat;
uint32_t RTC_AsynchPrediv;
uint32_t RTC_SynchPrediv;
}RTC_InitTypeDef;
此结构体用于RTC_Init,即RTC初始化。
其间,RTC_HourFormat影响RTC_CR[6] FMT:时钟格局,该位影响时钟的表达方式:AM/PM或24小时表达方式。
RTC_AsynchPrediv和RTC_SynchPrediv则影响RTC_PRER寄存器的值,
RTC_AsynchPrediv影响[22:16]PREDIV_A[6:0],该值决议ck_apre的频率。
ck_apre = RTCCLK/(PREDIV_A + 1)
RTC_SynchPrediv影响[14:0]PREDIV_S,该值决议ck_spre频率。
ck_spre = ck_apre/( PREDIV_S + 1)
因此处选用32768Hz晶振,为生成1Hz时钟,故运用:
RTC_InitStructure.RTC_SynchPrediv = 0xFF;
RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
typedef struct
{
uint8_t RTC_Hours;
uint8_t RTC_Minutes;
uint8_t RTC_Seconds;
uint8_t RTC_H12;
}RTC_TimeTypeDef;
typedef struct
{
uint8_t RTC_WeekDay;
uint8_t RTC_Month;
uint8_t RTC_Date;
uint8_t RTC_Year;
}RTC_DateTypeDef;
上述两个结构体用于保存时刻或日期,格局可认为BCD码或二进制数,留意年份RTC_Year的取值规模为0-99。
下面是RTC部分函数。
RTC_Init:RTC初始化
RTC_EnterInitMode:用于设置RTC_ISR(RTC初始化和状况寄存器)[7]INIT初始化形式,在初始化形式下,RTC_TR、RTC_CR、RTC_PRER均可修正。计时中止直至INIT复位。
RTC_ExitInitMode:复位RTC_ISR[7]INIT。
时刻装备及获取函数:
ErrorStatus RTC_SetTime(uint32_tRTC_Format, RTC_TimeTypeDef* RTC_TimeStruct); void RTC_GetTime(uint32_tRTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
ErrorStatus RTC_SetDate(uint32_tRTC_Format, RTC_DateTypeDef* RTC_DateStruct); void RTC_GetDate(uint32_tRTC_Format, RTC_DateTypeDef* RTC_DateStruct);
这几个函数完成对RTC_TR和RTC_DR的拜访取得当时时刻及日期。终究,存入这两个寄存器的值为BCD码。而这些函数第二个参数的结构体中所存入的值可认为BCD码,也可认为二进制数,其格局由第一个参数(RTC_Format_BIN/RTC_Format_BCD)指定。
唤醒中止相关函数:
RTC_WakeUpClockConfig:影响RTC_CR[2:0]WUCKSEL,确认唤醒时钟ck_wut的时钟源。
RTC_SetWakeUpCounter:设置RTC_WUTR[15:0]WUT,当WUTE=1时,WUTF标志位每隔(WUT+1)个ck_wut时钟周期置位。
RTC_WakeUpCmd:影响RTC_CR[10]WUTE唤醒时钟使能位。
备份寄存器:
在STM32F1中是在stm32f10x.bkp.c中完成,这儿由RTC完成了。
RTC_WriteBackupRegister、RTC_ReadBackupRegister完成对相应备份寄存器的读写。
中止相关:
RTC_ITConfig:影响RTC_CR[15]TSIE时刻戳中止使能、[14]WUTIE唤醒时钟中止使能、[13-12]ALRA(B)IE:闹铃A/B中止使能。
三、初始化流程及代码
初始化流程大致如下:
1) 使能时钟,装备RTC时钟及分频比,取得1Hz的ck_spre时钟。
2) 装备NVIC相关参数
3) 唤醒中止装备。因此处需求完成秒中止,故选用ck_spre时钟作为ck_wut时钟源,唤醒时钟计数器设置为0,则可完成秒中止。
static void RTC_Configuration(void)
{
RTC_InitTypeDefRTC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
RTC_InitStructure.RTC_HourFormat= RTC_HourFormat_24; //24 hour format
//32768/ (1 + 0x7F) = 32768 /128 = 256Hz,
//256/ (1 + 0xFF) = 1Hz, This is the calender frequecy~
RTC_InitStructure.RTC_SynchPrediv= 0xFF;
RTC_InitStructure.RTC_AsynchPrediv= 0x7F;
if(RTC_Init(&RTC_InitStructure) == ERROR)
printf(“RTCinit failed“);
else
printf(“RTCinit success”);
NVIC_Configuration();
RTC_WakeUpCmd(DISABLE); //important
//Configure the RTC WakeUp Clock source: CK_SPRE (1Hz)
RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
RTC_SetWakeUpCounter(0x0);
RTC_WakeUpCmd(ENABLE);
RTC_ClearITPendingBit(RTC_IT_WUT);
RTC_ITConfig(RTC_IT_WUT,ENABLE);
}
中止装备流程见RM009023.5节RTC interrupt
使能唤醒中止初始化序列:
1) 装备并使能EXTI Line22进入中止形式并挑选上升沿触发。
2) 在NVIC中装备RTC_WKUP_IRQ
3) 装备RTC来发生RTC唤醒时钟事情
static void NVIC_Configuration(void)
{
EXTI_InitTypeDefEXTI_InitStructure;
EXTI_ClearITPendingBit(EXTI_Line22);
EXTI_InitStructure.EXTI_Line= EXTI_Line22;
EXTI_InitStructure.EXTI_Mode= EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd= ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_Init(&NV%&&&&&%_InitStructure);
}