STM32F1xx官方资料:

《STM32中文参考手册V10》-第16章  实时时钟(RTC)

RTC实时时钟

RTC实时时钟简介

实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。 RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒后,RTC的设置和时间维持不变。 

BKP备份寄存器简介

备份寄存器是42个16位的寄存器,可用来存储84个字节的用户应用程序数据。他们处在备份域里,当Vdd电源被切断,他们仍然由Vbat维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位。

此外,BKP控制寄存器用来管理侵入检测和RTC校准功能。在本文中,使用备份寄存器来存储RTC的相关信息(标记时钟是否已经经过了配置)。

复位后,对备份寄存器和RTC的访问被禁止,并且备份域被保护以防止可能存在的意外的写操作。执行以下操作可以使能对备份寄存器和RTC的访问。

  • 通过设置寄存器RCC_APB1ENR的PWREN和BKPEN位来打开电源和后备接口的时钟;
  • 电源控制寄存器(PWR_CR)的DBP位来使能对后备寄存器和RTC的访问。

RTC实时时钟的主要特征

  • 可编程的预分频系数:分频系数最高为220;
  • 32位的可编程计数器,可用于较长时间段的测量;
  • 2个分离的时钟:用于APB1接口的PCLK1和RTC时钟(RTC时钟的频率必须小于PCLK1时钟频率的四分之一以上);
  • 可以选择以下三种RTC的时钟源:
  1. HSE时钟除以128;
  2. LSE振荡器时钟;
  3. LSI振荡器时钟;
  • 2个独立的复位类型:
  1. APB1接口由系统复位;
  2. RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位;
  • 3个专门的可屏蔽中断:
  1. 闹钟中断,用来产生一个软件可编程的闹钟中断;
  2. 秒中断,用来产生一个可编程的周期性中断信号(最长可达1秒);
  3. 溢出中断,指示内部可编程计数器溢出并回转为0的状态。

RTC工作原理

RTC工作原理框图

由工作框图可以看出,RTC由两部分组成:

  • APB1接口:用来和APB1总线相连。通过APB1接口可以访问RTC的相关寄存器(预分频值,计数器值,闹钟值)
  • RTC核心:由一组可编程计数器组成,分两个主要模块:
  1. RTC预分频模块,它可以编程产生最长1秒的RTC时间基TR_CLK。如果设置了秒中断允许位,可以产生秒中断;
  2. 32位的可编程计数器,可被初始化为当前时间。系统时间按TR_CLK周期累加并与存储在RTC_ALR寄存器中的可编程时间相比,当匹配时候如果设置了闹钟中断允许位,可以产生闹钟中断;如果溢出,可以产生溢出中断。

复位过程

  • 除了RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器外,所有的系统寄存器都由系统复位或电源复位进行异步复位。
  • RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器仅能通过备份域复位信号复位。

读RTC寄存器

RTC内核完全独立于APB1接口,软件通过APB1接口对RTC相关寄存器访问。但是相关寄存器只在RTC APB1时钟进行重新同步的RTC时钟的上升沿被更新。所以软件必须先等待寄存器同步标志位(RTC_CRL的RSF位)被硬件置1才读。

这意味着,如果APB1接口曾经被关闭,而读操作又是在刚刚重新开启APB1之后,则在第一次的内部寄存器更新之前,从APB1上读出的RTC寄存器数值可能被破坏了(通常读到0)。简单地讲,在APB1接口被禁止(复位、无时钟或断电)的情况下,RTC核仍保持运行状态。接着,重新打开APB1接口,此时必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1,同步之后,读RTC寄存器的值才不会有误。

因此,若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器的RSF位被硬件置1。

写RTC寄存器

必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器。

另外,对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是1时,才可以写入RTC寄存器。

RTC相关配置寄存器

RTC控制寄存器高位(RTC_CRH)

作用:配置3个专门的可屏蔽中断(溢出中断、闹钟中断、秒中断)使能。

RTC控制寄存器低位(RTC_CRL)

