stm32移植millis()记录系统开机运行时间

时间:2021-09-15 16:43:29

首先初始化RTC和millis

MILLIS_Init();//初始化RTC为1Hz,同时初始化millis

MILLIS_Init() 函数的实现

void MILLIS_Init(void)
{
#ifdef USE_LSE
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable PWR and BKP clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR| RCC_APB1Periph_BKP, ENABLE); //使能电源时钟和备份区域时钟

/* Allow access to BKP Domain */
PWR_BackupAccessCmd(ENABLE); //取消备份区写保护

/* Reset Backup Domain */

if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET) //判断是否被唤醒
{
PWR_ClearFlag(PWR_FLAG_WU);// 清除唤醒标志
}else
{
BKP_DeInit(); //复位备份区域
}

/* Enable LSE */
RCC_LSEConfig(RCC_LSE_ON);
/* Wait till LSE is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{}

/* Select LSE as RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

/* Enable RTC Clock */
RCC_RTCCLKCmd(ENABLE);

/* Wait for RTC registers synchronization */
RTC_WaitForSynchro();

/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();

/* Enable the RTC ALARM */
RTC_ITConfig(RTC_IT_ALR,ENABLE);

/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();

/* Set RTC prescaler: set RTC period to 1sec */
RTC_SetPrescaler(32); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();


NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

#else
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
//中断时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);





//中断优先级配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//设置RTC闹钟中断
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

//闹钟中断接到第17线外部中断
EXTI_ClearITPendingBit(EXTI_Line17);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

//PWR_WakeUpPinCmd(DISABLE);

//电源管理部分时钟开启
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
//使能后备寄存器访问
PWR_BackupAccessCmd(ENABLE);


/* Reset Backup Domain */

if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET) //判断是否被唤醒
{
PWR_ClearFlag(PWR_FLAG_WU);// 清除唤醒标志
}else
{
BKP_DeInit(); //复位备份区域
}

//BKP_ClearFlag();
//BKP_DeInit();
//使能LSI
RCC_LSICmd(ENABLE);
//等待晶振启动
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{}
//设置时钟为内部晶振
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
RCC_RTCCLKCmd(ENABLE);
//等待RTC_CTL寄存器中的RSF位(寄存器同步标志)被硬件置1
RTC_WaitForSynchro();
RTC_WaitForLastTask();
//使能闹钟中断
RTC_ITConfig(RTC_IT_ALR, ENABLE);
RTC_WaitForLastTask();
//分频系数
RTC_SetPrescaler(32); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32+1) */
RTC_WaitForLastTask();
//初始计数值
RTC_SetCounter(0);
RTC_WaitForLastTask();
#endif
}

RTC相关中断的实现

void RTCAlarm_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_ALR) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line17);
RTC_ClearITPendingBit(RTC_IT_ALR);
}

return;
}
void RTC_IRQHandler()
{
if(RTC_GetITStatus(RTC_IT_ALR) == SET)
{
EXTI_ClearITPendingBit(EXTI_Line17); //闹钟中断接到第17线外部中断
RTC_ClearITPendingBit(RTC_IT_ALR);
RTC_WaitForLastTask();
}
else if(RTC_GetITStatus(RTC_IT_SEC) == SET)
{
RTC_ClearITPendingBit(RTC_IT_SEC);
}
}

返回系统运行时间函数

unsigned long millis()//返回系统从开机到现在运行的时间(ms)
{
return RTC_CURRENT_VAL;
}

#define RTC_CURRENT_VAL ((RTC->CNTH<<16)+RTC->CNTL) //返回RTC计数器里的,单位秒。