×
单片机 > 单片机程序设计 > 详情

STM32学习笔记——实时时钟RTC

发布时间:2020-05-21 发布时间:
|
 

//通过该例程,学会RTC的配置和读取计数值,数值格式的转换的方法 ,要想控制好的话,要多看资料,多看程序

 

 

 

 

 

 

#include "stm32f10x_lib.h"

 

 

 

vu32 TimeDisplay 0;

ErrorStatus HSEStartUpStatus;

u32 THH 0, TMM 0, TSS 0;

 

unsigned int jj 0;

unsigned int  LedNumVal ,LedNumVal1 0;    //变量定义

//此表为 LED 的字模, 共阴数码管 0-9  

unsigned char Disp_Tab[] {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};  //段码控制

 

//此表为8个数码管位选控制, 共阴数码管 1-8个  

unsigned char dispbit[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F};    //位选控制   查表的方法控制

 

unsigned int LedOut[10];    //变量定义

 

 

void RCC_Configuration(void);

void GPIO_Configuration(void);

void USART_Configuration(void);

void RTC_Configuration(void);

void NVIC_Configuration(void);

u32 Time_Regulate(void);

void Time_Adjust(void);

void Time_Show(void);

void Time_Display(u32 TimeVar);

void Delay(vu32 nCount);

 

 

 

int main(void)

{

#ifdef DEBUG

  debug();

#endif

 

  RCC_Configuration();   //系统时钟配置函数   

 

  NVIC_Configuration();  //NVIC配置函数

 

  GPIO_Configuration();   //配置GPIO

 

   //从指定的后备寄存器中读取数据,参数用来选择后备寄存器,可以是BKP_DR1~BKP_DR10 10个后备寄存器

  if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) //???为什么要检测0xA5A5

  {

    //配置RTC

    RTC_Configuration();

 

    

    Time_Adjust();

 

     BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); //向指定的后备寄存器中写入用户程序数据  这里是向BKP_DR1中写入0xA5A5

  }

   else

  {

    

    if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)  //检查指定的RCC标志位设置与否,这里检查POR/PDR复位

   // {

       

       RTC_WaitForSynchro();  //等待最近一次对RTC寄存器的写操作完成,也即等待RTC寄存器同步

 

    

    RTC_ITConfig(RTC_IT_SEC, ENABLE);  //使能或失能指定的RTC中断  第一个参数指定待配置的RTC中断源,可以是RTC_IT_SEC:秒中断

//RTC_IT_OW:溢出中断,RTC_IT_ALR:闹钟中断。  第二个参数可以是ENABLE 或DISABLE

 

    

    RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成

  }

 

#ifdef RTCClockOutput_Enable

 

    //使能或失能APB1外设时钟   具体说明详见《STM32函数说明》P208

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR RCC_APB1Periph_BKP, ENABLE);

 

  

  PWR_BackupAccessCmd(ENABLE);   //使能或失能RTC和后备寄存器访问

 

    //该函数使能或失能管脚的侵入检测功能   这里是失能

  BKP_TamperPinCmd(DISABLE); 

 

     //调用该函数前必须先失能管脚的侵入检测功能

  BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);  //选择在侵入检测管脚上输出的RTC时钟源  

  //参数指定RTC输出时钟源,可以是:BKP_RTCOutputSource_CalibClock: 侵入检测管脚上输出,其时钟频率为RTC时钟除以64

  //BKP_RTCOutputSource_None:侵入检测管脚上无RTC输出,BKP_RTCOutputSource_Alarm:侵入检测管脚上输出RTC闹钟脉冲

  //BKP_RTCOutputSource_Second:侵入检测管脚上输出RTC秒脉冲

