173 2438 5004
KEROS加密芯片——品牌直销 | 免费样品 | 技术支持
当前位置:网站首页 > 资讯中心 正文 资讯中心

stm32实时时钟引脚处理

keros@mark 2023-03-19 资讯中心

STM32的 RTC掉电后还继续计数吗?为什么我的拔掉电源线再重新安装电源RTC就变成0了?

掉电后没有备份电池不会再计数。拔掉电源,也没有备份电池,CPU不再计数,重新上电RTC就会变为0。STM32有一个Vbat引脚就是需要外接纽扣电池给CPU掉电后使用的,不接掉电后重新开始计时。而且RTC 是集成电路,实时时钟芯片是日常生活中应用最为广泛的消费类电子产品之一。

它为人们提供精确的实时时间,或者为电子系统提供精确的时间基准,目前实时时钟芯片大多采用精度较高的晶体振荡器作为时钟源。有些时钟芯片为了在主电源掉电时,还可以工作,需要外加电池供电。

扩展资料:

RTC发展历史:

1,早期RTC产品:

早期RTC产品实质是一个带有计算机通讯口的分频器。它通过对晶振所产生的振荡频率分频和累加,得到年、月、日、时、分、秒等时间信息并通过计算机通讯口送入处理器处理。

2,中期RTC产品:

在20世纪90年代中期出现了新一代RTC,它采用特殊CMOS工艺;功耗大为降低,典型值约0.5μA下;供电电压仅为1.4V以下;和计算机通讯口也变为串行方式,出现了诸如三线SIO/四线SPI,部分产品采用2线I2C总线;包封上采用SOP/SSOP封装,体积大为缩小;

基于stm32的多功能时钟1——时钟显示

        读者们,大家好!

        接着上一章多功能时钟(绪论)的内容,在这一章中,我将介绍多功能时钟的时钟显示部分。话不多说,我们正式开始吧~

        多功能时钟,时钟显示功能是必不可少的。所以,我们利用stm32的定时器来计时。本来打算采用stm32的RTC实时时钟,但后来想,刚开始弄得时候,尽量简单一些,别一开始就给自己出难题,毕竟RTC实时时钟要配置的东西还挺多的。如果此次做得不错的话,后面可以再加RTC实时时钟。

        stm32不同于51,共有11个定时器,其中2个高级控制定时器(TIM1和TIM8),4个普通定时器(TIM2~TIM5)和2个基本定时器(TIM6和TIM7),以及2个看门狗定时器和1个系统滴答定时器。这里,我们采用普通定时器TIM2,并且开启定时器的中断,中断时间为1s,并且在中断函数里,模拟时钟的计时功能。

(1)配置嵌套中断控制器NVIC

void tim2_nvic_config(void)

{

    NVIC_InitTypeDef NVIC_InitStruct;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;

    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级为2

    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;//子优先级为0

    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(NVIC_InitStruct);

}

        这里,我们只需对NVIC_InitStruct结构体的每个元素赋值,其中TIM2_IRQn为定时器TIM2中断线,设置优先级组为2,即抢占优先级组为4组,这里抢占优先级为2,子优先级为0,然后使能NVIC(优先级不能理解上网查询)。

(2)定时器初始化配置

void tim2_config(void)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

    tim2_nvic_config();                                //配置NVIC

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启时钟

    TIM_DeInit(TIM2);                                      //定时器2复位

    TIM_TimeBaseInitStruct.TIM_Period = 2000-1;                  //自动重装载寄存器值

    TIM_TimeBaseInitStruct.TIM_Prescaler = 36000-1;              //时钟预分频数

    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;    //采样分频

    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //计数模式

    TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStruct);            //初始化TIM2

    TIM_ClearFlag(TIM2, TIM_FLAG_Update);                        //清除溢出中断标志

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

    TIM_Cmd(TIM2, ENABLE);                                      //使能时钟

}

        TIM2初始化,首先配置NVIC,打开TIM2时钟,复位TIM2。然后对TIM_TimeBaseInitStruct结构体的每个元素赋值。这里,主要阐述如何计算定时中断时间。定时器的溢出中断时间由TIM_Period和TIM_Prescaler来决定的。这里,我直接给出公式:发生中断时间=(TIM_Period+1)*(TIM_Prescaler+1)/FCLK,而FCLK为72M,所以定时1s,可以这样:TIM_Period=2000-1,TIM_Prescaler=36000-1;最后清除溢出中断标志,使能时钟即可计时。

(3)编写中断计时函数

void TIM2_IRQHandler(void)

{

    if(TIM_GetITStatus(TIM2 ,TIM_IT_Update)!=RESET)

    {

        sec++;

        if(sec=60)

        {

            sec = 0;

            min++;

            if(min=60)

            {

                min = 0;

                hour++;

                if(hour=24)

                {

                    hour = 0;

                }

            }

        }

    }

    TIM_ClearITPendingBit(TIM2 ,TIM_FLAG_Update);

}

这里,先定义时、分、秒三个变量,然后在中断函数里,对时间变量的关系进行换算即可。

(4)编写时钟显示函数

        这里,我们采用LCD12864实时显示。LCD12864的相关内容,我后面在LCD库函数章节中,会专门介绍的。这里,只将时间显示即可。

    lcd_display_num_m(2, 16, hour/10);

    lcd_display_num_m(2, 24, hour%10);

    lcd_display_string(2,32,"时");

    lcd_display_num_m(2, 48, min/10);

    lcd_display_num_m(2, 56, min%10);

    lcd_display_string(2,64,"分");

    lcd_display_num_m(2, 80, sec/10);

    lcd_display_num_m(2, 88, sec%10);

    lcd_display_string(2,96,"秒");

        LCD12864的驱动函数,我跟着黄老师的视频后面写的,在老师的基础上,增加了汉字字符串显示函数。这里,看成库函数即可,只需简单的调用,显示时间就行。

(5)按键调整时间

        成功显示时间后,我们需要按键来调整时间。 我们需要设置时钟启/停键(K1),时间位选择键(K2),数值增加键(K3),数值减小键(K4)。

1.我们先对按键的GPIO进行配置,开启相应的时钟,选择相关引脚,设置浮空输入模式等。

void key_gpio_init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    /*使能GPIO的RCC时钟*/

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

    /*配置PB11~PB14引脚*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_Init(GPIOB,GPIO_InitStructure);

}

2.配置好按键的GPIO口后,编写按键扫描函数,从而达到调整时间的功能。

u8 flag,mark;//flag为定时器启停标志位,mark为位选择标志位

//mark为0表示未选中,mark为1表示选择时位,mark为2表示选择分位,mark为3表示选择秒位

void keyscan(void)

{

    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET)

    {

        delay_ms(10);

        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET)

        {

            flag = ~flag;

            if(!flag)

            {

                TIM_Cmd(TIM2, ENABLE);

            }

            else

            {

                TIM_Cmd(TIM2, DISABLE);

                mark = 0;

            }

        }while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET);

    }

    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET)

    {

        delay_ms(10);

        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET)

        {

            mark = mark=3?0:mark+1;

        }while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET);

    }

    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET)

    {

        delay_ms(10);

        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET)

        {

            if(flag)

            {

                switch(mark)

                {

                    case 1:hour = hour23?hour+1:0;break;

                    case 2:min = min59?min+1:0;break;

                    case 3:sec = sec59?sec+1:0;break;

                    default:break;

                }

            }

        }while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET);

    }

    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET)

    {

        delay_ms(10);

        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET)

        {

            if(flag)

            {

                switch(mark)

                {

                    case 1:hour = hour0?hour-1:23;break;

                    case 2:min = min0?min-1:59;break;

                    case 3:sec = sec0?sec-1:59;break;

                    default:break;

                }

            }

        }while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET);

    }

}

        至此,我们完成了时钟显示的功能,当然,后期如果可以的话,我们可以使用stm32的RTC实时时钟资源,还可以设置闹钟、整点报时的功能。

         本章,我主要介绍了如何利用stm32的TIM定时器和GPIO资源,实现时钟显示和按键调整的功能。下一章中,我将介绍如何利用DHT11模块来测量温度和湿度,从而实现系统对环境参量的获取。

基于stm32的多功能时钟4——超声波测距

        hello,读者们好!

         前两章,主要讲述了环境参量的测量获取,想必大家都有些许收获。在这一章中,我将介绍如何利用超声波来测距。在现实生活中,利用超声波测距的应用很多,广泛应用于机器人避障 、物体测距 、液位检测 、公共安防、停车场检测等领域。

        本次测距使用的超声波为HC-SRO4,该模块共有4个引脚,分别是两个电源引脚VCC和GND,一个触发控制信号输入(TRIG)和一个回响信号输出( ECHO),性能稳定,测度距离精确,模块高精度,盲区小。

        那么,超声波模块测距原理是:首先,给Trig引脚至少10us的高电平信号,检测Echo是否有信号返回,若有信号返回,则Echo发出高电平。高电平持续的时间就是超声波从发射到返回的时间,所以测试距离为(高电平时间*声速)/2。下面,就是超声波模块的时序图。

        本模块使用方法简单,配合stm32的定时器TIM4,一个控制口发一个10us以上的高电平,就可以在接收口等待高电平输出。一有输出就可以开定时器TIM4计时,当此口变为低电平时就可以读定时器TIM4的值,此时就为此次测距的时间,方可算出距离。如此不断的周期测,即可以达到你移动测量的值。

(1)配置超声波的引脚

/*初始化超声波引脚:Trig:PB0,Echo:PB1*/

void ultra_gpio_init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    /*使能GPIO的RCC时钟*/

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

    /*配置Trig引脚*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//Trig

    GPIO_Init(GPIOB,GPIO_InitStructure);

    /*配置Echo引脚*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//Echo

    GPIO_Init(GPIOB,GPIO_InitStructure);

}

        由于PB0接超声波Trig引脚,所以选择推挽输出模式,PB1接超声波Echo引脚,所以选择浮空输入模式。这样,超声波模块引脚就配置完成。

(2)定时器TIM4初始化

/*定时器4的NVIC配置*/

