stm32独立看门狗和rtc闹钟
- 独立看门狗
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;
四、技术应用
- 看门狗
- 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闹钟相关推荐
- cubeIDE开发, stm32独立看门狗IWDG的CubeMX配置及HAL库底层实现分析
一.STM32 的IWDG简介 2.1 看门狗原理 看门狗本质上就是一种计数器,和我们现实生活中一炷香现象.沙漏现象等是同理的,计数器一般有两种做法,一种是递增,超过固定阀值报警:一种是递减,通常值降 ...
- 【STM32】stm32独立看门狗(IWDG)
stm32独立看门狗(IWDG) 0x01 IWDG简介 0x02 IWDG主要性能 0x03 IWDG寄存器配置 0x01 IWDG简介 STM32F10xxx内置两个看门狗,(独立看门狗和窗口看门 ...
- STM32 独立看门狗实验
一.STM32 独立看门狗简介 STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效.这里需要注意独立看门狗的时钟是一个内部 RC 时钟,所以并不是准确的 ...
- STM32—独立看门狗(IWDG)
STM32-独立看门狗(IWDG) 独立看门狗(IWDG) STM32-独立看门狗(IWDG) 独立看门狗(IWDG) IWDG 简介 IWDG 功能框图剖析 独立看门狗时钟 计数器 重装载寄存器 键 ...
- STM32独立看门狗实验
一 为什么需要看门狗? 在MCU微型计算机系统中,MCU运行程序很容易受到外界电磁场的干扰,从而造成程序运行错误甚至发生跑飞现象,从而陷入死循环,程序的正常运行被打乱,从而造成不可预料的严重后果,于是 ...
- STM32独立看门狗(宠物狗)
一.前言 ······在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系 ...
- stm32 独立看门狗和窗口看门狗区别
原文地址https://www.cnblogs.com/pertor/p/9483445.html 一.使用调条件 二.特点对比 三.手册介绍 [注]图中的WDGTB为3表示2^3=8,表示8分频,最 ...
- stm32 独立看门狗学习
STM32F10xxx内置两个看门狗,提供了更高的安全性.时间的精确性和使用的灵活性.两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障. 独立看门狗(IWDG)由专用的低速 ...
- STM32 - 独立看门狗IWDG - 使用注意事项+代码
一.包含头文件 #include "stm32f10x_iwdg.h" 二.设置 独立看门狗 的超时时间 1.配置代码 /** 设置 IWDG 的超时时间* Tout(ms) = ...
最新文章
- SQL Server 日期和时间相关的数据类型有两种
- 是小厂全栈好,还是大厂专业工程师好?
- 构建乘积数组(剑指offer)
- hadoop-hdfs-存储模型-架构模型-角色介绍
- 【CF 736C】Ostap and Tree,树形DP
- Quartz任务调度器
- 关于null对象使用print方法打印问题总结,null+123打印结果是null123还是123?
- 项目是如何完成的(一)
- java 基础 1 final关键字
- Druid-1.1.12.jar下载 (链接下载+使用)
- 通过docker安装nexus3
- MagicDraw建模显示中文问题
- 003-Java技术体系
- 【光学】Matlab模拟相互垂直的光波叠加
- 惊艳全网的裸眼3D巨屏,竟是一场视觉骗局?
- Xcode6使用iOS7模拟器调试的方法
- 下属被阿里挖角的那个早晨,我开始想念周鸿祎!
- 视频教程-【吴刚大讲堂】电商品牌文案设计方法-电子商务
- c语言字符串的小程序,微信小程序字符串转换为数字如何实现
- 微信小程序 环形进度条_微信小程序实现圆形进度条动画
热门文章
- 视频画中画随心变 浮空影视播放器体会
- Android修改context.getResources().getDisplayMetrics()对应多分辨率风险点
- TP5日志记录与异常处理
- IBM组织结构图相关
- LeetCode 925 Long Pressed Name
- word里面如何输入2分之1的这种分数结构
- 七、Openpyxl工作表对象的属性和方法-5(打印设置1/2)
- python+django英语单词学习网站vue
- 多目标优化算法:基于非支配排序的瞪羚优化算法(Non-Dominated Sorting Gazelle Optimization Algorithm,NSGOA)
- 纺织行业MES系统解决方案