#endif

 

  //清除复位标志

  RCC_ClearFlag();

 

 

 while (1)

    unsigned int ;

     

   // if (++jj >= 0x01ff)

   // LedNumVal1++ ;

   //    jj 0;

   //  }

      //得到时间并显示   RTC_GetCounter():获得RTC计数器的值  返回值是u32类型的RTC计数器的值

     Time_Display(RTC_GetCounter());

 

     LedOut[0]=Disp_Tab[THH0/10]; //时

     LedOut[1]=Disp_Tab[THH];

     LedOut[2]=~0XBF; //横线

     LedOut[3]=Disp_Tab[TMM0/10];  //分  

 LedOut[4]=Disp_Tab[TMM];     

     LedOut[5]=~0XBF;  //横线

     LedOut[6]=Disp_Tab[TSS0/10];  //十位  

     LedOut[7]=Disp_Tab[TSS];     //个位  

 

 for( i=0; i<8; i++) 

 {  

    //BSRR:端口位设置/复位寄存器,详细的GPIO寄存器结构体说明见《STM32函数说明》P120

    GPIOB->BSRR LedOut[i]<<8 0xFF00;   

        GPIOB->BRR (~(LedOut[i]<<8)) 0xFF00;  //BRR:端口位复位寄存器

         

    GPIOB->BSRR dispbit[i] 0x00FF;   //使用查表法进行位选  

        GPIOB->BRR (~dispbit[i]) 0x00FF;

       

        Delay(0x000ff);  //扫描间隔时间

 }

  //while 

}

 

 

void Delay(vu32 nCount)

{

  for(; nCount != 0; nCount--);

}

 

 

 

 

void RCC_Configuration(void)

{

  //复位RCC外部设备寄存器到默认值

  RCC_DeInit();

 

  //打开外部高速晶振

  RCC_HSEConfig(RCC_HSE_ON);

 

   //等待外部高速时钟准备好

  HSEStartUpStatus RCC_WaitForHSEStartUp();

 [page]

  if(HSEStartUpStatus == SUCCESS)   //外部高速时钟已经准别好

  {     

    //开启FLASH的预取功能

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

 

    //FLASH延迟2个周期

    FLASH_SetLatency(FLASH_Latency_2);

 

  //配置AHB(HCLK)时钟=SYSCLK

    RCC_HCLKConfig(RCC_SYSCLK_Div1);  

  

   //配置APB2(PCLK2)钟=AHB时钟

    RCC_PCLK2Config(RCC_HCLK_Div1); 

 

    //配置APB1(PCLK1)钟=AHB 1/2时钟

    RCC_PCLK1Config(RCC_HCLK_Div2);

 

     //配置PLL时钟 == 外部高速晶体时钟*9  PLLCLK 8MHz 72 MHz 

    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

 

    //使能PLL时钟

    RCC_PLLCmd(ENABLE);

 

   //等待PLL时钟就绪

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

    {

    }

 

  //配置系统时钟 PLL时钟

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

 

   //检查PLL时钟是否作为系统时钟

    while(RCC_GetSYSCLKSource() != 0x08)

    {

    }

  }

 

    //启动GPIO

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA RCC_APB2Periph_GPIOB ,ENABLE);

 

    //启动AFIO

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

                         

}

 

 

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;   //定义NVIC配置的结构体变量

 

#ifdef  VECT_TAB_RAM

  

  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else  

  

  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

#endif

 

  

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

 

  

  NVIC_InitStructure.NVIC_IRQChannel RTC_IRQChannel;   //指定是RTC全局中断

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;

  NVIC_Init(&NVIC_InitStructure);

 

 

}

 

 

void GPIO_Configuration(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;    //定义配置GPIO的结构体变量

 

    GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);  //改变指定管脚的映射

//第一个参数选择重映射的管脚  用以选择用作事件输出的GPIO端口  在这里是SWJ完全失能 详见《STM32函数说明》P132

//第二个参数指定管脚重映射的新状态,可以是:ENABLE或DISABLE

 

    GPIO_InitStructure.GPIO_Pin GPIO_Pin_All ; //选择所有管脚

    GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //推挽输出模式

    GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //引脚频率50M

    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA

    GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB

  

