• 独立看门狗

1、独立看门狗概述

在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”(watchdog) 。

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

2、STM32独立看门狗

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

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

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

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由钮扣电池进行独立供电

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();

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();

三、函数说明

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

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;

四、技术应用

  1. 看门狗

  1. RTC

小天才手表

公交刷卡机

看门狗

#include "iwdg.h"void Iwdg_Init(void)
{//1、 取消寄存器写保护:IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//2、设置独立看门狗的预分频系数,确定时钟; 在32KHZ,分频128,得频率:250HZIWDG_SetPrescaler(IWDG_Prescaler_128);//3、设置看门狗重装载值,确定溢出时间:2SIWDG_SetReload(500);//4、使能看门狗IWDG_Enable();//应用程序喂狗:IWDG_ReloadCounter();
}
#ifndef __IWDG_H
#define __IWDG_H#include "stm32f4xx.h"void Iwdg_Init(void);#endif
#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)
{//判断接收标志位是否为1if(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));//标志位置1rx_flag = 1;//下一帧数据从buffer[0]开始接受count = 0; }}
}void USART2_IRQHandler(void)
{u8 data;//判断接收标志位是否为1if(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));//标志位置1rx_flag = 1;//下一帧数据从buffer[0]开始接受count = 0; }}}void USART3_IRQHandler(void)
{u8 data;//判断接收标志位是否为1if(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));//标志位置1rx_flag = 1;//下一帧数据从buffer[0]开始接受count = 0; }}}int main(void)
{int ret;u8 data[5] = {0};//设置NVIC分组(一个工程只能设置一个分组) //第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);Led_Init();Delay_Init();Tim7_Init(); //初始化定时器7Usart1_Init(115200);Iwdg_Init();printf("iwdg test\r\n");while(1){if(GPIO_ReadInputDataBit(GPIOA,  GPIO_Pin_0) == Bit_RESET){//延时消抖 20msdelay_ms(20); //判断按键是否按下if(GPIO_ReadInputDataBit(GPIOA,  GPIO_Pin_0) == Bit_RESET){printf("key up\r\n");//往一个非法地址写入一个值,模拟程序跑飞*((unsigned int *)0xC0000000) = 0x666;}}       //这里的循环相当应用程序的时间delay_s(4);}
}

RTC_TIM

#include "rtc.h"#define  BKP_DR  0x2162void 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);}
}
#ifndef __RTC_H
#define __RTC_H#include "stm32f4xx.h"
#include "delay.h"void Rtc_Tim_Init(void);#endif
#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)
{//判断接收标志位是否为1if(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));//标志位置1rx_flag = 1;//下一帧数据从buffer[0]开始接受count = 0; }}
}void USART2_IRQHandler(void)
{u8 data;//判断接收标志位是否为1if(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));//标志位置1rx_flag = 1;//下一帧数据从buffer[0]开始接受count = 0; }}}void USART3_IRQHandler(void)
{u8 data;//判断接收标志位是否为1if(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));//标志位置1rx_flag = 1;//下一帧数据从buffer[0]开始接受count = 0; }}}int main(void)
{RTC_TimeTypeDef  RTC_TimeStruct;RTC_DateTypeDef  RTC_DateStruct;   //设置NVIC分组(一个工程只能设置一个分组) //第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3NVIC_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);}
}

RTC_ALARM

#include "rtc.h"#define  BKP_DR  0x2162void 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;         //中断线17EXTI_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;         //中断线17EXTI_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){//判断是否为闹钟Aif(RTC_GetFlagStatus(RTC_FLAG_ALRAF) == SET){LED0_ON;}//判断是否为闹钟Bif(RTC_GetFlagStatus(RTC_FLAG_ALRBF) == SET){LED0_OFF;LED1_ON;}RTC_ClearFlag(RTC_FLAG_ALRAF);RTC_ClearFlag(RTC_FLAG_ALRBF);}//清空标志位EXTI_ClearITPendingBit(EXTI_Line17);
}
#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
#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)
{//判断接收标志位是否为1if(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));//标志位置1rx_flag = 1;//下一帧数据从buffer[0]开始接受count = 0; }}
}void USART2_IRQHandler(void)
{u8 data;//判断接收标志位是否为1if(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));//标志位置1rx_flag = 1;//下一帧数据从buffer[0]开始接受count = 0; }}}void USART3_IRQHandler(void)
{u8 data;//判断接收标志位是否为1if(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));//标志位置1rx_flag = 1;//下一帧数据从buffer[0]开始接受count = 0; }}}int main(void)
{RTC_TimeTypeDef  RTC_TimeStruct;RTC_DateTypeDef  RTC_DateStruct;   //设置NVIC分组(一个工程只能设置一个分组) //第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3NVIC_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);}
}

stm32独立看门狗和rtc闹钟相关推荐

  1. cubeIDE开发, stm32独立看门狗IWDG的CubeMX配置及HAL库底层实现分析

    一.STM32 的IWDG简介 2.1 看门狗原理 看门狗本质上就是一种计数器,和我们现实生活中一炷香现象.沙漏现象等是同理的,计数器一般有两种做法,一种是递增,超过固定阀值报警:一种是递减,通常值降 ...

  2. 【STM32】stm32独立看门狗(IWDG)

    stm32独立看门狗(IWDG) 0x01 IWDG简介 0x02 IWDG主要性能 0x03 IWDG寄存器配置 0x01 IWDG简介 STM32F10xxx内置两个看门狗,(独立看门狗和窗口看门 ...

  3. STM32 独立看门狗实验

    一.STM32 独立看门狗简介 STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效.这里需要注意独立看门狗的时钟是一个内部 RC 时钟,所以并不是准确的 ...

  4. STM32—独立看门狗(IWDG)

    STM32-独立看门狗(IWDG) 独立看门狗(IWDG) STM32-独立看门狗(IWDG) 独立看门狗(IWDG) IWDG 简介 IWDG 功能框图剖析 独立看门狗时钟 计数器 重装载寄存器 键 ...

  5. STM32独立看门狗实验

    一 为什么需要看门狗? 在MCU微型计算机系统中,MCU运行程序很容易受到外界电磁场的干扰,从而造成程序运行错误甚至发生跑飞现象,从而陷入死循环,程序的正常运行被打乱,从而造成不可预料的严重后果,于是 ...

  6. STM32独立看门狗(宠物狗)

    一.前言 ······在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系 ...

  7. stm32 独立看门狗和窗口看门狗区别

    原文地址https://www.cnblogs.com/pertor/p/9483445.html 一.使用调条件 二.特点对比 三.手册介绍 [注]图中的WDGTB为3表示2^3=8,表示8分频,最 ...

  8. stm32 独立看门狗学习

    STM32F10xxx内置两个看门狗,提供了更高的安全性.时间的精确性和使用的灵活性.两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障. 独立看门狗(IWDG)由专用的低速 ...

  9. STM32 - 独立看门狗IWDG - 使用注意事项+代码

    一.包含头文件 #include "stm32f10x_iwdg.h" 二.设置 独立看门狗 的超时时间 1.配置代码 /** 设置 IWDG 的超时时间* Tout(ms) = ...

最新文章

  1. SQL Server 日期和时间相关的数据类型有两种
  2. 是小厂全栈好,还是大厂专业工程师好?
  3. 构建乘积数组(剑指offer)
  4. hadoop-hdfs-存储模型-架构模型-角色介绍
  5. 【CF 736C】Ostap and Tree,树形DP
  6. Quartz任务调度器
  7. 关于null对象使用print方法打印问题总结,null+123打印结果是null123还是123?
  8. 项目是如何完成的(一)
  9. java 基础 1 final关键字
  10. Druid-1.1.12.jar下载 (链接下载+使用)
  11. 通过docker安装nexus3
  12. MagicDraw建模显示中文问题
  13. 003-Java技术体系
  14. 【光学】Matlab模拟相互垂直的光波叠加
  15. 惊艳全网的裸眼3D巨屏,竟是一场视觉骗局?
  16. Xcode6使用iOS7模拟器调试的方法
  17. 下属被阿里挖角的那个早晨,我开始想念周鸿祎!
  18. 视频教程-【吴刚大讲堂】电商品牌文案设计方法-电子商务
  19. c语言字符串的小程序,微信小程序字符串转换为数字如何实现
  20. 微信小程序 环形进度条_微信小程序实现圆形进度条动画

热门文章

  1. 视频画中画随心变 浮空影视播放器体会
  2. Android修改context.getResources().getDisplayMetrics()对应多分辨率风险点
  3. TP5日志记录与异常处理
  4. IBM组织结构图相关
  5. LeetCode 925 Long Pressed Name
  6. word里面如何输入2分之1的这种分数结构
  7. 七、Openpyxl工作表对象的属性和方法-5(打印设置1/2)
  8. python+django英语单词学习网站vue
  9. 多目标优化算法:基于非支配排序的瞪羚优化算法(Non-Dominated Sorting Gazelle Optimization Algorithm,NSGOA)
  10. 纺织行业MES系统解决方案