当前位置: 首页 > news >正文

16-看门狗和RTC

一、独立看门狗

1、独立看门狗概述

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

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

2、STM32独立看门狗

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

        STM32F4 的独立看门狗由内部专门的 LSIRC32Khz 低速时钟 (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();

如下例子是防止程序重启的代码,应用到看门狗的作用

看门狗例子源码:

https://download.csdn.net/download/m0_63622771/90841876

4、效果分析

没有喂狗,系统重启

int main(void)
{int ret;u8 data[5];//中断的优先级分组,一个项目只能设置一次//中断优先级分为第二组,抢占级范围:0~3  响应:0~3NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);Delay_Init();//初始化后GPIOF_ODR默认为低电平,所以灯亮Led_Init();Usart1_Init(115200);Tim3_NoISR_Init(50000-1);Dht11_Init();//下面我们设置了一条狗,使其每两秒内要喂狗,不然会让程序重启。Iwdg_Init();//如果打印这一句话,说明系统重启。printf("iwdg test\r\n");while(1){    ret = Dht11_Data(data);if(ret == 0){//让CPU打印数据printf("湿度:%d.%d\r\n", data[0], data[1]);printf("温度:%d.%d\r\n", data[2], data[3]);}delay_s(1);delay_ms(500);delay_ms(400);}return 0;
}

下面是添加喂狗的情况,系统会正常运行

int main(void)
{int ret;u8 data[5];//中断的优先级分组,一个项目只能设置一次//中断优先级分为第二组,抢占级范围:0~3  响应:0~3NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);Delay_Init();//初始化后GPIOF_ODR默认为低电平,所以灯亮Led_Init();Usart1_Init(115200);Tim3_NoISR_Init(50000-1);Dht11_Init();Iwdg_Init();//如果打印这一句话,说明系统重启。printf("iwdg test\r\n");while(1){    ret = Dht11_Data(data);if(ret == 0){//让CPU打印数据printf("湿度:%d.%d\r\n", data[0], data[1]);printf("温度:%d.%d\r\n", data[2], data[3]);}delay_s(1);delay_ms(500);delay_ms(400);//保证上面程序运行的时间少于2S//应用程序喂狗:IWDG_ReloadCounter();}return 0;
}

注意:真正看门狗喂程序不应该放主函数当中,因为主函数运行的时间不可控制,而是应该将喂狗程序放在一个基本定时器当中,每隔固定时间进行喂狗。

例如下面使用定时器7,每隔1.8s喂狗源码:

二、RTC(时钟)

1、RTC概述

RTC(Real Time Clock,实时时钟)是一种专门用于记录时间的设备或模块,通常作为计算机系统中的一部分存在。其本质是一个计数器,以秒为单位进行计数,可以提供精确的时间信息,并且具有以下特性:

提供时间信息: RTC能够提供当前的时间,通常以秒钟数的形式表示,但也可以提供更精细的时间分辨率,如毫秒或微秒级别。

持久性: RTC具有持久性,即在MCU(Microcontroller Unit,微控制器单元)掉电后(主电源)仍然能够继续运行(依靠纽扣电池,也就说纽扣电池给RTC进行供电),因此能够确保时间信息的连续性和准确性。

低功耗: RTC通常具有低功耗特性,以确保在长时间内使用时消耗的能量较少,这对于依靠电池供电的应用尤为重要,因为它可以延长电池的使用寿命。

总的来说,RTC在许多应用中扮演着关键的角色,特别是在需要准确记录时间并且需要在掉电后继续运行的场景下,如数据记录、日志记录、定时任务等。

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

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

STM32F4 的 RTC 时钟源( RTCCLK )通过时 钟控制器,可以从 LSE 时钟、 LSI 时钟以及 HSE 时钟三者中选择(通过 RCC_BDCR 寄存器选择)。一般我们选择 LSE ,即外部 32.768Khz 晶振作为时钟源 (RTCCLK) ,而 RTC 时钟核心,要求提供 1Hz 的时钟 ,所以,我们要设置 RTC 的可编程预分配器。STM32F4 的可编程预分配器(RTC_PRER)分为 2 个部分:

1, 一个通过 RTC_PRER 寄存器的 PREDIV_A 位配置的 7 位异步预分频器。

异步预分频需要设置为:0x7f (127则是128分频)

2, 一个通过 RTC_PRER 寄存器的 PREDIV_S 位配置的 15 位同步预分频器。

同步预分频需要设置为:0xFF (255则是256分频)
BCD码
BCD码(Binary-Coded Decimal)是一种用二进制编码表示十进制数的编码方式1.BCD码的分类:
有权码‌:如8421码、2421码、5421码,每个二进制位有固定的权值。
‌无权码‌:如余3码、余3循环码、格雷码,每个编码中的1和0没有确切的权值。最常见的是8421码

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

纽扣电池供电电路,纽扣电池供电由PWR外设进行管理

纽扣电池实物图

纽扣电池电路图

2、RTC时间与日期配置流程

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

后备寄存器是一种掉电后可保存数据的寄存器。
uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR)//读后备寄存器
void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data)//写入后备寄存器