void tim4_nvic_config(void)

{

    NVIC_InitTypeDef NVIC_InitStruct;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn;

    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级为0

    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;//子优先级为0

    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(NVIC_InitStruct);

}

/*定时器4初始化*/

void tim4_config(void)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

    tim4_nvic_config();                                //配置NVIC

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//开启时钟

    TIM_DeInit(TIM4);                                      //定时器4复位

    TIM_TimeBaseInitStruct.TIM_Period = 1000-1;                  //自动重装载寄存器值

    TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1;              //时钟预分频数

    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;    //采样分频

    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //计数模式

    TIM_TimeBaseInit(TIM4, TIM_TimeBaseInitStruct);            //初始化TIM4

    TIM_ClearFlag(TIM4, TIM_FLAG_Update);                        //清除溢出中断标志

    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

    TIM_Cmd(TIM4, DISABLE);

}

        由于考虑到测距时的距离过大,计数会溢出,出现不准确的现象,这里需要用到长计时,并且使用TIM4中断对计时变量进行自增,所以需要配置NVIC。这里设置的中断优先级比较高,因为测距不能被其他中断打断,否则可能出现数据不准的现象,或是数据抖动现象。其次,设置TIM4的中断溢出时间为1ms,此时还不能开启定时器TIM4。

(3)编写定时器中断程序

/*定时器4中断服务函数*/

void TIM4_IRQHandler(void)

{

    if(TIM_GetITStatus(TIM4 ,TIM_IT_Update)!=RESET)

    {

        TIM4_NUM++;//长计时变量

    }

    TIM_ClearITPendingBit(TIM4 ,TIM_FLAG_Update);

}

        为避免测量的距离过长,这里我们需要进行长计时,只需在中断函数里这样操作:TIM4_NUM++,同时记得在每次测量距离前对TIM4_NUM复位即可。

(4)编写超声波测距相关函数

/*启动超声波测距*/

u16 ultra_measure(void)

{

    u16 distance;

    TRIG_H;

    delay_us(20);

    TRIG_L;

    while(ECHO==RESET);

    TIM_SetCounter(TIM4,0);

    TIM4_NUM = 0;

    TIM_Cmd(TIM4, ENABLE);

    while(ECHO!=RESET);

    TIM_Cmd(TIM4, DISABLE);

    distance = (u16)ultra_get_distance();

    return distance;

}

/*获取超声波传播时间,间接计算出距离*/

float ultra_get_distance(void)

{

    u32 time;

    float distance;

    time = TIM4_NUM*1000;

    time += TIM_GetCounter(TIM4);//获取超声波测距总时间

    TIM4-CNT = 0;                            //定时器复位

    distance = (float)time*0.017;

    return distance;

}

        这里,需要查阅超声波手册中的时序图,方可编写程序。首先,向给trig 发送至少10 us的高电平脉冲,然后等待,捕捉 echo 端输出上升沿,捕捉到上升沿的同时,打开定时器开始计时,再次等待捕捉echo的下降沿,当捕捉到下降沿,读出计时器的时间,这就是超声波在空气中运行的时间,按照测试距离=(高电平时间*声速)/2 就可以算出超声波到障碍物的距离。

        这里我们测算的距离:distance = (float)time*0.017,计算的距离单位为cm。

(5)主函数调用测距函数

最后,在主函数里,调用测距函数即可获取到距离值,再通过lcd显示函数,显示出距离值。

    value = ultra_measure();

    lcd_display_string(0,32,"测量距离");

    lcd_display_num_m(3, 48, value/1000);

    lcd_display_num_m(3, 56, (value%1000)/100);

    lcd_display_num_m(3, 64, (value%100)/10);

    lcd_display_num_m(3, 72, value%10);

        通过本章的介绍,相信你对于超声波测距应该了解不少了吧,相信你也可以做出来的。通过不断改变超声波和障碍物之间的位置,距离值会随之改变,是不是很有趣啊~

        到目前为止,多功能时钟已经具备了显示时间、测量温湿度、测量空气质量以及测距的功能,但我们的LCD显示部分还没有优化。在下一章中,我将带着大家完成多功能时钟人机交互界面(简称UI)的开发,到时候,我们的界面就会变得比较美观了。敬请期待~

stm32fir实时吗

实时。英文缩写:RTC。显示年、月、日、时、分、秒、星期,自动计算闰年,能够区分每个月的天数。

RTC特点:能从RTC获取到具体的日期时间,断掉后再开机时间仍然准确。

RTC模块分为两种,一种集成在芯片内部,另外一种是外接RTC芯片。

芯片集成:

1.外设、模块功能

集成→直接用内部寄存器/寄存器配置

没有集成→外接模块

2.协议

集成

(USART,IIC,SPI…)直接用芯片内部控制器进行控制

没有集成

1.IO模拟。

2.芯片内有没有读写时序一致的协议

例: 8080协议→驱动屏幕,内部没有集成8080

FSMC:静态存储器,读写时序与8080一致

用FSMC模拟8080驱动屏幕

STM32内部实时时钟介绍

BCD:二进制的十进制码

BIN:二进制

HEX:十六进制

BCD码表示时间:

15:39

0001 0101:0011 1001

  实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器。 RTC 提供一个日历时钟、两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。 RTC 还包含用于管理低功耗模式的自动唤醒单元。

  两个 32 位寄存器包含二进码十进数格式 (BCD) 的秒、分钟、小时( 12 或 24 小时制)、星期几、日期、月份和年份。此外,还可提供二进制格式的亚秒值。

  系统可以自动将月份的天数补偿为 28、 29(闰年)、 30 和 31 天。并且还可以进行夏令时(在夏季的某一天会在凌晨时分跳过一小时,而后会在冬季补回来)补偿。

  其它 32 位寄存器还包含可编程的闹钟亚秒、 秒、分钟、小时、星期几和日期。此外,还可以使用数字校准功能对晶振精度的偏差进行补偿。

  上电复位后,所有 RTC 寄存器都会受到保护,以防止可能的非正常写访问。

  无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内, RTC 便不会停止工作。

STM32内部实时时钟特点

RTC的电源部分

LSI,LSE,HSE 都可提供时钟给RTC,但对于某些器件来说,可能没有外部晶振提供时钟,所以最好使用内部低速时钟提供时钟源。

当主电源 VDD 断电时,可通过 VBAT (纽扣电池)电压为实时时钟 (RTC)、 RTC 备份寄存器和备份 SRAM(BKP SRAM) 供电。

访问RTCRTC备份域数据、需要按照以下步骤

将 RCC_APB1ENR 寄存器中的 PWREN 位置 2.使能电源接口时钟

电源控制器中的PWR_CR的DBP位值1(使能对备份域的访问)

选择RTC时钟源(LSI LSE HSE)

1.配置RCC_BDCR中的RTCSEL[1:0]、选择时钟源

2.如果选择了HSE、需要配置RCC_CFGR中的RTCPRE[4:0]位进行分频

对RCC_BDCR中的RTCCEN[15]位进行编程、使能RTC时钟

STM32内部实时时钟框架

RTC基本日历功能框架分析

基本日历功能主要就是让日历模块正常工作(1秒1秒地计数),我们从日历时间读取出当前实时时间日期。也就是说,日历的工作频率就是1HZ。

RTC寄存器写保护

上电复位后、所有的RTC寄存器受到写保护、取消写保护必须按照以下顺序将对应的密钥写入关键字寄存器(RTC_WPR)

1)0xCA写入RTC_WPR

2) 0x53写入 RTC_WPR

RTC进入初始化模式(设置日历寄存器要注意)

要编程包括时间格式和预分频器配置在内的初始时间和日期日历值,需按照以下顺序操作:

将 RTC_ISR 寄存器中的 INIT 位置 1 以进入初始化模式。在此模式下,日历计数器将停止工作并且其值可更新。

轮询 RTC_ISR 寄存器中的INITF 位。当 INITF置1时进入初始化阶段模式。大约需要2个RTCCLK 时钟周期(由于时钟同步)。

要为日历计数器生成 1 Hz 时钟,应首先编程 RTC_PRER 寄存器中的同步预分频系数,然后编程异步预分频系数。即使只需要更改这两个字段中之一,也必须对 RTC_PRER寄存器执行两次单独的写访问。

在影子寄存器( RTC_TR 和 RTC_DR)中加载初始时间和日期值,然后通过 RTC_CR寄存器中的 FMT 位配置时间格式( 12 或 24 小时制)。

通过清零 INIT 位退出初始化模式。随后,自动加载实际日历计数器值,在 4 个 RTCCLK时钟周期后重新开始计数。

RTC同步(读取日历值要注意)

  每次将日历寄存器中的值复制到RTC_SSR、RTC_TR和RTC_DR影子寄存器时,RTC_ISR寄存器中的 RSF 位都会置1(日历影子寄存器已同步 )。每两个 RTCCLK 周期执行一次复制。为确保这 3 个值来自同一时刻点,读取 RTC_SSR 或 RTC_TR 时会锁定高阶日历影子寄存器中的值,直到读取RTC_DR。为避免软件对日历执行读访问的时间间隔小于 2 个 RTCCLK 周期:第一次读取日历之后必须通过软件将 RSF 清零,并且软件必须等待到 RSF 置 1 之后才可再次读取RTC_SSR、 RTC_TR 和 RTC_DR 寄存器。

/*

函 数 名:Rtc_Config

函数功能:实时时钟RTC初始化

返 回 值:无

形 参:无

备 注:

*/

void Rtc_Config(void)

{

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); //打开电源接口时钟

PWR_BackupAccessCmd(ENABLE); //启动寄存器访问

