打印
[其他ST产品]

stm32独立看门狗和rtc闹钟

[复制链接]
558|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
独立看门狗概述
      在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”(watchdog) 。

    看门狗( watchdog timer),是一个定时器(12位)电路, 一般有一个输入,叫喂狗(kicking the dog or service the dog),一个输出到MCU的RST端,MCU正常工作的时候,每隔一段时间输出一个信号到喂狗端,给WDT清零,如果超过规定的时间不喂狗,(一般在程序跑飞时,不在程序正常的状态),WDT 定时超过,就会给出一个复位信号到MCU,使MCU复位. 防止MCU死机. 看门狗的作用就是防止程序发生死循环,或者说程序跑飞。



STM32独立看门狗
独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它仍有效。

   独立看门狗适合应用于需要看门狗作为一个在主程序之外 能够完全独立工作,并且对时间精度要求低的场合。



STM32F4 的独立看门狗由内部专门的 32Khz 低速时钟 (LSI) 驱动,即使主时钟发生故障,它也仍然有效。这里需要注意独立看门狗的时钟是一个内部RC时钟,所以并不是准确的32Khz,而是在15~47Khz 之间的一个可变化的时钟,只是我们在估算的时候,以 32Khz 的频率来计算,独立看门狗对时间的要求不是很精确,所以,时钟有些偏差都是接受的范围。




使用特权

评论回复
沙发
过期的塔头|  楼主 | 2024-2-27 19:29 | 只看该作者

使用特权

评论回复
板凳
过期的塔头|  楼主 | 2024-2-27 19:29 | 只看该作者
3、独立看门狗操作步骤
独立看门狗操作步骤需要添加的库函数文件:stm32f4xx_iwdg.c

1、 取消寄存器写保护:

      IWDG_WriteAccessCmd();

2、设置独立看门狗的预分频系数,确定时钟:

     IWDG_SetPrescaler();

3、设置看门狗重装载值,确定溢出时间:

    IWDG_SetReload();

4、使能看门狗

    IWDG_Enable();

5、应用程序喂狗:

   IWDG_ReloadCounter();

RTC
1、RTC时间
RTC (Real Time Clock):实时时钟

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

两个32位寄存器包含二进码十进制格式(BCD)的秒,分钟,小时(12或24小时制),星期几,日期,月份和年份。此外,还可以提供二进制的亚秒值。系统可以自动将月份的天数补偿为28,29(闰年),30,31天。并且还可以进行夏令时补偿。



选择外部时钟源,当主时钟发生故障时,RTC还能正常运行;且当主电源发生故障,RTC由钮扣电池进行独立供电

使用特权

评论回复
地板
过期的塔头|  楼主 | 2024-2-27 19:30 | 只看该作者
RTC时间与日期配置流程:

RTC时间与日期配置流程所需要的库函数文件:stm32f4xx_rtc.c与stm32f4xx_pwr.c

1、使能PWR时钟:RCC_APB1PeriphClockCmd();

2、使能后备寄存器访问:   PWR_BackupAccessCmd();

3、配置RTC时钟源,使能RTC时钟:

      RCC_RTCCLKConfig();

      RCC_RTCCLKCmd();

      如果使用LSE,要打开LSE:RCC_LSEConfig(RCC_LSE_ON);

4、 初始化RTC(同步/异步分频系数和时钟格式):RTC_Init ();

5、 设置时间:RTC_SetTime ();

6、设置日期:RTC_SetDate();

使用特权

评论回复
5
过期的塔头|  楼主 | 2024-2-27 19:30 | 只看该作者
2、RTC闹钟
RTC 中断
所有 RTC 中断均与 EXTI(外部中断控制) 控制器相连。
要使能 RTC 闹钟中断,需按照以下顺序操作:
1. 将 EXTI 线 17 配置为中断模式并将其使能,然后选择上升沿有效。
2. 配置 NVIC 中的 RTC_Alarm IRQ 通道并将其使能。
3. 配置 RTC 以生成 RTC 闹钟(闹钟 A 或闹钟 B)。

闹钟A配置流程