作用:RTC操作是否完成判断、配置模式判断、寄存器同步判断、3个中断的标志位。

这个寄存器尤其重要(尤其是位5、位4、位3):

  • 写任何寄存器之前,必须判断上一次写操作已经结束,也就是判断RTOFF位是否置1;
  • 写CNT、ALR、PRL寄存器,必须先配置CNF位进入配置模式,修改完之后,设置CNF位为0退出配置模式;
  • 读任何寄存器,必须先判断RSF位,确定已经同步。

RTC预分频装载寄存器(RTC_PRLH、RTC_PRLL)

作用:配置RTC预分频装载值,这个值是20bit长度。

根据这个寄存器的值可以确定,TR_CLK和RTCCLK之间的关系公式:

fTR_CLK=fRTCCLK/(PRL+1)

如果输入时钟频率是32.768kHz(fRTCCLK,也就是以LSE作为时钟源),这个寄存器中写入7FFFh(32767)可获得周期为1秒钟的信号。

RTC预分频器余数寄存器(RTC_DIVH、RTC_DIVL)

作用:获得预分频计数器的当前值,也就是从RTC预分频装载寄存器倒数到0之间的一个值(以RTCCLK为时钟)。

RTC计数器寄存器(RTC_CNTH、RTC_CNTL)

作用:存放计数器内的计数值(以TR_CLK为时钟)。

注意:由于RTC预分频器余数寄存器以RTCCLK为时钟,而RTC计数器寄存器以TR_CLK为时钟,而RTCCLK的时钟通常远远大于TR_CLK,所以利用RTC预分频器余数寄存器可以获得更准确的控制。比如,RTC计数器寄存器存储当前时间,精确到秒;但是利用由于RTC预分频器余数寄存器,可以在RTC预分频装载寄存器倒数到0的平均数处停下,从而达到0.5秒的更精确时间。

RTC闹钟寄存器(RTC_ALRH、RTC_ALRL)

作用:当RTC计数器寄存器的值与RTC闹钟寄存器的值相等的时候,触发一个闹钟事件,产生一个闹钟中断。

读写RTC寄存器的步骤

读RTC寄存器

  • 查询RSF位(寄存器同步标志位),直至RSF的值变成1;
  • 对一个或多个RTC寄存器进行读操作。

写RTC寄存器

  • 查询RTOFF位(RTC操作关闭位),直到RTOFF的值变为1 ;
  • 置CNF位(配置标志位)值为1,进入配置模式(仅仅PRL、CNT、ALR寄存器);
  • 对一个RTC寄存器进行写操作;
  • 清除CNF标志位,退出配置模式(仅仅PRL、CNT、ALR寄存器);
  • 查询RTOFF,直至RTOFF位变为1以确认写操作已经完成。

也就是说:对寄存器的写操作,无论是设置中断使能等等,每操作一次就需要查询一次RTOFF位。而对于PRL、CNT、ALR寄存器,还需要进入配置模式,这个就没有必要每操作一次就退出配置模式,可以等都配置完成了再退出。

RTC相关配置库函数

  • 2个时钟源操作函数
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);
void RCC_RTCCLKCmd(FunctionalState NewState);

作用:确定RTC的时钟源,使能RTC时钟(通常选用LSE时钟源)。

  • 3个参数配置函数
void RTC_SetCounter(uint32_t CounterValue);
void RTC_SetPrescaler(uint32_t PrescalerValue);
void RTC_SetAlarm(uint32_t AlarmValue);

作用:配置预分频装载寄存器的值、计数器的值、闹钟配置。

  • 1个中断配置函数
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);

作用:配置RTC中断的选择和使能。

  • 2个配置模式函数
void RTC_EnterConfigMode(void);
void RTC_ExitConfigMode(void);

作用:前者允许RTC配置,后者退出配置模式。

  • 2个同步函数
void RTC_WaitForLastTask(void);
void RTC_WaitForSynchro(void);

作用:前者等待上次操作完成(CRL寄存器的RTOFF位),后者等待时钟同步(CRL寄存器的RSF位)。

  • 4个状态位函数
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);

作用:前两者获取(或清除)状态标志位,后两者为获取(或清除)中断状态标志位。

  • 其他的相关函数
void PWR_BackupAccessCmd(FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
void RCC_LSEConfig(uint8_t RCC_LSE);

作用:第一个函数使能BKP后备区域访问使能,第二个函数使能PWR和BKP时钟,第三个函数开启LSE时钟(这里为什么使用这几个函数?是在上文:BKP备份寄存器简介中讲到)。

void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);
uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);

作用:上面的PWR_BackupAccessCmd()函数使能BKP后备区域使能之后,就可以通过这两个函数来读BKP的寄存器,写BKP的寄存器。

RTC一般步骤

  • 使能PWR和BKP时钟。调用函数:RCC_APB1PeriphClockCmd();
  • 使能后备寄存器访问。调用函数:PWR_BackupAccessCmd();
  • 配置RTC时钟源,使能RTC时钟。调用函数:RCC_RTCCLKConfig();RCC_RTCCLKCmd();
  • 如果使用LSE,要打开LSE:RCC_LSEConfig(RCC_LSE_ON);
  • 设置RTC预分频系数。调用函数:RTC_SetPrescaler();
  • 设置时间。调用函数:RTC_SetCounter();
  • 开启相关中断(如果需要)。调用函数:RTC_ITConfig();
  • 编写中断服务函数。调用函数:RTC_IRQHandler();
  • 部分操作要等待写操作完成和同步。调用函数:RTC_WaitForLastTask();RTC_WaitForSynchro()。

下面按照这个一般步骤来进行一个简单的RTC程序:

//时间结构体
typedef struct
{vu8 hour;vu8 min;vu8 sec;          //公历日月年周vu16 w_year;vu8  w_month;vu8  w_date;vu8  week;
}_calendar_obj; 
_calendar_obj calendar;//时钟结构体 static void RTC_NVIC_Config(void)
{   NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;     //RTC全局中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级1位,从优先级3位NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //先占优先级0位,从优先级4位NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        //使能该通道中断NVIC_Init(&NVIC_InitStructure);        //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
//BKP->DR1用于保存是否第一次配置的设置
//返回0:正常
//其他:错误代码u8 RTC_Init(void)
{//检查是不是第一次配置时钟u8 temp=0;RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);  //使能PWR和BKP外设时钟   PWR_BackupAccessCmd(ENABLE);  //使能后备寄存器访问  if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050)        //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎{                BKP_DeInit();   //复位备份区域    RCC_LSEConfig(RCC_LSE_ON);  //设置外部低速晶振(LSE),使用外设低速晶振while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250)  //检查指定的RCC标志位设置与否,等待低速晶振就绪{temp++;delay_ms(10);}if(temp>=250)return 1;//初始化时钟失败,晶振有问题     RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);     //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟    RCC_RTCCLKCmd(ENABLE);    //使能RTC时钟  RTC_WaitForLastTask();   //等待最近一次对RTC寄存器的写操作完成RTC_WaitForSynchro();      //等待RTC寄存器同步  RTC_ITConfig(RTC_IT_SEC, ENABLE);     //使能RTC秒中断RTC_WaitForLastTask();    //等待最近一次对RTC寄存器的写操作完成RTC_EnterConfigMode();/// 允许配置 RTC_SetPrescaler(32767); //设置RTC预分频的值RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成RTC_Set(2015,1,14,17,42,55);  //设置时间   RTC_ExitConfigMode(); //退出配置模式  BKP_WriteBackupRegister(BKP_DR1, 0X5050);   //向指定的后备寄存器中写入用户程序数据}else//系统继续计时{RTC_WaitForLastTask();    //等待最近一次对RTC寄存器的写操作完成RTC_ITConfig(RTC_IT_SEC, ENABLE);  //使能RTC秒中断RTC_WaitForLastTask();    //等待最近一次对RTC寄存器的写操作完成}RTC_NVIC_Config();//RCT中断分组设置                              RTC_Get();//更新时间   return 0; //ok}
//RTC时钟中断
//每秒触发一次
//extern u16 tcnt;
void RTC_IRQHandler(void)
{        if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断{                          RTC_Get();//更新时间   }if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断{RTC_ClearITPendingBit(RTC_IT_ALR);       //清闹钟中断     RTC_Get();              //更新时间   printf("Alarm Time:%d-%d-%d %d:%d:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);//输出闹铃时间   }                                                RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);       //清闹钟中断RTC_WaitForLastTask();
}
//判断是否是闰年函数
//月份   1  2  3  4  5  6  7  8  9  10 11 12
//闰年   31 29 31 30 31 30 31 31 30 31 30 31
//非闰年 31 28 31 30 31 30 31 31 30 31 30 31
//输入:年份
//输出:该年份是不是闰年.1,是.0,不是
u8 Is_Leap_Year(u16 year)
{             if(year%4==0) //必须能被4整除{ if(year%100==0) { if(year%400==0)return 1;//如果以00结尾,还要能被400整除     else return 0;   }else return 1;   }else return 0;
}
//设置时钟
//把输入的时钟转换为秒钟
//以1970年1月1日为基准
//1970~2099年为合法年份
//返回值:0,成功;其他:错误代码.
//月份数据表
u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表
//平年的月份日期表
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{u16 t;u32 seccount=0;if(syear<1970||syear>2099)return 1;       for(t=1970;t<syear;t++)    //把所有年份的秒钟相加{if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数else seccount+=31536000;           //平年的秒钟数}smon-=1;for(t=0;t<smon;t++)      //把前面月份的秒钟数相加{seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数     }seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加 seccount+=(u32)hour*3600;//小时秒钟数seccount+=(u32)min*60;     //分钟秒钟数seccount+=sec;//最后的秒钟加上去RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);  //使能PWR和BKP外设时钟  PWR_BackupAccessCmd(ENABLE);   //使能RTC和后备寄存器访问 RTC_SetCounter(seccount);   //设置RTC计数器的值RTC_WaitForLastTask();  //等待最近一次对RTC寄存器的写操作完成   return 0;
}//初始化闹钟
//以1970年1月1日为基准
//1970~2099年为合法年份
//syear,smon,sday,hour,min,sec:闹钟的年月日时分秒
//返回值:0,成功;其他:错误代码.
u8 RTC_Alarm_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{u16 t;u32 seccount=0;if(syear<1970||syear>2099)return 1;       for(t=1970;t<syear;t++)    //把所有年份的秒钟相加{if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数else seccount+=31536000;           //平年的秒钟数}smon-=1;for(t=0;t<smon;t++)      //把前面月份的秒钟数相加{seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数     }seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加 seccount+=(u32)hour*3600;//小时秒钟数seccount+=(u32)min*60;     //分钟秒钟数seccount+=sec;//最后的秒钟加上去              //设置时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);  //使能PWR和BKP外设时钟   PWR_BackupAccessCmd(ENABLE);  //使能后备寄存器访问  //上面三步是必须的!RTC_SetAlarm(seccount);RTC_WaitForLastTask();   //等待最近一次对RTC寄存器的写操作完成   return 0;
}//得到当前的时间
//返回值:0,成功;其他:错误代码.
u8 RTC_Get(void)
{static u16 daycnt=0;u32 timecount=0; u32 temp=0;u16 temp1=0;     timecount=RTC_GetCounter();   temp=timecount/86400;   //得到天数(秒钟数对应的)if(daycnt!=temp)//超过一天了{     daycnt=temp;temp1=1970; //从1970年开始while(temp>=365){              if(Is_Leap_Year(temp1))//是闰年{if(temp>=366)temp-=366;//闰年的秒钟数else {temp1++;break;}  }else temp-=365;      //平年 temp1++;  }   calendar.w_year=temp1;//得到年份temp1=0;while(temp>=28)//超过了一个月{if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份{if(temp>=29)temp-=29;//闰年的秒钟数else break; }else {if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年else break;}temp1++;  }calendar.w_month=temp1+1; //得到月份calendar.w_date=temp+1;     //得到日期 }temp=timecount%86400;          //得到秒钟数        calendar.hour=temp/3600;        //小时calendar.min=(temp%3600)/60;   //分钟    calendar.sec=(temp%3600)%60;   //秒钟calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期   return 0;
}
//获得现在是星期几
//功能描述:输入公历日期得到星期(只允许1901-2099年)
//输入参数:公历年月日
//返回值:星期号
u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{   u16 temp2;u8 yearH,yearL;yearH=year/100;   yearL=year%100; // 如果为21世纪,年份数加100  if (yearH>19)yearL+=100;// 所过闰年数只算1900年之后的  temp2=yearL+yearL/4;temp2=temp2%7; temp2=temp2+day+table_week[month-1];if (yearL%4==0&&month<3)temp2--;return(temp2%7);
}
 int main(void){  u8 t=0;   delay_init();            //延时函数初始化    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级uart_init(115200);     //串口初始化为115200LED_Init();                //LED端口初始化LCD_Init();              usmart_dev.init(SystemCoreClock/1000000);   //初始化USMART RTC_Init();             //RTC初始化POINT_COLOR=RED;//设置字体为红色 LCD_ShowString(60,50,200,16,16,"WarShip STM32");   LCD_ShowString(60,70,200,16,16,"RTC TEST");   LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(60,110,200,16,16,"2015/1/14");      //显示时间POINT_COLOR=BLUE;//设置字体为蓝色LCD_ShowString(60,130,200,16,16,"    -  -  ");      LCD_ShowString(60,162,200,16,16,"  :  :  ");           while(1){                                   if(t!=calendar.sec){t=calendar.sec;LCD_ShowNum(60,130,calendar.w_year,4,16);                                    LCD_ShowNum(100,130,calendar.w_month,2,16);                                     LCD_ShowNum(124,130,calendar.w_date,2,16);     switch(calendar.week){case 0:LCD_ShowString(60,148,200,16,16,"Sunday   ");break;case 1:LCD_ShowString(60,148,200,16,16,"Monday   ");break;case 2:LCD_ShowString(60,148,200,16,16,"Tuesday  ");break;case 3:LCD_ShowString(60,148,200,16,16,"Wednesday");break;case 4:LCD_ShowString(60,148,200,16,16,"Thursday ");break;case 5:LCD_ShowString(60,148,200,16,16,"Friday   ");break;case 6:LCD_ShowString(60,148,200,16,16,"Saturday ");break;  }LCD_ShowNum(60,162,calendar.hour,2,16);                                     LCD_ShowNum(84,162,calendar.min,2,16);                                      LCD_ShowNum(108,162,calendar.sec,2,16);LED0=!LED0;}  delay_ms(10);                                 };  }

STM32控制程序分析

RTC_Init()函数:RTC初始化函数。

按照之前的RTC一般步骤初始化RTC函数,这里需要注意的是,为了区分是否是第一次执行RTC_Init()函数,这里使用了一个flag(向BKP_DR1寄存器写入0x5050,当然写入其他的数字也都是可以的)。

if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050)      //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎{                //第一次执行RTC_InitBKP_WriteBackupRegister(BKP_DR1, 0X5050);    //向指定的后备寄存器中写入用户程序数据}else//系统继续计时{//不是第一次执行RTC_Init}

为什么要区分是否第一次执行RTC_Init呢?因为如果由于断电等因素,程序中断,但是RTC时钟却还是在执行中;等恢复供电,重新启动程序,这个时候就不需要再对RTC时钟进行初始化了。

同时,设置外部低速晶振(LSE),使用外设低速晶振。需要检查指定的RCC标志位设置与否,等待低速晶振就绪。

这里时间的设置是:距离1970年1月1日0点0分0秒的时间距离。其中,RTC_Get()、RTC_Set()等函数的内容涉及到时间距离转换的各种算法,就不在本文的讨论范围了。

【STM32】RTC实时时钟概述、寄存器、库函数(RTC一般步骤)相关推荐

  1. 嵌入式--RTC实时时钟原理及相关库函数功能

    一.RTC实时时钟原理 1.RTC实时时钟是一个独立的定时器,可以提供日期时间或者闹钟的功能.其核心是通过32位可编程计数器RTC_CNT计数来进行时间配置. 2.图1中RTCCLK为RTC时钟源,其 ...

  2. RTC实时时钟(学习笔记)

    RTC实时时钟特征与原理 RTC(Real Time Clock):实时时钟. RTC是个独立的定时器.RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能.修改计数器的值可 ...

  3. 【正点原子FPGA连载】第三十一章RTC实时时钟数码管显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

    1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码+手册+视频下载地址:ht ...

  4. 【正点原子FPGA连载】 第二十四章 RTC实时时钟LCD显示实验-摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  5. STM32——RTC实时时钟原理+BKP寄存器原理

    一.RTC实时时钟特征与原理 1.RTC(Real Time Clock):实时时钟 2.RTC是个独立的BCD定时器/计数器.RTC提供一个日历时钟,两个可编程闹钟中断,以及一个具有中断功能的周期性 ...

  6. STM32 RTC实时时钟

    我用的是STM32库函数:两个知识点:       一.RTC时钟框图分析(重要)       二.时间是怎样显示出来的(简析) 一.RTC时钟框图分析(重要) 先熟悉一下几个知识点:       1 ...

  7. STM32之RTC实时时钟

    RTC实时时钟简介: STM32的RTC外设,实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断).但是从掉电还能继续运 ...

  8. RTC实时时钟(STM32)

    Cortex-M4-实时时钟 实时时钟概述 实时时钟介绍 英文缩写:RTC.显示年.月.日.时.分.秒.星期,自动计算闰年,能够区分每个月的天数. RTC特点:能从RTC获取到具体的日期时间,断掉后再 ...

  9. 【正点原子STM32连载】 第二十七章 RTC实时时钟实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

最新文章

  1. 关于Java中的迭代器
  2. 翻转单词顺序和左旋转字符串
  3. linux每天一小步---sed命令详解
  4. audino python_用 Python 实现 PowerDesigner 数据模型文件的处理
  5. 推导基姆拉尔森公式根据日期计算星期
  6. python_open3d_Error: The DISPLAY environment variable is missing
  7. Go语言之 下载安装及第一个代码
  8. php设置 url长度,URL长度有限制吗?_PHP教程
  9. 如何使用浏览器网络监视工具进行黑客攻击
  10. 什么是GRE词汇红宝书?
  11. python语言在ansys的应用_Python语言在ANSYS的应用10讲-掌握SCDM脚本封装及ACT向导开发...
  12. java链接打印机打印文件
  13. 智慧经营误区为何很多人还在执迷不悟?
  14. 双线macd指标参数最佳设置_一文讲透双线MACD指标及其实战运用
  15. 分布式理论(五)—— 一致性算法 Paxos
  16. tensorflow的安装和求解泊松方程
  17. C++技术——构造法
  18. D. Nastia Plays with a Tree(树形dp)
  19. Windows Server 2008 域操作(创建域、加入域、创建普通用户、组策略管理设置)
  20. 迈瑞BC5800出图

热门文章

  1. 简单移位密码——凯撒加密、解密算法
  2. Linux从入门到放弃 docker
  3. 颜色特征怎么在kcf算法中得出高斯响应矩阵的代码_剖析KCF
  4. 使用FreeType实现矢量字体的粗体、斜体、描边、阴影效果
  5. matlab与单片机联合开发【一】
  6. 高考数学复习-立体几何知识点总结及复习资料
  7. 电脑运行java程序很卡_我的世界卡运行不流畅解决办法
  8. 启发式算法,元启发式算法,超启发式算法
  9. 基于FMC 接口的Xilinx FPGA XC7K325T PCIeX8 接口卡
  10. C语言snprintf()函数用法