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

发布者:幸福之路最新更新时间:2015-08-14 来源: eefocus关键字:STM32  实时时钟  RTC 手机看文章 扫描二维码
随时随地手机看文章
 

//通过该例程,学会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 引用地址:STM32学习笔记——实时时钟RTC

上一篇:STM32学习笔记——测试闪灯程序
下一篇:ucos-ii学习笔记——首个多任务程序的创建

推荐阅读最新更新时间:2024-03-16 14:28

STM32 RTC问题
STM32的RTC用纽扣电池供电,本来考虑将电池正极接到一个AD端口,采集电压值,但发现电池很快消耗殆尽,测量电流得到电流竟然高达20mA,而且单片机是工作的,还能驱动外围电路。 下图是设计的电路图: 下面是出现这种问题的原因:I/O接二极管到VCC。 RTC
[单片机]
<font color='red'>STM32</font> <font color='red'>RTC</font>问题
如何优雅地解决STM32的Flash写保护的问题
本文介绍了如何解决 STM32 芯片 Flash 写保护导致无法下载程序,无法在线调试的问题;如果您遇到相同的问题,希望本文可以带来一些帮助; 1 FLASH 的写保护 如果对 Flash 设置了写保护,那就无法对 Flash 进行编程和擦除。 在开发 STM32 的时候,如果出现这种情况,通常仿真器都支持对 Flash 进行解锁,像 jlink,stlink 等仿真器都支持这个功能。 2 错误提示 在使用 MDK 进行调试的时候,出现报错 ==Flash Timeout.Reset Target and try it again==,具体如下图所示; 折腾了一番之后,并没有解决问题,因为使用的仿真器是 stlink,因此
[单片机]
STM32的内存地址映射与IAP下载
stm32的flash地址起始于0x08000000,结束地址是0x080000000加上芯片实际的flash大小,不同的芯片flash大小不同。RAM起始地址上0x200000000,结束地址是0x20000000加上芯片的RAM大小。STM32将外设等都映射为地址的形式,对地址的操作就是多外设的操作。 stm32的外设地址从0x40000000开始,可以看到在库文件中,是通过基于0x40000000地址的偏移量来操作寄存器以及外设的。 一般情况下,程序文件从0x08000000地址写入,这是STM32开始执行的地方,0x08000004是stm32的中断向量表起始地址。 在使用keil编程的过程中,其编程地址的设置一般是这样
[单片机]
<font color='red'>STM32</font>的内存地址映射与IAP下载
STM32学习笔记之绪论
学习STM32也有些日子了。作为初学者,从最初的一无所知,到现在略知皮毛之皮毛,感觉着实不容易。 下面把自己的体会以及自认为初学者不易掌握的要点和大家分享一下,有错误的地方,欢迎大家指正。 一、关于学习方法 初学STM32给我的一个感觉就是,概念繁多而且很多都可以继续深究下去, 教程对此又不可能都很详细的论述,但于我来说如鱼鲠喉实在不爽。 因为我喜欢刨根问底,网络资料又实在繁杂,如此又耗费精力,又打击学习积极性。 终于有一天,我转变了心态,如果STM32犹如枝繁叶茂的大树(整个嵌入式体系亦如此),我要做的不是连每一个叶子都明了,而是暂时只要知晓其主干及一些必要的干支即可。其他的枝叶等有时间再去深究,而很多脉络随
[单片机]
<font color='red'>STM32</font>学习笔记之绪论
沙场点兵STM32微处理器全系列成员
众所周知,STM32系列32位Flash微控制器在电子行业中不管是以前还是现在都有着无可替代、无与伦比的地位。其基于ARM Cortex™‑M处理器,旨在为MCU用户提供新的开发自由度,集高性能、实时功能、数字信号处理、低功耗与低电压操作等特性于一身,同时还保持了集成度高和易于开发的特点,最重要的是,性价比高、价格便宜。 无可比拟且品种齐全的STM32产品基于行业标准内核,提供了大量工具和软件选项,使该系列产品成为小型项目和完整平台的理想选择。下面我们”沙场点兵”STM32系列中全系列成员,捕捉精髓,学习技术,创造可能…… NO.1:STM32 F0入门级Cortex™-M0 MCU 基于ARM® Cortex-
[单片机]
基于STM32单片机对HCSR04超声波的控制
注意:定义GPIOB2为超声输出;GPIOB10为输入,定时器用tim2 #include “HCSR04.h” #include “delay.h” #include “sys.h” int overcount; float length=0; void HCSR04_init() { GPIO_InitTypeDef GPIO_InitStructure; TIM_TImeBaseInitTypeDef TIM_TImeBaseInitStructer; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , EN
[单片机]
基于<font color='red'>STM32</font>单片机对HCSR04超声波的控制
智能小车运行及测速原理
光电码盘测速原理 如何求解小车速度参数(大小与方向)? 测量速度方向的方法 根据A、B两相脉冲的超前滞后关系确定电机旋转方向: 假定A相超前于B相时,为电机正方向;则当A相滞后于B相,当前电机为反向旋转。 普通测量速度大小的方法 单位时间内采集的脉冲数就是转速大小的表征值,可以根据它转换为各种单位下的转速大小。 四倍频测量速度的大小 下面我们说一下编码器倍频的原理。为了提高大家下面学习的兴趣,我们先明确,这是一项实用的技术,可以真正地把编码器的精度提升 4 倍。作用可类比 于单反相机的光学变焦,而并非牺牲清晰度来放大图像的数码变焦。OK,先看看下面编码器输出的波形图。 这里,我们是通过软件的方法实现四倍频。首先
[单片机]
智能小车运行及测速原理
STM32触摸按键原理和电路设计
01触摸按键原理 触摸使用RC充放电原理: RC电路是指由电阻R和电容C组成的电路,它是脉冲产生和整形电路中常用的电路。 充电过程: 电源通过电阻给电容充电,由于一开始电容两端的电压为0,所以电压的电压都在电阻上,这时电流大,充电速度快。随着电容两端电压的上升,电阻两端的电压下降,电流也随之减小,充电速度小。充电的速度与电阻和电容的大小有关。电阻R越大,充电越慢,电容C越大,充电越慢。衡量充电速度的常数t(tao)=RC。 放电过程: 电容C通过电阻R放电,由于电容刚开始放电时电压为E,放电电流I=E/R,该电流很大,所以放电速度很快。随着电容不断的放电,电容的电压也随着下降。电流也很快减小。电容的放电速度与RC有关,R的阻值
[单片机]
<font color='red'>STM32</font>触摸按键原理和电路设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved