STM32个人笔记-看门狗

目录

看门狗

独立看门狗

功能框图

IWDG配置

测试环节

窗口看门狗

功能框图

WWDG_CR控制寄存器

WWDG_CFG配置寄存器

WWDG_SR状态寄存器

WWDG配置

测试环节

IWDG和WWDG的区别

使用条件对比

特点对比

相同点

不同点

两者区别


看门狗

早期的MCU没有看门狗,就容易引起有些产品死机了不能重启工作。为了避免这个问题,后期的MCU在内部继承了看门狗的功能。看门狗功能由VDD电压域供电,在停止模式和待机模式下仍能工作。

现如今有两种看门狗,应用不同领域。两种看门狗:独立看门狗窗口看门狗

RLR 是重装载寄存器,用来设置独立看门狗的计数器的值。

TR 是窗口看门狗的计数器的值,由用户独立设置, WR 是窗口看门狗的上窗口值,由用户独立设置。

独立看门狗中,待计数器递减到0前不喂狗(刷新数值),就会产生复位。 

窗口看门狗中,在TR与WR期间喂狗(刷新数值)会产生复位,在WR递减到0x40前不喂狗(刷新数值),就会产生复位。所以窗口看门狗喂狗时间不能过早也不能过晚。

独立看门狗

功能框图

IWDG的时钟由独立的RC振荡器LSI提供,即便主时钟发生故障时仍然保持工作状态。LSI频率一般在30~60kHz之间,根据温度和工作场合会有一定的漂移,一般取40kHz,所以IWDG的定时时间不一定非常准确,只适用于对时间精度要求比较低的场合。

递减计数器的时钟由LSI经过8-bit prescaler(8位预分频器)而来,可以通过IWDG_PR预分频器寄存器设置分频因子。

递减计数器是12位,最大值为0xfff,当减到0时产生一个复位信号:IWDG_RESET。

重装载寄存器是12位,里面存放着要刷新到计数器的值,这个值决定着IWDG的溢出时间。

IWDG_KR键值寄存器为只写寄存器,写入键值会起键值作用。

键值键值作用
0xAAAA把IWDG_PLR的值重装载到递减计数器
0x5555IWDG_PR和IWDG_PLR这两个寄存器可写
0xCCCC启动IWDG

IWDG_PR 和 IWDG_RLR 寄存器具有写保护功能。要修改这两个寄存器的值,必须先向 IWDG_KR 寄存器中写入0x5555。 将其他值写入 IWDG_KR 寄存器将会打乱操作顺序,寄存器将重新被保护,必须先向 IWDG_KR 寄存器中写入0x5555后才能写0xAAAA。

IWDG 在一旦启用,就不能再被关闭!

IWDG配置

溢出时间:625/(40k/64) =1s。

IWDG_HandleTypeDef hiwdg;

void MX_IWDG_Init(void)
{
    hiwdg.Instance 			= IWDG;
    hiwdg.Init.Prescaler 	= IWDG_PRESCALER_64;
    hiwdg.Init.Reload 		= 625;

    if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
    {
        Error_Handler();
    }
}

测试环节

0.5s喂狗一次,时间不宜太晚。

/**
  * @brief  守护任务循环入口
  * @note   None
  * @param  argument : NULL
  * @retval None
  */
void StartGuardTask(void *argument)
{ 
    for(;;)
    {
		HAL_IWDG_Refresh(&hiwdg);
        osDelay(500);
    }
}

窗口看门狗

之所以称为窗口,是因为其喂狗时间是一个有上下限的范围内,可以通过设定时间寄存器,设定其上限时间和下限时间:喂狗时间不能过早也不能过晚。

功能框图

WWDG时钟来自PCLK1,PCLK1最大是36M,由RCC时钟控制器开启。

递减计数器时钟由CK计时器时钟(PCLK1/4096,手册规定)经过预分频器分频得到(分频系数由WWDG_CFG:WDGTB0/1配置),所以计数器的时钟CNT_CK = PCLK1/4096/(2^WDGTB)。递减一个数为1/CNT_CK。