1、RTC已经初始化好相关参数。

2、关闭闹钟:RTC_AlarmCmd(RTC_Alarm_A,DISABLE);

3、配置闹钟参数:RTC_SetAlarm();

4、开启闹钟:RTC_AlarmCmd(RTC_Alarm_A,ENABLE);

5、开启配置闹钟中断:

     RTC_ITConfig();

     EXTI_Init();

     NVIC_Init();

6、编写中断服务函数:RTC_Alarm_IRQHandler();


使用特权

评论回复
6
过期的塔头|  楼主 | 2024-2-27 19:30 | 只看该作者
三、函数说明
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);

函数功能:是否使能 IWDG_PR and IWDG_RLR寄存器

返回值:无

uint16_t IWDG_WriteAccess:是否使能

IWDG_WriteAccess_Enable

IWDG_WriteAccess_Disable

void IWDG_SetPrescaler(uint8_t IWDG_Prescaler)

函数功能:设置看门预分频器

返回值:无

uint8_t IWDG_Prescaler:分频系数

IWDG_Prescaler_4   

IWDG_Prescaler_8   

IWDG_Prescaler_16  

IWDG_Prescaler_32  

IWDG_Prescaler_64  

IWDG_Prescaler_128

IWDG_Prescaler_256

void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource)

void IWDG_SetReload(uint16_t Reload)

函数功能:设置重载值

返回值:无

uint16_t Reload:重载值寄存器的值,范围:0~0xFFF

void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource)

函数功能:RTC时钟源配置

返回值:无

uint32_t RCC_RTCCLKSource:时钟源选择

RCC_RTCCLKSource_LSE      

RCC_RTCCLKSource_LSI      

RCC_RTCCLKSource_HSE_Div2

RCC_RTCCLKSource_HSE_Div3

RCC_RTCCLKSource_HSE_Div4

RCC_RTCCLKSource_HSE_Div5

RCC_RTCCLKSource_HSE_Div6

RCC_RTCCLKSource_HSE_Div7

RCC_RTCCLKSource_HSE_Div8

RCC_RTCCLKSource_HSE_Div9

RCC_RTCCLKSource_HSE_Div10

RCC_RTCCLKSource_HSE_Div11

RCC_RTCCLKSource_HSE_Div12

RCC_RTCCLKSource_HSE_Div13

RCC_RTCCLKSource_HSE_Div14

RCC_RTCCLKSource_HSE_Div15

RCC_RTCCLKSource_HSE_Div16

RCC_RTCCLKSource_HSE_Div17

RCC_RTCCLKSource_HSE_Div18

RCC_RTCCLKSource_HSE_Div19

RCC_RTCCLKSource_HSE_Div20

RCC_RTCCLKSource_HSE_Div21

RCC_RTCCLKSource_HSE_Div22

RCC_RTCCLKSource_HSE_Div23

RCC_RTCCLKSource_HSE_Div24

RCC_RTCCLKSource_HSE_Div25

RCC_RTCCLKSource_HSE_Div26

RCC_RTCCLKSource_HSE_Div27

RCC_RTCCLKSource_HSE_Div28

RCC_RTCCLKSource_HSE_Div29

RCC_RTCCLKSource_HSE_Div30

RCC_RTCCLKSource_HSE_Div31

使用特权

评论回复
7
过期的塔头|  楼主 | 2024-2-27 19:30 | 只看该作者
ErrorStatus RTC_Init(RTC_InitTypeDef* RTC_InitStruct);

函数功能:RTC设置

返回值

成功:SUCCESS

失败:ERROR

RTC_InitTypeDef* RTC_InitStruct:RTC结构体

typedef struct

{

  uint32_t RTC_HourFormat;   //小时制选择

  

  uint32_t RTC_AsynchPrediv; //异步通道分频器

  

  uint32_t RTC_SynchPrediv;  //同步通道分频器

}RTC_InitTypeDef;

ErrorStatus RTC_SetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);

函数功能:RTC时间设置

返回值

成功:SUCCESS

失败:ERROR