RCC_LSICmd(ENABLE); //打开LSI时钟

// RCC_LSEConfig(RCC_LSE_ON); //打开LSE时钟

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //选择LSI时钟为RTC时钟源

RCC_RTCCLKCmd(ENABLE); //RTC时钟使能

RTC_WriteProtectionCmd(DISABLE); //取消写保护

RTC_EnterInitMode();

RTC_InitTypeDef rtc_InitTypeDef; //初始化结构体

rtc_InitTypeDef.RTC_AsynchPrediv = 0x7f; //异步分频

rtc_InitTypeDef.RTC_HourFormat = RTC_HourFormat_24; //24小时格式

rtc_InitTypeDef.RTC_SynchPrediv = 0xff; //同步分频

RTC_Init(rtc_InitTypeDef); //RTC初始化

Rtc_Set_Data(22,9,2,5);

Rtc_Set_Time(RTC_H12_PM,17,0,0);

RTC_ExitInitMode();

}

/*

函 数 名:Rtc_Set_Time

函数功能:设置初始时间

返 回 值:ErrorStatus 设置成功失败的标志

形 参:u8 h12,u8 hour,u8 min,u8 sec

备 注:

*/

ErrorStatus Rtc_Set_Time(u8 h12,u8 hour,u8 min,u8 sec)

{

RTC_TimeTypeDef rtc_TimeTypeDef; //时间结构体

rtc_TimeTypeDef.RTC_H12 = h12; //AM 或 24 小时制

rtc_TimeTypeDef.RTC_Hours = hour; //小时

rtc_TimeTypeDef.RTC_Minutes = min; //分钟

rtc_TimeTypeDef.RTC_Seconds = sec; //秒

return RTC_SetTime(RTC_Format_BIN,rtc_TimeTypeDef); //BIN格式,时间初始化

}

/*

函 数 名:Rtc_Set_Data

函数功能:设置初始日期

返 回 值:ErrorStatus 设置成功失败的标志

形 参:u8 year,u8 month,u8 date,u8 weekday

备 注:

*/

ErrorStatus Rtc_Set_Data(u8 year,u8 month,u8 date,u8 weekday)

{

RTC_DateTypeDef rtc_DateTypeDef; //日期结构体

rtc_DateTypeDef.RTC_Year = year; //年

rtc_DateTypeDef.RTC_Month = month; //月

rtc_DateTypeDef.RTC_Date = date; //日

rtc_DateTypeDef.RTC_WeekDay = weekday; //星期

return RTC_SetDate(RTC_Format_BIN,rtc_DateTypeDef); //BIN格式,日期初始化

}

/*

函 数 名:RTC_print

函数功能:时间打印

返 回 值:无

形 参:无

备 注:

*/

void RTC_print(void)