窗口看门狗的上限窗口就是配置寄存器WWDG_CFG:W[6:0],下限窗口是固定的0x40。当窗口看门狗的计数器在上限窗口之外,或是在下限窗口之外都会产生复位。

WWDG_CR控制寄存器

WWDG_CR:WDGA为第8位,是看门狗的激活位。该位由软件置1,以启动看门狗。注意该位一旦设置,就只能在硬件复位后才拿清零了。

WWDG_CR:T[6:0]:看门狗的计数器值。

WWDG_CFG配置寄存器

配置寄存器WWDG_CFG:EWI为提前唤醒中断位,也就是在快要产生复位的前一段时间(T[6:0]=0X40) 来提醒我们,需要进行喂狗了,否则将复位。因此,我们一般用该位来设置中断,当窗口看门狗的计数器值减到 0X40 的时候,如果该位设置,并开启了中断,则会产生中断,我们可以在中断里面向 WWDG_CR 重新写入计数器的值,来达到喂狗的目的。注意这里在进入中断后, 必须在不大于 1 个窗口看门狗计数周期的时间(在 PCLK1 频率为 36M 且 WDGTB 为 0 的条件下,该时间为 113us)内重新写 WWDG_CR,否则,看门狗将产生复位。

配置寄存器WWDG_CFG:WDGTB[1:0]为计数器设定时钟分频系数,确定这个计数器可以定时的时间范围,从而确定窗口的时间范围。

上限窗口由 WWDG_CFG:W[6:0] 设定,最大为0x7F,即127。最小为0x40,即64。所以取值范围为0x40~0x7F,即64~127。

WWDG_SR状态寄存器

只用到一个位,WWDG_SR:EWIF。用来记录当前是否有提前唤醒的标志。

当计数器值达到 40h 时,此位由硬件置 1。它必须通过软件写 0 来清除。对此位写 1 无效。 即使中断未被使能, 在计数器的值达到 0X40 的时候, 此位也会被置 1。

WWDG配置

WWDG_HandleTypeDef hwwdg;

void MX_WWDG_Init(void)
{
    hwwdg.Instance 			= WWDG;
    hwwdg.Init.Prescaler 	= WWDG_PRESCALER_8;
    hwwdg.Init.Window 		= 80;
    hwwdg.Init.Counter 		= 127;
    hwwdg.Init.EWIMode 		= WWDG_EWI_ENABLE;
    if (HAL_WWDG_Init(&hwwdg) != HAL_OK)
    {
        Error_Handler();
    }
}

void HAL_WWDG_MspInit(WWDG_HandleTypeDef *wwdgHandle)
{
    if (wwdgHandle->Instance == WWDG)
    {
        __HAL_RCC_WWDG_CLK_ENABLE();

        HAL_NVIC_SetPriority(WWDG_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(WWDG_IRQn);
    }
}

测试环节

// WWDG 中断服务程序,如果发生了此中断,表示程序已经出现了故障,
// 这是一个死前中断。在此中断服务程序中应该干最重要的事,
// 比如保存重要的数据等
void WWDG_IRQHandler(void)
{
	//WWDG 中断服务处理函数,用户代码在提前唤醒中断回调函数中添加
	HAL_WWDG_IRQHandler(&WWDG_Handle);
}

void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
{
	//比如黄灯亮
	//真正使用的时候,这里应该是做最重要的事情
}

void test(void)
{
	uint8_t wwdg_tr, wwdg_wr;
	
	初始化
	
	//检查窗口看门狗复位标志位
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET)
    {
        // 窗口看门狗复位了,可以做一些处理来判断
		// 比如红灯亮

        //清除复位标志位
        __HAL_RCC_CLEAR_RESET_FLAGS();
    }
    else
    {
        // 正常启动
		// 比如蓝灯亮
    }
	
	// 窗口值我们在初始化的时候设置成0X5F,这个值不会改变
    wwdg_wr = WWDG->CFR & 0X7F;
	
	while (1)
    {
		//-----------------------------------------------------
        // 这部分应该写需要被WWDG监控的程序,这段程序运行的时间决定了窗口值应该设置成多大。
        //-----------------------------------------------------
        // 计时器值,初始化成最大0X7F,当开启WWDG时候,这个值会不断减小
        // 当计数器的值大于窗口值时喂狗的话,会复位,当计数器减少到0X40
        // 还没有喂狗的话就非常非常危险了,计数器再减一次到了0X3F时就复位
        // 所以要当计数器的值在窗口值和0X40之间的时候喂狗,其中0X40是固定的。
        wwdg_tr = WWDG->CR & 0X7F;

        if (wwdg_tr == wwdg_wr)
        {
            // 喂狗,刷新递减计数器的值,设置成最大WDG_CNT=0X7F
			HAL_WWDG_Refresh(&hwwdg);
        }
    }
}