uint32_t RTC_Format:存储格式

RTC_Format_BIN:二进制存储

RTC_Format_BCD:BCD编码存储

RTC_TimeTypeDef* RTC_TimeStruct:时间结构体

typedef struct

{

  uint8_t RTC_Hours;    //时

  uint8_t RTC_Minutes;  //分

  

  uint8_t RTC_Seconds;  //秒

  uint8_t RTC_H12;      //上/下午

}RTC_TimeTypeDef;

ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct);

函数功能:RTC日期设置

返回值

成功:SUCCESS

失败:ERROR

uint32_t RTC_Format:存储格式

RTC_Format_BIN:二进制存储

RTC_Format_BCD:BCD编码存储

RTC_DateTypeDef* RTC_DateStruct:日期结构体

typedef struct

{

  uint8_t RTC_WeekDay; //星期

  

  uint8_t RTC_Month;   //月

  uint8_t RTC_Date;     //日

  

  uint8_t RTC_Year;     //年

}RTC_DateTypeDef;

/**

  * @brief  Set the specified RTC Alarm.

  * @NOTE   The Alarm register can only be written when the corresponding Alarm

  *         is disabled (Use the RTC_AlarmCmd(DISABLE)).   

  * @param  RTC_Format: specifies the format of the returned parameters.

  *          This parameter can be one of the following values:

  *            @ARG RTC_Format_BIN: Binary data format

  *            @arg RTC_Format_BCD: BCD data format

  * @param  RTC_Alarm: specifies the alarm to be configured.

  *          This parameter can be one of the following values:

  *            @arg RTC_Alarm_A: to select Alarm A

  *            @arg RTC_Alarm_B: to select Alarm B  

  * @param  RTC_AlarmStruct: pointer to a RTC_AlarmTypeDef structure that

  *                          contains the alarm configuration parameters.     

  * @retval None

  */

void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmTypeDef* RTC_AlarmStruct)

函数说明:闹钟设置

返回值:无

uint32_t RTC_Format:存储格式

RTC_Format_BIN:二进制存储

RTC_Format_BCD:BCD编码存储

uint32_t RTC_Alarm:选择闹钟

RTC_Alarm_A:闹钟A

RTC_Alarm_B:闹钟B

RTC_AlarmTypeDef* RTC_AlarmStruct:闹钟结构体

typedef struct

{

  RTC_TimeTypeDef RTC_AlarmTime;     //时间设置

  uint32_t RTC_AlarmMask;            //掩码位

  uint32_t RTC_AlarmDateWeekDaySel;  //选择日期还是星期设置闹钟

  

  uint8_t RTC_AlarmDateWeekDay;      //日期还是星期

}RTC_AlarmTypeDef;

typedef struct

{

  uint8_t RTC_Hours;    //时

  uint8_t RTC_Minutes;  //分

  

  uint8_t RTC_Seconds;  //秒

  uint8_t RTC_H12;      //上/下午

}RTC_TimeTypeDef;

使用特权

评论回复
8
过期的塔头|  楼主 | 2024-2-27 19:31 | 只看该作者
看门狗
#include "iwdg.h"

void Iwdg_Init(void)
{
        //1、 取消寄存器写保护:
        IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
        //2、设置独立看门狗的预分频系数,确定时钟; 在32KHZ,分频128,得频率:250HZ
        IWDG_SetPrescaler(IWDG_Prescaler_128);
        //3、设置看门狗重装载值,确定溢出时间:2S
        IWDG_SetReload(500);
        //4、使能看门狗
        IWDG_Enable();

        //应用程序喂狗:
    IWDG_ReloadCounter();
}

使用特权

评论回复
9
过期的塔头|  楼主 | 2024-2-27 19:31 | 只看该作者
#ifndef __IWDG_H
#define __IWDG_H

#include "stm32f4xx.h"


void Iwdg_Init(void);

#endif

使用特权

评论回复
10
过期的塔头|  楼主 | 2024-2-27 19:31 | 只看该作者
#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"
#include "usart.h"
#include "sys.h"
#include "dht11.h"
#include "infrared.h"
#include "iwdg.h"


