天天看点

《MiniPRO H750开发指南》第十八章 独立看门狗(IWDG)实验

第十八章独立看门狗(IWDG)实验​

本章我们学习如何使用STM32H7的独立看门狗(以下简称IWDG)。STM32H7内部自带了2个看门狗:独立看门狗(IWDG)和窗口看门狗(WWDG)。这一章我们只介绍独立看门狗,窗口看门狗将在下一章介绍。在本章中,我们将通过按键KEY_UP来喂狗,然后通过LED0提示复位状态。​

本章分为如下几个小节:​

18.1 IWDG简介​

18.2 硬件设计​

18.3 程序设计​

18.4 下载验证​

18.1 IWDG简介​

独立看门狗本质上是一个定时器,这个定时器有一个输出端,可以输出复位信号。该定时器是一个12位的递减计数器,当计数器的值减到0的时候,就会产生一个复位信号。如果在计数没减到0之前,重置计数器的值的话,那么就不会产生复位信号,这个动作我们称为喂狗。看门狗功能由VDD电压域供电,在停止模式和待机模式下仍然可以工作。​

18.1.1 IWDG框图​

下面先来学习IWDG框图,通过学习IWDG框图会有一个很好的整体掌握,同时对之后的编程也会有一个清晰的思路。​

《MiniPRO H750开发指南》第十八章 独立看门狗(IWDG)实验

图18.1.1.1 IWDG框图​

从IWDG框图整体认知就是,IWDG有一个输入(时钟lsi_ck),经过一个8位的可编程预分频器提供时钟给一个12位递减计数器,满足条件就会输出一个复位信号(iwdg1_out_rst)。IWDG内部输入/输出信号如下表:​

信号名称​ 信号类型​ 说明​
lsi_ck​ 数字信号​ LSI时钟​
iwdg1_out_rst​ 数字信号​ IWDG1 复位信号输出​

表18.1.1.1 IWDG内部输入/输出信号​

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

18.1.2 IWDG寄存器​

IWDG的框图很简单,用到的寄存器也不多。我们主要用到其中3个寄存器:​

  • 键寄存器(IWDG_KR)​键寄存器可以看作是独立看门狗的控制寄存器,其描述如图18.1.2.1所示:​
  • 《MiniPRO H750开发指南》第十八章 独立看门狗(IWDG)实验
  • 图18.1.2.1 WDG_KR寄存器​

    在键寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。 无论何时,只要键寄存器IWDG_KR中被写入0xAAAA, IWDG_RLR中的值就会被重新加载到计数器中从而避免产生看门狗复位 。​

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

  • 预分频寄存器(IWDG_PR)​预分频寄存器描述如图18.1.2.2所示:​
  • 《MiniPRO H750开发指南》第十八章 独立看门狗(IWDG)实验
  • 图18.1.2.2 IWDG_ PR寄存器​

    该寄存器用来设置看门狗时钟(LSI)的分频系数,最低为4分频,最高位256分频,该寄存器是一个32位的寄存器,但是我们只用了最低3位,其他都是保留位。​

  • 重载寄存器(IWDG_ RLR)​
《MiniPRO H750开发指南》第十八章 独立看门狗(IWDG)实验

图18.1.2.3 IWDG_ RLR寄存器​

该寄存器用来保存重装载到计数器中的值。该寄存器也是一个32位寄存器,只有低12位是有效的。 ​

18.2 硬件设计​

1. 例程功能​

在配置看门狗后,LED0将常亮,如果KEY_UP按键按下,就喂狗,只要KEY_UP不停的按,看门狗就一直不会产生复位,保持LED0的常亮,一旦超过看门狗定溢出时间(Tout)还没按,那么将会导致程序重启,这将导致LED0熄灭一次。​

2. 硬件资源​

1)RGB灯​

RED :LED0 - PB4​

2)独立按键​

WK_UP - PA0。​

3)独立看门狗​

3. 原理图​

独立看门狗实验的核心是在STM32H750内部进行,并不需要外部电路。但是考虑到指示当前状态和喂狗等操作,我们需要2个IO口,一个用来输入喂狗信号,另外一个用来指示程序是否重启。喂狗我们采用板上的KEY_UP键来操作,而程序重启,则是通过LED0来指示的。​

18.3 程序设计​

18.3.1 IWDG的HAL库驱动​

IWDG在HAL库中的驱动代码在stm32h7xx_hal_iwdg.c文件(及其头文件)中。 ​

1. HAL_IWDG_Init函数​

IWDG的初始化函数,其声明如下:​

HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg);      
  • 函数描述:​用于初始化IWDG。​
  • 函数形参:​形参1是IWDG句柄,IWDG_HandleTypeDef结构体类型,其定义如下:​
typedef struct​
{​
 IWDG_TypeDef *Instance; /* IWDG寄存器基地址 */​
 IWDG_InitTypeDef Init; /* IWDG初始化参数 */​
}IWDG_HandleTypeDef;      
  • 1)Instance:指向IWDG寄存器基地址。2)Init:IWDG初始化结构体,用于配置计数器的相关参数。IWDG_InitTypeDef这个结构体类型定义如下:
typedef struct
{
 uint32_t Prescaler;  /* 预分频系数 */
 uint32_t Reload;  /* 重装载值 */
 uint32_t Window;  /* 窗口值 */      
  • } IWDG_InitTypeDef;

    1)Prescaler:预分频系数,IWDG_PRESCALER_4到IWDG_PRESCALER_256。

    2)Reload:重装载值,范围:0到0x0FFF。

    3)Window:窗口值。

  • 函数返回值:​HAL_StatusTypeDef枚举类型的值。​2. HAL_IWDG_Refresh函数​HAL_IWDG_Refresh函数是独立看门狗的喂狗函数。其声明如下:​
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg);      
  • 函数描述:​用于把重装载寄存器的值重载到计数器中,喂狗,防止IWDG复位。​
  • 函数形参:​形参1是IWDG_HandleTypeDef结构体指针类型的IWDG句柄。​
  • 函数返回值:​

HAL_StatusTypeDef枚举类型的值。​

独立看门狗配置步骤 ​

1)取消寄存器写保护,设置看门狗预分频系数和重装载值​

首先我们必须取消IWDG_PR和IWDG_RLR寄存器的写保护,这样才可以设置寄存器IWDG_PR和IWDG_RLR的值。取消写保护和设置预分频系数以及重装载值在HAL库中是通过函数HAL_IWDG_Init实现的。​

通过该函数设置看门狗的分频系数,和重装载的值。看门狗的喂狗时间(也就是看门狗溢出时间)的计算方式为:​

Tout=((4×2^prer) ×rlr) /32      

其中Tout为看门狗溢出时间(单位为ms)。​

prer为看门狗时钟预分频值(IWDG_PR值),范围为0~7。​

rlr为看门狗的重装载值(IWDG_RLR的值)。​

比如我们设定prer值为4(4代表的是64分频,HAL库中可以使用宏定义标识符IWDG_PRESCALER_64),rlr值为500,那么就可以得到Tout=64×500/32=1000ms,这样,看门狗的溢出时间就是1s,只要你在一秒钟之内,有一次写入0XAAAA到IWDG_KR,就不会导致看门狗复位(当然写入多次也是可以的)。这里需要提醒大家的是,看门狗的时钟不是准确的32Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。​

2)重载计数值喂狗(向IWDG_KR写入0XAAAA)​

在HAL中重载计数值的函数是HAL_IWDG_Refresh,该函数的作用是把值0xAAAA写入到IWDG_KR寄存器,从而触发计数器重载,即实现独立看门狗的喂狗操作。​

3) 启动看门狗(向IWDG_KR写入0XCCCC)​

HAL库函数里面启动独立看门狗是通过宏定义标识符来实现的:​

#define __HAL_IWDG_START(__HANDLE__) ​
 WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_ENABLE);      

我们只需要调用宏定义标识符__HAL_IWDG_START即可实现看门狗使能。实际上,当我们调用了看门狗初始化函数HAL_IWDG_Init之后,在内部已经调用了该宏启动看门狗。​

18.3.2 程序流程图​

《MiniPRO H750开发指南》第十八章 独立看门狗(IWDG)实验

图18.3.2.1 独立看门狗实验程序流程图​

18.3.3 程序解析​

1. IWDG驱动代码​

这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。独立看门狗(IWDG)驱动源码包括两个文件:wdg.c和wdg.h。​

wdg.h头文件只有函数的声明,就不解释了。下面我们直接解析wdg.c的程序,先看IWDG的初始化函数,其定义如下:​

/**​
初始化独立看门狗 ​
 * @param prer: IWDG_PRESCALER_4~IWDG_PRESCALER_256,对应4~256分频​
分频因子 = 4 * 2^prer. 但最大值只能是256!​
自动重装载值,0~0XFFF. ​
时间计算(大概):Tout=((4 * 2^prer) * rlr) / 32 (ms). ​
无​
 */​
void iwdg_init(uint8_t prer, uint16_t rlr)​
{​
 g_iwdg_handle.Instance = IWDG1;​
 g_iwdg_handle.Init.Prescaler = prer;  /* 设置IWDG分频系数 */​
 g_iwdg_handle.Init.Reload = rlr;  /* 重装载 */​
 g_iwdg_handle.Init.Window = IWDG_WINDOW_DISABLE;  /* 关闭窗口功能 */​
 HAL_IWDG_Init(&g_iwdg_handle); ​
}      

IWDG_Init是独立看门狗初始化函数,主要设置预分频数和重装载寄存器的值。通过这两个寄存器,就可以大概知道看门狗复位的时间周期为多少了。​

/**​
喂独立看门狗​
无​
无​
 */​
void iwdg_feed(void)​
{ ​
 HAL_IWDG_Refresh(&g_iwdg_handle); /* 重装载计数器 */​
}      

iwdg_feed函数用来喂狗,在该函数内部只需调用HAL库函数HAL_IWDG_Refresh。​

2. main.c代码​

在main.c里面编写如下代码:​

int main(void)​
{​
 sys_cache_enable();  /* 打开L1-Cache */​
 HAL_Init();  /* 初始化HAL库 */​
 sys_stm32_clock_init(240, 2, 2, 4); /* 设置时钟, 480Mhz */​
 delay_init(480);  /* 延时初始化 */​
 usart_init(115200);  /* 串口初始化为115200 */​
 led_init();  /* 初始化LED */​
 key_init();  /* 初始化按键 */​
 delay_ms(100);  /* 延时100ms再初始化看门狗,LED0的变化可见"*/​
 iwdg_init(IWDG_PRESCALER_64, 500); /* 预分频数为64,重载值为500,溢出时间为1s */​
 LED0(0);  /* 点亮LED0(红灯) */​
 while (1)​
 {​
 if (key_scan(0) == WKUP_PRES)  /* 如果WK_UP按下,则喂狗 */​
 {​
 iwdg_feed();  /* 喂狗 */​
 }​
 delay_ms(10);​
 }​
}      

18.4 下载验证​