RTC日期时间例子源码:

3、RTC闹钟

STM32有两个闹钟,分别闹钟A与闹钟B.

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、开启配置闹钟中断:

    

     EXTI_Init();

     NVIC_Init();

RTC_ITConfig();

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

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

可通过下面函数判断是哪个闹钟发生响应

FlagStatus RTC_GetFlagStatus(uint32_t RTC_FLAG)//获取标志位

RTC闹钟例子:

https://download.csdn.net/download/m0_63622771/90842074

4、实验效果

时间设置

        RTC_TimeStruct.RTC_H12        = RTC_H12_PM; //下午,在24小时制时,这个参数是无用RTC_TimeStruct.RTC_Hours    = 9; //时RTC_TimeStruct.RTC_Minutes    = 16; //分RTC_TimeStruct.RTC_Seconds    = 10; //秒//RTC_Format_BIN,写10进制,硬件自动转换为2进制进行存储RTC_SetTime (RTC_Format_BIN, &RTC_TimeStruct);

闹钟A的设置时间1后

    //闹钟时间设置RTC_AlarmTime.RTC_H12        = RTC_H12_AM; //上午,在24小时制时,这个参数是无用RTC_AlarmTime.RTC_Hours        = 9; //时RTC_AlarmTime.RTC_Minutes    = 17; //分RTC_AlarmTime.RTC_Seconds    = 10; //秒

5、掩码位理解

掩码位:对某个位屏蔽,可以理解为忽略这个操作
在代码中:RTC_AlarmStruct.RTC_AlarmMask            = RTC_AlarmMask_Hours;  //表示闹钟A有小时掩码位
如设置的时间:9:55:10,接下来,忽略了小时,也就每隔小时的55分10秒都会响应响应,一天有24个闹钟。

三、函数说明

//1
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);
函数功能:是否使能 IWDG_PR and IWDG_RLR寄存器
返回值:无
uint16_t IWDG_WriteAccess:是否使能
IWDG_WriteAccess_Enable 
IWDG_WriteAccess_Disable//2
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 //3
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource)
void IWDG_SetReload(uint16_t Reload)
函数功能:设置重载值
返回值:无
uint16_t Reload:重载值寄存器的值,范围:0~0xFFF//4
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_Div30
RCC_RTCCLKSource_HSE_Div31//5
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;//6
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; //7
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;//8
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:闹钟BRTC_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; 

http://www.xdnf.cn/news/460189.html

相关文章:

  • 高防服务器流量“清洗”什么意思
  • 如何在 AWS 上构建支持 AVIF 的前端图片优化方案
  • 2025认证杯数学建模C题思路+代码+模型:化工厂生产流程的预测和控制
  • MH22D3开发高级UI应用,适配arm2d驱动
  • Linux线程互斥锁
  • idea启动报错:java: 警告: 源发行版 11 需要目标发行版 11(亲测解决)
  • OpenHarmony 5.1.0 Release目录结构详细解析(3级目录)
  • 以项目的方式学QT开发(三)
  • WooCommerce短代码Shortcodes使用方法
  • Tomcat多应用部署与静态资源路径问题全解指南
  • Python高级进阶:Vim与Vi使用指南
  • 【高斯拟合】不用库手写高斯拟合算法:从最小二乘到拟合参数推导
  • window 显示驱动开发-报告图形内存(四)
  • 国内MCP服务平台推荐 AIbase推出MCP服务器客户端商店
  • PromptIDE提示词开发工具支持定向优化啦
  • Dify与n8n全面对比指南:AI应用开发与工作流自动化平台选择【2025最新】
  • Makefile 在 Go 项目中的实践
  • django中用 InforSuite RDS 替代memcache
  • 【Hadoop】伪分布式安装
  • Pycharm IDEA加载大文件时报错:The file size exceeds configured limit
  • 鸿蒙OSUniApp 实现的表单验证与提交功能#三方框架 #Uniapp
  • NuGet程序包还原失败
  • 【论文阅读】BEVFormer
  • 使用 163 邮箱实现 Spring Boot 邮箱验证码登录
  • 【问题记录】08 MAC电脑,安装HP打印机驱动,提示:此更新需要macOS版本15.0或更低版本
  • 如何使用WordPress SEO检查器进行实时内容分析
  • 数据结构 -- 顺序查找和折半查找
  • Vue 3 中 watch 的使用与深入理解
  • SpringBoot集成Redis:实现分布式锁(redistemplate,lua,redisson)
  • 《深入理解AXI4协议:从入门到实践》-- 第十篇:AXI5与CHI协议前瞻