u8  buffer[64] = {0};
u8  rx_buffer[64] = {0};
u8  count = 0, rx_i = 0;
u8  rx_flag = 0; //接受标志位,rx_flag = 表示数据帧完毕


void USART1_IRQHandler(void)
{
       


        //判断接收标志位是否为1
        if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART1, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART1);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
               
                }
               
        }
}




void USART2_IRQHandler(void)
{
       
        u8 data;

        //判断接收标志位是否为1
        if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART2, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART2);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
                }
               
        }


}


void USART3_IRQHandler(void)
{
       
        u8 data;

        //判断接收标志位是否为1
        if(USART_GetITStatus(USART3, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART3, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART3);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
                }
               
        }


}




int main(void)
{
        int ret;
        u8 data[5] = {0};
        //设置NVIC分组(一个工程只能设置一个分组)
        //第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        Led_Init();
        Delay_Init();
        Tim7_Init();        //初始化定时器7
        Usart1_Init(115200);
        Iwdg_Init();
        printf("iwdg test\r\n");
       
        while(1)
        {
               
               
                if(GPIO_ReadInputDataBit(GPIOA,  GPIO_Pin_0) == Bit_RESET)
                {
                        //延时消抖 20ms
                        delay_ms(20);
                        //判断按键是否按下
                        if(GPIO_ReadInputDataBit(GPIOA,  GPIO_Pin_0) == Bit_RESET)
                        {
                                printf("key up\r\n");
                               
                                //往一个非法地址写入一个值,模拟程序跑飞
                                *((unsigned int *)0xC0000000) = 0x666;
                        }

                }               
               
                //这里的循环相当应用程序的时间
                delay_s(4);


        }
}

使用特权

评论回复
11
过期的塔头|  楼主 | 2024-2-27 19:31 | 只看该作者
RTC_TIM
#include "rtc.h"

#define  BKP_DR  0x2162


void Rtc_Tim_Init(void)
{

        RTC_InitTypeDef  RTC_InitStruct;
        RTC_TimeTypeDef  RTC_TimeStruct;
        RTC_DateTypeDef  RTC_DateStruct;
       
        //1、使能PWR时钟,与电源寄存器有关
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
        //2、使能后备寄存器访问,是一种掉电保存数据的寄存器  
        PWR_BackupAccessCmd(ENABLE);
       
        //判断后备寄存器的值
        if(RTC_ReadBackupRegister(RTC_BKP_DR0) != BKP_DR)
        {
                //3、配置RTC时钟源,使能RTC时钟:
                RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
                RCC_RTCCLKCmd(ENABLE);
                //如果使用LSE,要打开LSE:
                RCC_LSEConfig(RCC_LSE_ON);
                //延时一段时间,等待时钟源稳定
                delay_ms(50);
               
                RTC_InitStruct.RTC_HourFormat        = RTC_HourFormat_24;        //24小时制
                RTC_InitStruct.RTC_AsynchPrediv        = 0x7F;                                        //异步分频 128分频
                RTC_InitStruct.RTC_SynchPrediv        = 0xFF;                                        //同频分频 255分频
                //4、初始化RTC(同步/异步分频系数和时钟格式):
                RTC_Init(&RTC_InitStruct);


                RTC_TimeStruct.RTC_H12                = RTC_H12_PM;                //下午 24小时制,可写可不写
                RTC_TimeStruct.RTC_Hours        = 15;                                //小时
                RTC_TimeStruct.RTC_Minutes        = 30;                                //分
                RTC_TimeStruct.RTC_Seconds        = 10;                                //ADC+
                RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);       
               
                RTC_DateStruct.RTC_Year                   = 21;                                        //年份
                RTC_DateStruct.RTC_Month        = 11;                                        //月份
                RTC_DateStruct.RTC_Date                = 16;                                        //日
                RTC_DateStruct.RTC_WeekDay  = RTC_Weekday_Tuesday;        //星期二
                RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
       
                //将值写入后备寄存器
                RTC_WriteBackupRegister(RTC_BKP_DR0, BKP_DR);
       
        }
}