IWDG和WWDG的区别

使用条件对比

 

特点对比

相同点

不同点

两者区别

独立看门狗没有中断,窗口看门狗有中断。

独立看门狗有硬件软件之分,窗口看门狗只能软件控制。

独立看门狗只有下限,窗口看门狗有下限和上限。

独立看门狗是12位递减的,窗口看门狗是7位递减的。

独立看门狗是用的内部大约40kHz的RC振荡器,窗口看门狗是用的系统时钟APB1。

独立看门狗没有中断功能,只要在计数器减到0(下限)之前,重新装载计数器的值,就不会产生复位。

要注意看门狗和外接复位IC同时存在的情况,外部电路可能会阻止看门狗复位。

窗口看门狗有中断,这个中断的作用是在计数器达到下限0x40的时候,产生中断,让你喂狗。如果不喂狗,计数器的值变为0x3f时,将会产生系统复位。即便是喂狗,也该在中断里快速喂狗,要不时间长了计数器减1也会变成0x3f产生复位。

窗口看门狗还有一个上限值,只有计数器值在上限值和下限值之间才能装载计数器,否则就会产生系统复位。当上限值小于下限值,没有意义。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32是一款非常流行的嵌入式微控制器系列,它具有强大的性能和丰富的外设资源。在学习STM32时,掌握如何进行Flash读写是非常重要的。 Flash是一种非易失性存储器,可以用来存储程序代码和数据。在STM32中,Flash存储器通常用来存储应用程序代码。下面是一个简单的Flash读写程序的示例: 1.首先,我们需要包含适用于所使用的STM32型号的头文件。例如,对于STM32F4系列,我们需要包含"stm32f4xx.h"。 2.然后,我们需要定义一个指向Flash存储器的指针变量。例如,可以使用如下代码:`uint32_t* flash_address = (uint32_t*)0x08000000;`其中0x08000000是Flash存储器的起始地址。 3.要读取Flash存储器中的数据,我们可以通过以下代码实现:`data = *flash_address;`其中data是一个变量,用于存储读取到的数据。 4.要写入数据到Flash存储器中,我们可以通过以下代码实现:`*flash_address = data;`其中data是要写入的数据。 需要注意的是,STM32的Flash存储器是有写保护机制的,因此在写入数据之前,我们需要禁用写保护。可以使用以下代码禁用写保护:`FLASH->KEYR = 0x45670123; FLASH->KEYR = 0xCDEF89AB;`然后才能进行数据写入。 另外,为了确保数据的完整性,我们可以使用CRC校验来验证Flash存储器中的程序代码的正确性。可以使用库函数来计算校验和,然后将其与预期的校验和进行比较以进行验证。 综上所述,掌握STM32的Flash读写操作对于嵌入式系统的开发非常重要。上述示例代码可以帮助我们快速进行Flash读写操作,同时注意写保护和数据校验可以提高数据的安全性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值