{

RTC_TimeTypeDef RTC_Time;

RTC_DateTypeDef RTC_Data;

RTC_GetTime(RTC_Format_BIN,RTC_Time);

RTC_GetDate(RTC_Format_BIN,RTC_Data);

printf("20%d年%d月%d日星期%d ",RTC_Data.RTC_Year,RTC_Data.RTC_Month,RTC_Data.RTC_Date,RTC_Data.RTC_WeekDay);

printf("%d:%d:%d\r\n",RTC_Time.RTC_Hours,RTC_Time.RTC_Minutes,RTC_Time.RTC_Seconds);

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

RTC可编程闹钟

可编程闹钟介绍

  RTC 单元提供两个可编程闹钟,即闹钟 A 和闹钟 B。

  可通过将RTC_CR寄存器中的ALRAE和ALRBE位置1来使能可编程闹钟功能。如果日历亚秒、秒、分钟、小时、日期或日分别与闹钟寄存器 RTC_ALRMASSR/RTC_ALRMAR和RTC_ALRMBSSR/RTC_ALRMBR 中编程的值相匹配则 ALRAF 和 ALRBF 标志会被置为 1可通过RTC_ALRMAR 和 RTC_ALRMBR 寄存器的 MSKx 位以及 RTC_ALRMASSR和 RTC_ALRMBSSR 寄存器的 MASKSSx 位单独选择各日历字段。可通过 RTC_CR 寄存器中 的 ALRAIE 和 ALRBIE 位使能闹钟中断。

  闹钟 A 和闹钟 B(如果已通过 RTC_CR 寄存器中的位 OSEL[0:1] 使能)可连接到 RTC_ALARM 输出。可通过 RTC_CR 寄存器的 POL 位配置 RTC_ALARM 极性。

编程闹钟

要对可编程的闹钟(闹钟 A 或闹钟 B)进行编程或更新,必须执行类似的步骤:

将 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位清零以禁止闹钟 A 或闹钟 B。

轮询 RTC_ISR 寄存器中的 ALRAWF 或 ALRBWF 位,直到其中一个置 1,以确保闹钟

寄存器可以访问。大约需要 2 个 RTCCLK 时钟周期(由于时钟同步)。

编程闹钟 A 或闹钟 B 寄存器(RTC_ALRMASSR/RTC_ALRMAR 或 RTC_ALRMBSSR/

RTC_ALRMBR)。

将 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位置 1 以再次使能闹钟 A 或闹钟 B。

闹钟中断

u8 alarm_flag;

/*

函 数 名:ALarm_Config

函数功能:RTC闹钟初始化

返 回 值:无

形 参:无

备 注:

*/

void ALarm_Config(u32 week)

{

RTC_AlarmCmd(RTC_Alarm_A,DISABLE); //关闭闹钟A

RTC_AlarmTypeDef rtc_AlarmTypeDef;

rtc_AlarmTypeDef.RTC_AlarmDateWeekDay = week;

rtc_AlarmTypeDef.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay; //每固定星期报警

rtc_AlarmTypeDef.RTC_AlarmMask = RTC_AlarmMask_None; //与日历时间完全匹配

rtc_AlarmTypeDef.RTC_AlarmTime = Rtc_alarmA_time(RTC_H12_PM,17,0,10);

RTC_SetAlarm(RTC_Format_BIN,RTC_Alarm_A,rtc_AlarmTypeDef);

EXTI_InitTypeDef EXTI17_InitTypeDef;

EXTI17_InitTypeDef.EXTI_Line = EXTI_Line17; //外部中断线17

EXTI17_InitTypeDef.EXTI_LineCmd = ENABLE; //外部中断使能

EXTI17_InitTypeDef.EXTI_Mode = EXTI_Mode_Interrupt; //中断寄存器模式

EXTI17_InitTypeDef.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发

EXTI_Init(EXTI17_InitTypeDef);

RTC_ITConfig(RTC_IT_ALRA,ENABLE); //打开ALARMA中断

NVIC_InitTypeDef nvic_InitTypeDef; //中断初始化

nvic_InitTypeDef.NVIC_IRQChannel = RTC_Alarm_IRQn; //中断号

nvic_InitTypeDef.NVIC_IRQChannelPreemptionPriority = 0; //占先优先级

nvic_InitTypeDef.NVIC_IRQChannelSubPriority = 2; //次级优先级

nvic_InitTypeDef.NVIC_IRQChannelCmd = ENABLE; //NVIC中断响应

NVIC_Init(nvic_InitTypeDef); //初始化NVIC中断

RTC_AlarmCmd(RTC_Alarm_A,ENABLE); //闹钟使能

}

/*

函 数 名:Rtc_alarmA_time

函数功能:设置闹钟时间

返 回 值:RTC_TimeTypeDef 闹钟时间结构体

形 参:u8 h12,u8 hour,u8 min,u8 sec,RTC_TimeTypeDef* RTC_TimeStruct

备 注:

*/

RTC_TimeTypeDef Rtc_alarmA_time(u8 h12,u8 hour,u8 min,u8 sec)

{

RTC_TimeTypeDef Alarm_Time;

Alarm_Time.RTC_H12 = h12;

Alarm_Time.RTC_Hours = hour;

Alarm_Time.RTC_Minutes = min;

Alarm_Time.RTC_Seconds = sec;

return Alarm_Time;

}

/*

函 数 名:RTC_Alarm_IRQHandler

函数功能:RTC闹钟中断服务函数

返 回 值:无

形 参:无

备 注:

*/

void RTC_Alarm_IRQHandler(void)

{

if(RTC_GetFlagStatus(RTC_FLAG_ALRAF))

{

RTC_ClearFlag(RTC_FLAG_ALRAF);

alarm_flag = 1;

}

EXTI-PR |= (0x01 17); //挂起寄存器写1清零

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

打开CSDN APP,看更多技术内容

STM32-RTC实时时钟_ONE_Day|的博客_stm32内置rtc可采用...

RTC时钟源有三种来源,分别是HSE的128分频,LSE时钟源,LSI时钟源,一般RTC选择的是LSE时钟源,也就是外部低速时钟源,外接一个32.768KHz的晶振,因为这个时钟源比较准确 RTC组成 APB1接口:用来和APB1总线相连。通过APB1接口可以访问RTC的相关...

继续访问

16.STM32RTC实时时钟知识与实验_stm32 rtc_普通的不普通少年的博客-CSD...

1.实时时钟 RTC是一个独立的BCD定时器/计数器。RTC提供一个日历时钟,两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC还包括用于管理低功耗模式的自动唤醒单元。 有两个32位的寄存器,包含二进制吗十进制格式BCD的...

继续访问

i2c_rtc.rar_dsp28335_iic rtc_iic 读取rtc实验

首先 通过模拟IIC接口,往RTC寄存器中写一个预设时间,再通过模拟IIc读取RTC寄存器中的时间,观察秒钟的变化情况。

i2c底层数据传输解析之RTC实时时钟

在i2c上进行数据传输,都是通过一个叫i2c_smbus_xfer的函数进行传输,这个函数被i2c_smbus函数族所调用,不同的i2c_smbus函数族的函数调用时都会传入一个i2c_smbus_xfer_emulated函数的switch中所需要的size,在case分支中将不同的数据写入i2c_msg结构体成员,然后执行i2c_smbus_xfer_emulated中的i2c_transfer,i2c_transfer最终调用了i2c_algorithm算法实现中的master_xfer周期性的发送i

继续访问

STM32实时时钟_面向offer编程的博客_获取clk时钟 stm32

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

继续访问

STM32之RTC实时时钟

RTC实时时钟简介: STM32的RTC外设,实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断).但是从掉电还能继续运行来看,它是STM32中唯一一个具有这个功能功能的外设.(RTC外设的复杂之处不在于它的定时,而在于它掉电还可以继续运行的特性) 所谓掉电,是指电源Vpp断开的情况下,为了RTC外设掉电可以继续运行,必须给STM32芯片通过VBAT引脚街上锂电池.当主电源VDD有效时,由VDD给RTC外设供电.当VDD掉电后,

继续访问

【STM32】详解RTC实时时钟的概念和配置示例代码

RTC实时时钟

继续访问

STM32之RTC

简介:STM32 的实时时钟(RTC)是一个独立的定时器。STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。 框图: 相关寄存器: 控制寄存器 第 0 位是秒钟标志位,我们在进入闹钟中断的时候,通过判断这位来决定是不是发生了秒钟中断。然后必须通过软件将该位清零(写0) 第 3 位为寄存器同步标志位,我们在修改控制寄存器 RTC_CRH/CRL 之前,必须先判断该位,是否已经同步了,如果没有则等待同步,在没同步的情

继续访问

STM32基础10--实时时钟(RTC)

目录 前言 RTC框图 STM32实时时钟电路 功能需要 STM32CubeMx配置RTC 配置RCC 配置RTC 配置时间,闹钟,唤醒 开启中断 设置中断优先级 功能代码实现 STM32Cude生成RTC初始化 自定义触发闹钟次数变量 重写周期唤醒回调函数 重写闹钟中断函数 前言 在做51单片机项目时,如果需要年月日时分秒的时间记录,会在51单片机上面外挂一个DS1302的时钟芯片,再加上时间芯片的外围电路。但在STM32F407中,不再需...

继续访问

STM32精英版(正点原子STM32F103ZET6开发板)学习篇15——RTC实时时钟+备份区域BKP

摘抄自正点原子官方PPT 什么是RTC?   RTC (Real Time Clock):实时时钟,是个独立的定时器。RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期。   RTC模块和时钟配置系统(RCC_BDCR寄存器)是在后备区域(断电后还会工作),即在系统复位或从待机模式唤醒后RTC的设置和时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前, 先要取消备

继续访问

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

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

继续访问

STM32日历读取,设置和输出

一、了解时钟RTC RTC (Real Time Clock):实时时钟 RTC是个独立的定时器。RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。 在断电情况下 RTC仍可以独立运行 只要芯片的备用电源一直供电,RTC上的时间会一直走。 RTC实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能(也可以触发中断)。但其高

继续访问

STM32基于固件库学习笔记(11)RTC实时时钟

使用RTC实时时钟的秒中断打印当前时间。(相当于使用简单的定时器每一秒中断打印时间)

继续访问

STM32:RTC实时时钟原理

STM32:RTC实时时钟原理

继续访问

DS1307实时时钟RTC读取(STM32)记录

最开始将函数从51单片机移植过来,如何整都读取出来的数据是65,不是实时时钟数据,查了下手册,发现必须4.5V-5.5V供电才可以,没有办法,跳线解决,但SCL与SDA采用3.3V+10K电阻上拉倒没有问题; 读取函数设置如下(PB12 PB13): //初始化IIC void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_...

继续访问

STM32-RTC实时时钟-毫秒计时实现

阅读目录 1、RTC时钟简介 2、软硬件设计 3、时钟配置与函数编写 4、秒钟计时原理 5、毫秒计时原理 6、修改时间 OS:Windows 64 Developmentkit:MDK5.14 IDE:UV4 MCU:STM32F103C8T6 回到顶部 1、RTC时钟简介 STM32的实时时钟(RTC)是一个独立的定时器,在相应软件配置下,可提供时钟日历的功能。 详细资料请参考ALIENTEK的官方文档——《STM32F1开发指南(精英版-库函数版)》,以下为博主摘录要..

继续访问

FPGA-使用RTC时钟芯片进行时钟读取(数码管显示)

做时钟显示如果用单片机做,会产生很大的累积误差,本程序采用时钟芯片PCF8563 一:芯片主要电气特性: 1)大工作电压范围:1.0~5.5V 2)400KHz 的 I2C 总线接口(VDD=1.8~5.5V 时)。 时钟频率最大400KH 3)i2C 总线从地址:读,0A3H;写,0A2H . 二:管脚 电路接线图: top.v: mod...

继续访问

51-DS1302实时时钟

51单片机

继续访问

STM32——实时时钟RTC的日历读取

STM32的 RTC 外设(Real Time Clock),实质是一个掉电后还继续运行的定时器。从定时器的角度来说,相对于通用定时器 TIM 外设,它十分简单,只有很纯粹的计时和触发中断的功能;但从掉电还继续运行的角度来说,它却是 STM32 中唯一一个具有如此强大功能的外设。所以 RTC 外设的复杂之处并不在于它的定时功能,而在于它掉电还继续运行的特性。STM32的 RTC 外设(Real Time Clock),实质是一个掉电后还继续运行的定时器。

继续访问

STM32CubeMX之RTC电子钟

RTC由两个主要部分组成(见下图)。第一部分(APB1 接口 )用来和APB1 总线相连。此单元还包含一组16位寄存器,可通过APB1 总线对其进行读写操作。APB1 接口由APB1 总线时钟驱动,用来与APB1 总线接口。另一部分(RTC核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是RTC的预分频模块,它可编程产生最长为1 秒的RTC时间基准TR_CLK。RTC的预分频模块包含了一个20位的可编程分频器(RTC 预分频器)。

继续访问

最新发布 基于STM32实现RTC实时时钟

rtc实时时钟是一个很重要的内容,今天要配置的时RTC唤醒中断,它在很多地方都会被用到。今天需要配置的东西会有点多,代码长度也会比较长。实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器。RTC 提供一个日历时钟、两个可编程 闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC 还包含用于管理低功耗模式的自动唤醒单元。两个 32 位寄存器包含二进码十进数格式 (BCD) 的秒、分钟、小时(12 或 24 小时制)、星 期几、日期、月份和年份。此外,还可提供二进制格式的亚

stm32时钟怎么关联引脚

高速外部时钟HSE的引脚是OSC_OUT和OSC_IN这两个引脚芯片是独立引出的,可以接外部的晶振电路,而低速外部时钟LSE的引脚OSC32_IN和OSC32_OUT两个引脚不是独立的,而是在PC14和PC15上,对应关系为OSC32_IN--PC14 ; OSC32_OUT--PC15

2018-04-26 STM32中使用内部RC振荡器做系统时钟

STM32使用内部RC振荡器时,OSC32_IN,OSC32_OUT接法:

    1)对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。

    2)对于少于100脚的产品,有2种接法:

          2.1)OSC_IN和OSC_OUT分别通过10K电阻接地。此方法可提高EMC性能。

          2.2)分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽输出并输出'0'。此方法可以减小功耗并(相对上面2.1)节省2个外部电阻。

例程如下:

//=== 晶振脚重映射到PD0,PD1 并配置为推挽输出输出‘0’

void HSI_Config(void) 

   GPIO_InitTypeDef GPIO_InitStructure; 

   RCC_DeInit(); /*将外设RCC寄存器重设为缺省值*/  

   RCC_HSICmd(ENABLE);  

   while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET);//等待HSI就绪  

   RCC_HCLKConfig(RCC_SYSCLK_Div1);  /*设置AHB时钟(HCLK) RCC_SYSCLK_Div1——AHB时钟 = 系统时*/   

   RCC_PCLK2Config(RCC_HCLK_Div1);  /*设置高速AHB时钟(PCLK2)RCC_HCLK_Div1——APB2时钟= HCLK*/      

   RCC_PCLK1Config(RCC_HCLK_Div2); /*设置低速AHB时钟(PCLK1)RCC_HCLK_Div2——APB1时钟= HCLK /2*/       

   FLASH_SetLatency(FLASH_Latency_2); //FLASH_Latency_2 2延时周期 

   FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//预取指缓存使能 

    RCC_PLLConfig(RCC_PLLSource_HSI_Div2,RCC_PLLMul_16);/*设置PLL时钟源及倍频系数,频率为8/2*16=64Mhz*/     

   RCC_PLLCmd(ENABLE);      /*使能PLL */  

   while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) ; /*检查指定的RCC标志位(PLL准备好标志)设置与否*/     

   RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  /*设置系统时钟(SYSCLK)*/   

   while(RCC_GetSYSCLKSource() != 0x08);    /*0x08:PLL作为系统时钟*/    

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD |RCC_APB2Periph_AFIO,ENABLE);//打开重映射时钟,并打开重映射后的IO口 

   GPIO_PinRemapConfig(GPIO_Remap_PD01,ENABLE); //IO口重映射开启 

   /*选择要控制的引脚*/ 

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; 

   /*设置引脚为通用推挽输出*/ 

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 

   /*设置引脚速率为50MHz*/ 

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

   /*调用库函数,初始化GPIOC*/ 

   GPIO_Init(GPIOD, GPIO_InitStructure); 

   /*固定IO口下拉到地*/ 

   GPIO_ResetBits(GPIOD, GPIO_Pin_0 | GPIO_Pin_1); 

    HSI内部8MHz的RC振荡器的误差在1%左右,内部RC振荡器的精度通常比用HSE(外部晶振)要差上十倍以上。STM32的ISP就是用(HSI)内部RC振荡器。

本文标签:stm32实时时钟引脚处理

产品列表
产品封装
友情链接