使用特权

评论回复
12
过期的塔头|  楼主 | 2024-2-27 19:31 | 只看该作者
#ifndef __RTC_H
#define __RTC_H

#include "stm32f4xx.h"
#include "delay.h"

void Rtc_Tim_Init(void);

#endif

使用特权

评论回复
13
过期的塔头|  楼主 | 2024-2-27 19:31 | 只看该作者
#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"
#include "usart.h"
#include "sys.h"
#include "dht11.h"
#include "infrared.h"
#include "iwdg.h"
#include "rtc.h"


u8  buffer[64] = {0};
u8  rx_buffer[64] = {0};
u8  count = 0, rx_i = 0;
u8  rx_flag = 0; //接受标志位,rx_flag = 表示数据帧完毕


void USART1_IRQHandler(void)
{
       


        //判断接收标志位是否为1
        if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART1, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART1);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
               
                }
               
        }
}




void USART2_IRQHandler(void)
{
       
        u8 data;

        //判断接收标志位是否为1
        if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART2, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART2);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
                }
               
        }


}


void USART3_IRQHandler(void)
{
       
        u8 data;

        //判断接收标志位是否为1
        if(USART_GetITStatus(USART3, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART3, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART3);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
                }
               
        }


}





int main(void)
{
        RTC_TimeTypeDef  RTC_TimeStruct;
        RTC_DateTypeDef  RTC_DateStruct;       
       
       
        //设置NVIC分组(一个工程只能设置一个分组)
        //第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//        Led_Init();
        Delay_Init();

        Usart1_Init(115200);

        Rtc_Tim_Init();
       

       
        while(1)
        {
                //获取日期
                RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
                printf("日期:%d-%d-%d 星期:%d\r\n",RTC_DateStruct.RTC_Year,
                RTC_DateStruct.RTC_Month,RTC_DateStruct.RTC_Date,RTC_DateStruct.RTC_WeekDay);
                //获取时间
                RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);
                printf("时间:%d:%d:%d\r\n",RTC_TimeStruct.RTC_Hours,
                RTC_TimeStruct.RTC_Minutes,RTC_TimeStruct.RTC_Seconds);
                delay_s(1);
        }
}

使用特权

评论回复
14
过期的塔头|  楼主 | 2024-2-27 19:31 | 只看该作者
#ifndef __RTC_H
#define __RTC_H

#include "stm32f4xx.h"
#include "delay.h"

void Rtc_Tim_Init(void);

#endif


使用特权

评论回复
15
过期的塔头|  楼主 | 2024-2-27 19:31 | 只看该作者
#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"
#include "usart.h"
#include "sys.h"
#include "dht11.h"
#include "infrared.h"
#include "iwdg.h"
#include "rtc.h"


u8  buffer[64] = {0};
u8  rx_buffer[64] = {0};
u8  count = 0, rx_i = 0;
u8  rx_flag = 0; //接受标志位,rx_flag = 表示数据帧完毕


void USART1_IRQHandler(void)
{
       


        //判断接收标志位是否为1
        if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART1, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART1);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
               
                }
               
        }
}




void USART2_IRQHandler(void)
{
       
        u8 data;

        //判断接收标志位是否为1
        if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART2, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART2);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
                }
               
        }


}


void USART3_IRQHandler(void)
{
       
        u8 data;

        //判断接收标志位是否为1
        if(USART_GetITStatus(USART3, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART3, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART3);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
                }
               
        }


}





int main(void)
{
        RTC_TimeTypeDef  RTC_TimeStruct;
        RTC_DateTypeDef  RTC_DateStruct;       
       
       
        //设置NVIC分组(一个工程只能设置一个分组)
        //第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//        Led_Init();
        Delay_Init();

        Usart1_Init(115200);

        Rtc_Tim_Init();
       

       
        while(1)
        {
                //获取日期
                RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
                printf("日期:%d-%d-%d 星期:%d\r\n",RTC_DateStruct.RTC_Year,
                RTC_DateStruct.RTC_Month,RTC_DateStruct.RTC_Date,RTC_DateStruct.RTC_WeekDay);
                //获取时间
                RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);
                printf("时间:%d:%d:%d\r\n",RTC_TimeStruct.RTC_Hours,
                RTC_TimeStruct.RTC_Minutes,RTC_TimeStruct.RTC_Seconds);
                delay_s(1);
        }
}

