STM32F1与STM32CubeIDE快速入门-独立看门狗(IWDG)

独立看门狗(IWDG)

1、独立看门狗介绍

独立看门狗用于检测和解决由于软件故障引起的故障。当它在预期的时间窗口内没有刷新时,它会触发一个重置序列。由于它的时钟是一个独立的 32-kHz 低速内部 RC 振荡器 (LSI),因此即使主时钟出现故障,它也会保持活动状态。一旦启用,它会强制激活低速内部振荡器,并且只能通过复位禁用。应用程序的主要好处之一是它能够独立于主时钟运行。

独立看门狗的主要特性如下:

  • 可编程超时范围从 125 us 到 32.8 秒

  • 可编程时间窗宽度

  • 由独立的 RC 振荡器 (LSI) 提供时钟

  • 产生复位时:

    • 达到超时值
    • 刷新发生在窗外
  • 可以冻结在调试、停止或待机模式

  • 可配置为自动启用

独立看门狗的功能框图如下:

在这里插入图片描述

独立的看门狗寄存器位于 CORE 电压域,而其功能位于 VDD 电压域。当递减计数器达到零时,看门狗复位被激活。当应用软件没有按时刷新窗口看门狗时,就会发生这种情况。如果软件在递减计数器大于 Window 寄存器中存储的值时刷新看门狗,也会产生复位。 为防止看门狗复位,必须在递减计数器值不为零且低于时间窗口值时进行刷新。

在这里插入图片描述

激活 IWDG 是直接的。我们需要做的就是用预定义的常量 0xCCCC 加载Key寄存器 IWDG_KR。一旦加载了该值,IWDG 硬件就会启动,其计数器将从复位值 0xFFF 或预加载值向下计数到 0x000。当计数器计数到 0x000 计数时,发出复位信号。这通常是我们不想要的,因此为了避免重置,我们需要用 0xAAAA 重写 IWDG_KR。这将重新加载计数器,从而避免重置。在这一点上,很明显我们需要定期将 0xAAAA 写入软件中的 IWDG_KR 寄存器。如果软件卡住了,它将不会这样做,并且当时间或计数用完时,IWDG 将从初始化阶段重新启动 MCU。

在我们激活 IWDG 之前,它应该根据我们的超时需要进行配置。 IWDG_PR 和 IWDG_RLR 寄存器分别保存预分频因子或除数因子和重载值。这些值决定了复位前所需的超时时间。这些寄存器默认是写保护的,所以要改变它们的值,我们需要遵循一个序列,否则写保护将不会被删除。要配置 IWDG,我们需要按照以下步骤操作:

  1. 使用 0x5555 加载 IWDG_KR 寄存器。 这将删除 IWDG_PR 和 IWDG_RLR 寄存器的写保护,允许我们编辑它们的值。
  2. 编辑 IWDG_PR 和 IWDG_RLR 寄存器的值。
  3. 通过发出重新加载命令启用写保护,即将 0xAAAA 写入 IWDG_PR 寄存器。
  4. 通过使用 0xCCCC 加载 IWDG_PR 来启动 IDWG。

IWDG 超时公式如下:

在这里插入图片描述

例如,如果 RLR 等于 180,PR 等于 6,LSI 的频率为 45 kHz,那么我们大致得到大约 1000 毫秒或 1 秒的超时。

2、IWDG配置

STM32CubeIDE创建工程、系统配置、调试配置、串口配置,在这里不再做介绍,请参考:

IWDG的配置如下:

在这里插入图片描述

保存并生成代码。

3、代码生成与实现

1)IWDG初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void MX\_IWDG\_Init(void)
{

/\* USER CODE BEGIN IWDG\_Init 0 \*/

/\* USER CODE END IWDG\_Init 0 \*/

/\* USER CODE BEGIN IWDG\_Init 1 \*/

/\* USER CODE END IWDG\_Init 1 \*/
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER_64;
hiwdg.Init.Reload = 625;
if (HAL\_IWDG\_Init(&hiwdg) != HAL_OK)
{
Error\_Handler();
}
/\* USER CODE BEGIN IWDG\_Init 2 \*/

/\* USER CODE END IWDG\_Init 2 \*/

}

2)主程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/\* Includes ------------------------------------------------------------------\*/
#include "main.h"
#include "iwdg.h"
#include "usart.h"
#include "gpio.h"

/\* Private includes ----------------------------------------------------------\*/
/\* USER CODE BEGIN Includes \*/
#include <stdio.h>
/\* USER CODE END Includes \*/

/\* Private typedef -----------------------------------------------------------\*/
/\* USER CODE BEGIN PTD \*/

/\* USER CODE END PTD \*/

/\* Private define ------------------------------------------------------------\*/
/\* USER CODE BEGIN PD \*/
/\* USER CODE END PD \*/

/\* Private macro -------------------------------------------------------------\*/
/\* USER CODE BEGIN PM \*/

/\* USER CODE END PM \*/

/\* Private variables ---------------------------------------------------------\*/

/\* USER CODE BEGIN PV \*/

/\* USER CODE END PV \*/

/\* Private function prototypes -----------------------------------------------\*/
void SystemClock\_Config(void);
/\* USER CODE BEGIN PFP \*/

/\* USER CODE END PFP \*/

/\* Private user code ---------------------------------------------------------\*/
/\* USER CODE BEGIN 0 \*/

/\* USER CODE END 0 \*/

/\*\*
\* @brief The application entry point.
\* @retval int
\*/
int main(void) {
/\* USER CODE BEGIN 1 \*/

/\* USER CODE END 1 \*/

/\* MCU Configuration--------------------------------------------------------\*/

/\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/
HAL\_Init();

/\* USER CODE BEGIN Init \*/

/\* USER CODE END Init \*/

/\* Configure the system clock \*/
SystemClock\_Config();

/\* USER CODE BEGIN SysInit \*/

/\* USER CODE END SysInit \*/

/\* Initialize all configured peripherals \*/
MX\_GPIO\_Init();
MX\_IWDG\_Init();
MX\_USART1\_UART\_Init();
/\* USER CODE BEGIN 2 \*/
printf("\*\*\*\*IWDG Demo\*\*\*\*\r\n");
/\* USER CODE END 2 \*/

/\* Infinite loop \*/
/\* USER CODE BEGIN WHILE \*/
while (1) {
/\* USER CODE END WHILE \*/

/\* USER CODE BEGIN 3 \*/
printf("\n\r Refreshes the IWDG !!!\n\r");
HAL\_IWDG\_Refresh(&hiwdg);
HAL\_Delay(800);
}
/\* USER CODE END 3 \*/
}

/\*\*
\* @brief System Clock Configuration
\* @retval None
\*/
void SystemClock\_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };

/\*\* Initializes the RCC Oscillators according to the specified parameters
\* in the RCC\_OscInitTypeDef structure.
\*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI
| RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL\_RCC\_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error\_Handler();
}
/\*\* Initializes the CPU, AHB and APB buses clocks
\*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL\_RCC\_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
Error\_Handler();
}
}

/\* USER CODE BEGIN 4 \*/

/\* USER CODE END 4 \*/

/\*\*
\* @brief This function is executed in case of error occurrence.
\* @retval None
\*/
void Error\_Handler(void) {
/\* USER CODE BEGIN Error\_Handler\_Debug \*/
/\* User can add his own implementation to report the HAL error return state \*/
\_\_disable\_irq();
while (1) {
}
/\* USER CODE END Error\_Handler\_Debug \*/
}

#ifdef USE\_FULL\_ASSERT
/\*\*
\* @brief Reports the name of the source file and the source line number
\* where the assert\_param error has occurred.
\* @param file: pointer to the source file name
\* @param line: assert\_param error line source number
\* @retval None
\*/
void assert\_failed(uint8_t \*file, uint32_t line)
{
/\* USER CODE BEGIN 6 \*/
/\* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) \*/
/\* USER CODE END 6 \*/
}
#endif /\* USE\_FULL\_ASSERT \*/

4、运行结果

在这里插入图片描述

文章来源: https://iotsmart.blog.csdn.net/article/details/123626730