//????

    GPIO_InitStructure.GPIO_Pin GPIO_Pin_6 GPIO_Pin_7 ;

    GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

 

}

 

 

void RTC_Configuration(void)

  //启用PWR和BKP的时钟(from APB1)

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR RCC_APB1Periph_BKP, ENABLE);

 

    //后备域解锁

  PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问

 

 //备份寄存器模块复位

  BKP_DeInit();    //将BKP的全部寄存器重设为缺省值

 

  

  RCC_LSEConfig(RCC_LSE_ON); //设置外部低速晶振(LSE)32.768K  参数指定LSE的状态,可以是:RCC_LSE_ON:LSE晶振ON

  //RCC_LSE_ON:LSE晶振OFF,  RCC_LSE_Bypass:LSE晶振被外部时钟旁路

 

  //等待稳定

  while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)

  {}

  //RTC时钟源配置成LSE(外部32.768K)

  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);  //设置RTC时钟,参数指定RTC时钟,可以是:RCC_RTCCLKSource_LSE:选择LSE作为RTC时钟

  //RCC_RTCCLKSource_LSI:选择LSI作为RTC时钟,RCC_RTCCLKSource_HSE_Div128:选择HSE时钟128分频作为RTC时钟

 

  //RTC开启

  RCC_RTCCLKCmd(ENABLE);

 

  //开启后需要等待APB1时钟与RTC时钟同步,才能读写寄存器

  RTC_WaitForSynchro();  

 

  //每一次读写寄存器前,要确定上一个操作已经结束

  RTC_WaitForLastTask();   //等待最近一次对RTC寄存器的写操作完成

  

    //使能秒中断

  RTC_ITConfig(RTC_IT_SEC, ENABLE);   

 

  //读写寄存器前,要确定上一个操作已经结束

  RTC_WaitForLastTask();

 

  //设置RTC分频器,使RTC时钟为1Hz

  //RTC period RTCCLK/RTC_PR (32.768 KHz)/(32767+1)

  RTC_SetPrescaler(32767); 

 

  //等待寄存器写入完成

  RTC_WaitForLastTask();

 

    //等待写入完成

  RTC_WaitForLastTask();

 

}

 

 

void Time_Adjust(void)  //校准时间函数

  

  RTC_WaitForLastTask();

  

  RTC_SetCounter(12*3600 2*60 0);   //设置RTC计数器的值  参数是新的RTC计数器的值

  //在使用本函数前必须先调用函数RTC_WaitForLastTask(),等待标志位RTOFF被设置

 

  

  RTC_WaitForLastTask();

}

 

 

void Time_Display(u32 TimeVar)   //把RTC计数器的值转化为时,分,秒进制

{

 

  

  THH TimeVar 3600;

  

  TMM (TimeVar 3600) 60;

  

  TSS (TimeVar 3600) 60;

 

 }

 

 

 

void assert_failed(u8* file, u32 line)

{

  

 

  

  while (1)

  {}

}

 

 

 

 

 

 

 

中断服务程序在stm32f10x_it.c文件中,其中RTC中断处理函数如下:

 

 

void RTC_IRQHandler(void) //RTC的中断服务程序

 

  GPIO_WriteBit(GPIOB, GPIO_Pin_7, (BitAction)(1 GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_7))); //B7口取反

  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)

  {

    

    RTC_ClearITPendingBit(RTC_IT_SEC); //清除RTC的中断待处理位

 

    

    GPIO_WriteBit(GPIOB, GPIO_Pin_7, (BitAction)(1 GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_7)));

 

    

    TimeDisplay 1;

 

    

    RTC_WaitForLastTask();

    

    if (RTC_GetCounter() == 0x00015180)

    {

      RTC_SetCounter(0x0);

      

      RTC_WaitForLastTask();

    }

  }

}

关键字:STM32  实时时钟  RTC 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于AT91M42800A的LED显示系统设计