使用特权

评论回复
16
过期的塔头|  楼主 | 2024-2-27 19:32 | 只看该作者
RTC_ALARM
#include "rtc.h"

#define  BKP_DR  0x2162


void Rtc_Tim_Init(void)
{

        RTC_InitTypeDef  RTC_InitStruct;
        RTC_TimeTypeDef  RTC_TimeStruct;
        RTC_DateTypeDef  RTC_DateStruct;
       
        //1、使能PWR时钟,与电源寄存器有关
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
        //2、使能后备寄存器访问,是一种掉电保存数据的寄存器  
        PWR_BackupAccessCmd(ENABLE);
       
        //判断后备寄存器的值
        if(RTC_ReadBackupRegister(RTC_BKP_DR0) != BKP_DR)
        {
                //3、配置RTC时钟源,使能RTC时钟:
                RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
                RCC_RTCCLKCmd(ENABLE);
                //如果使用LSE,要打开LSE:
                RCC_LSEConfig(RCC_LSE_ON);
                //延时一段时间,等待时钟源稳定
                delay_ms(50);
               
                RTC_InitStruct.RTC_HourFormat        = RTC_HourFormat_24;        //24小时制
                RTC_InitStruct.RTC_AsynchPrediv        = 0x7F;                                        //异步分频 128分频
                RTC_InitStruct.RTC_SynchPrediv        = 0xFF;                                        //同频分频 255分频
                //4、初始化RTC(同步/异步分频系数和时钟格式):
                RTC_Init(&RTC_InitStruct);


                RTC_TimeStruct.RTC_H12                = RTC_H12_PM;                //下午 24小时制,可写可不写
                RTC_TimeStruct.RTC_Hours        = 15;                                //小时
                RTC_TimeStruct.RTC_Minutes        = 30;                                //分
                RTC_TimeStruct.RTC_Seconds        = 10;                                //ADC+
                RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);       
               
                RTC_DateStruct.RTC_Year                   = 21;                                        //年份
                RTC_DateStruct.RTC_Month        = 11;                                        //月份
                RTC_DateStruct.RTC_Date                = 16;                                        //日
                RTC_DateStruct.RTC_WeekDay  = RTC_Weekday_Tuesday;        //星期二
                RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
       
                //将值写入后备寄存器
                RTC_WriteBackupRegister(RTC_BKP_DR0, BKP_DR);
       
        }
}

//闹钟A初始化
void RTC_Alarm_AInit(void)
{
        RTC_AlarmTypeDef  RTC_AlarmStruct;
        RTC_TimeTypeDef   RTC_AlarmTime;
        EXTI_InitTypeDef  EXTI_InitStruct;
        NVIC_InitTypeDef  NVIC_InitStruct;
       
       
        //关闭闹钟:
        RTC_AlarmCmd(RTC_Alarm_A,DISABLE);
       
        RTC_AlarmTime.RTC_H12                = RTC_H12_PM;                //下午 24小时制,可写可不写
        RTC_AlarmTime.RTC_Hours                = 15;                                //小时
        RTC_AlarmTime.RTC_Minutes        = 30;                                //分
        RTC_AlarmTime.RTC_Seconds        = 30;                                //ADC+
       
       
        RTC_AlarmStruct.RTC_AlarmTime                        = RTC_AlarmTime;                                //设置时间
        RTC_AlarmStruct.RTC_AlarmMask                        = RTC_AlarmMask_None;                        //无掩码,按实际设置的时间响应闹钟
        RTC_AlarmStruct.RTC_AlarmDateWeekDaySel        = RTC_AlarmDateWeekDaySel_Date; //按日期响应闹钟
        RTC_AlarmStruct.RTC_AlarmDateWeekDay        = 16;                                                        //16号
        //配置闹钟参数:
        RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStruct);
       
        //开启闹钟:
        RTC_AlarmCmd(RTC_Alarm_A,ENABLE);
        //开启配置闹钟中断:
        RTC_ITConfig(RTC_IT_ALRA, ENABLE);
       
        EXTI_InitStruct.EXTI_Line        = EXTI_Line17;                        //中断线17
        EXTI_InitStruct.EXTI_Mode        = EXTI_Mode_Interrupt;         //中断模式
        EXTI_InitStruct.EXTI_Trigger= EXTI_Trigger_Rising;        //上升沿触发
        EXTI_InitStruct.EXTI_LineCmd= ENABLE;                                //中断线使能
        //初始化线上中断,设置触发条件等。
    EXTI_Init(&EXTI_InitStruct);
       
        NVIC_InitStruct.NVIC_IRQChannel                                                = RTC_Alarm_IRQn;//中断通道,中断通道在stm32f4xx.h文件当中查找
        NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority        = 2;                 //抢占优先级                       
        NVIC_InitStruct.NVIC_IRQChannelSubPriority                        = 2;                 //响应优先级
        NVIC_InitStruct.NVIC_IRQChannelCmd                                        = ENABLE;         //使能通道
        //配置中断分组(NVIC),并使能中断。
    NVIC_Init(&NVIC_InitStruct);       

}
//闹钟B初始化
void RTC_Alarm_BInit(void)
{
        RTC_AlarmTypeDef  RTC_AlarmStruct;
        RTC_TimeTypeDef   RTC_AlarmTime;
        EXTI_InitTypeDef  EXTI_InitStruct;
        NVIC_InitTypeDef  NVIC_InitStruct;
       
       
        //关闭闹钟:
        RTC_AlarmCmd(RTC_Alarm_B,DISABLE);
       
        RTC_AlarmTime.RTC_H12                = RTC_H12_PM;                //下午 24小时制,可写可不写
        RTC_AlarmTime.RTC_Hours                = 15;                                //小时
        RTC_AlarmTime.RTC_Minutes        = 30;                                //分
        RTC_AlarmTime.RTC_Seconds        = 40;                                //ADC+
       
       
        RTC_AlarmStruct.RTC_AlarmTime                        = RTC_AlarmTime;                                //设置时间
        RTC_AlarmStruct.RTC_AlarmMask                        = RTC_AlarmMask_None;                        //无掩码,按实际设置的时间响应闹钟
        RTC_AlarmStruct.RTC_AlarmDateWeekDaySel        = RTC_AlarmDateWeekDaySel_Date; //按日期响应闹钟
        RTC_AlarmStruct.RTC_AlarmDateWeekDay        = 16;                                                        //16号
        //配置闹钟参数:
        RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_B, &RTC_AlarmStruct);
       
        //开启闹钟:
        RTC_AlarmCmd(RTC_Alarm_B,ENABLE);
        //开启配置闹钟中断:
        RTC_ITConfig(RTC_IT_ALRB, ENABLE);
       
        EXTI_InitStruct.EXTI_Line        = EXTI_Line17;                        //中断线17
        EXTI_InitStruct.EXTI_Mode        = EXTI_Mode_Interrupt;         //中断模式
        EXTI_InitStruct.EXTI_Trigger= EXTI_Trigger_Rising;        //上升沿触发
        EXTI_InitStruct.EXTI_LineCmd= ENABLE;                                //中断线使能
        //初始化线上中断,设置触发条件等。
    EXTI_Init(&EXTI_InitStruct);
       
        NVIC_InitStruct.NVIC_IRQChannel                                                = RTC_Alarm_IRQn;//中断通道,中断通道在stm32f4xx.h文件当中查找
        NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority        = 2;                 //抢占优先级                       
        NVIC_InitStruct.NVIC_IRQChannelSubPriority                        = 2;                 //响应优先级
        NVIC_InitStruct.NVIC_IRQChannelCmd                                        = ENABLE;         //使能通道
        //配置中断分组(NVIC),并使能中断。
    NVIC_Init(&NVIC_InitStruct);       

}
//闹钟中断服务函数
void RTC_Alarm_IRQHandler(void)
{
        if(EXTI_GetITStatus(EXTI_Line17) == SET)
        {
               
                //判断是否为闹钟A
                if(RTC_GetFlagStatus(RTC_FLAG_ALRAF) == SET)
                {
                        LED0_ON;
                }
                //判断是否为闹钟B
                if(RTC_GetFlagStatus(RTC_FLAG_ALRBF) == SET)
                {
                        LED0_OFF;
                        LED1_ON;
                }
               
                RTC_ClearFlag(RTC_FLAG_ALRAF);
                RTC_ClearFlag(RTC_FLAG_ALRBF);
               
        }
        //清空标志位
        EXTI_ClearITPendingBit(EXTI_Line17);
}

使用特权

评论回复
17
过期的塔头|  楼主 | 2024-2-27 19:32 | 只看该作者
#ifndef __RTC_H
#define __RTC_H

#include "stm32f4xx.h"
#include "delay.h"
#include "led.h"

void Rtc_Tim_Init(void);
void RTC_Alarm_AInit(void);
void RTC_Alarm_BInit(void);
#endif

使用特权

评论回复
18
过期的塔头|  楼主 | 2024-2-27 19:32 | 只看该作者
#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"
#include "usart.h"
#include "sys.h"
#include "dht11.h"
#include "infrared.h"
#include "iwdg.h"
#include "rtc.h"


u8  buffer[64] = {0};
u8  rx_buffer[64] = {0};
u8  count = 0, rx_i = 0;
u8  rx_flag = 0; //接受标志位,rx_flag = 表示数据帧完毕


void USART1_IRQHandler(void)
{
       


        //判断接收标志位是否为1
        if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART1, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART1);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
               
                }
               
        }
}




void USART2_IRQHandler(void)
{
       
        u8 data;

        //判断接收标志位是否为1
        if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART2, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART2);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
                }
               
        }


}


void USART3_IRQHandler(void)
{
       
        u8 data;

        //判断接收标志位是否为1
        if(USART_GetITStatus(USART3, USART_IT_RXNE) == SET)
        {
                //清空接受标志位
                USART_ClearITPendingBit(USART3, USART_IT_RXNE);       
                //接受数据
                buffer[count++] = USART_ReceiveData(USART3);
                //判断数据是否为':',如果是':'数据帧结束
                if(buffer[count-1] == ':')
                {
                        //数据赋值到rx_buffer,并过滤帧尾
                        for(rx_i=0; rx_i<(count-1); rx_i++)
                        {
                                rx_buffer[rx_i] = buffer[rx_i];
                        }
               
                        //清空数组
                        memset(buffer, 0, sizeof(buffer));
                       
                        //标志位置1
                        rx_flag = 1;
                        //下一帧数据从buffer[0]开始接受
                        count = 0;
                                       
                }
               
        }


}





int main(void)
{
        RTC_TimeTypeDef  RTC_TimeStruct;
        RTC_DateTypeDef  RTC_DateStruct;       
       
       
        //设置NVIC分组(一个工程只能设置一个分组)
        //第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        Led_Init();
        Delay_Init();

        Usart1_Init(115200);

        Rtc_Tim_Init();
        RTC_Alarm_AInit();
        RTC_Alarm_BInit();
       
        while(1)
        {
                //获取日期
                RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
                printf("日期:%d-%d-%d 星期:%d\r\n",RTC_DateStruct.RTC_Year,
                RTC_DateStruct.RTC_Month,RTC_DateStruct.RTC_Date,RTC_DateStruct.RTC_WeekDay);
                //获取时间
                RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);
                printf("时间:%d:%d:%d\r\n",RTC_TimeStruct.RTC_Hours,
                RTC_TimeStruct.RTC_Minutes,RTC_TimeStruct.RTC_Seconds);
                delay_s(1);
        }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

78

主题

923

帖子

0

粉丝