|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "STM32看门狗" |
| 4 | +date: 2025-10-28T08:44:39+0800 |
| 5 | +description: "独立看门狗(IndependentWatchdog,通常缩写为IWDG)主要作用是主要用于检测外界电磁干扰,或硬件异常导致的程序跑飞问题。IWDG本质上是一个12位的递减计数器。当计数器的值从某个初始值开始递减,并一直减到0时,系统会产生一个复位信号(IWDG_RESET)。CPU在接收到这个复位信号后,会重新启动系统,以确保系统从可能的错误或死锁状态中恢复。在计数器的值减到0之前,如果程序通过特定的“喂狗”操作(即重置计数器的值)来刷新计数器,那么就不会产生复位信号,系统将继续正常运行。" |
| 6 | +keywords: "【STM32】看门狗" |
| 7 | +categories: ['未分类'] |
| 8 | +tags: ['嵌入式硬件', 'Stm'] |
| 9 | +artid: "154004388" |
| 10 | +arturl: "https://blog.csdn.net/qq_62361050/article/details/154004388" |
| 11 | +image: |
| 12 | + path: https://api.vvhan.com/api/bing?rand=sj&artid=154004388 |
| 13 | + alt: "STM32看门狗" |
| 14 | +render_with_liquid: false |
| 15 | +featuredImage: https://bing.ee123.net/img/rand?artid=154004388 |
| 16 | +featuredImagePreview: https://bing.ee123.net/img/rand?artid=154004388 |
| 17 | +cover: https://bing.ee123.net/img/rand?artid=154004388 |
| 18 | +img: https://bing.ee123.net/img/rand?artid=154004388 |
| 19 | +--- |
| 20 | + |
| 21 | + |
| 22 | + |
| 23 | +# 【STM32】看门狗 |
| 24 | + |
| 25 | + |
| 26 | +[ |
| 27 | +『AI先锋杯·14天征文挑战第7期』 |
| 28 | +10w+人浏览 |
| 29 | +319人参与 |
| 30 | + |
| 31 | +](https://activity.csdn.net/writing?id=11005) |
| 32 | + |
| 33 | +## 一、独立看门狗 |
| 34 | + |
| 35 | +### 1. IWDG简介 |
| 36 | + |
| 37 | +独立看门狗(Independent Watchdog,通常缩写为IWDG)主要作用是主要用于检测外界电磁干扰,或硬件异常导致的程序跑飞问题。 |
| 38 | + |
| 39 | +* IWDG本质上是一个12位的递减计数器。当计数器的值从某个初始值开始递减,并一直减到0时,系统会产生一个复位信号(IWDG_RESET)。CPU在接收到这个复位信号后,会重新启动系统,以确保系统从可能的错误或死锁状态中恢复。 |
| 40 | +* 在计数器的值减到0之前,如果程序通过特定的“喂狗”操作(即重置计数器的值)来刷新计数器,那么就不会产生复位信号,系统将继续正常运行。这种“喂狗”操作通常是由程序在正常运行时定期执行的,以确保IWDG不会因计数器超时而产生复位信号。 |
| 41 | +* 它使用专用的低速时钟(LSI)作为时钟源,即使在主时钟发生故障时,IWDG仍然能够继续运行。IWDG可以在停止模式和待机模式下工作,确保在这些模式下系统仍然受到保护。 |
| 42 | + |
| 43 | +### 2. IWDG工作原理及框图 |
| 44 | + |
| 45 | + |
| 46 | + |
| 47 | + |
| 48 | + |
| 49 | +### 3. IWDG寄存器及函数介绍 |
| 50 | + |
| 51 | + |
| 52 | + |
| 53 | +### 4. IWDG溢出时间计算 |
| 54 | + |
| 55 | + |
| 56 | + |
| 57 | +```c |
| 58 | +Tout:看门狗溢出时间 |
| 59 | +fIWDG:看门狗的时钟源频率 |
| 60 | +psc:看门狗预分频系数 |
| 61 | +rlr:看门狗重装载值 |
| 62 | + |
| 63 | +``` |
| 64 | + |
| 65 | + |
| 66 | + |
| 67 | +### 5. IWDG配置步骤 |
| 68 | + |
| 69 | + |
| 70 | + |
| 71 | +### 6. 小实验:独立看门狗喂狗实验 |
| 72 | + |
| 73 | +**实验目的** |
| 74 | + |
| 75 | +配置 IWDG 溢出时间为 1 秒左右,并验证未及时喂狗时系统将被复位。 |
| 76 | + |
| 77 | +**代码实现** |
| 78 | + |
| 79 | +main.c |
| 80 | + |
| 81 | +```c |
| 82 | +#include "sys.h" |
| 83 | +#include "uart1.h" |
| 84 | +#include "delay.h" |
| 85 | +#include "led.h" |
| 86 | +#include "uart1.h" |
| 87 | +#include "iwdg.h" |
| 88 | + |
| 89 | +int main(void) |
| 90 | +{ |
| 91 | + HAL_Init(); /* 初始化HAL库 */ |
| 92 | + stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ |
| 93 | + //LED初始化 |
| 94 | + led_init(); |
| 95 | + uart1_init(115200); |
| 96 | + iwdg_init(IWDG_PRESCALER_32,1250 - 1); |
| 97 | + printf("hello world\r\n"); |
| 98 | + printf("狗儿肚子饿了,再不喂它的话就咬人了\r\n"); |
| 99 | + |
| 100 | + if(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET){ |
| 101 | + printf("独立看门狗复位\r\n"); |
| 102 | + __HAL_RCC_CLEAR_RESET_FLAGS(); |
| 103 | + }else{ |
| 104 | + printf("其他复位重启\r\n"); |
| 105 | + } |
| 106 | + |
| 107 | + while(1) |
| 108 | + { |
| 109 | + delay_ms(500); |
| 110 | + iwdg_feed(); |
| 111 | + printf("狗儿已经喂饱了,不会咬人了!\r\n"); |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +``` |
| 116 | +
|
| 117 | +iwdg.c |
| 118 | +
|
| 119 | +```c |
| 120 | +#include "iwdg.h" |
| 121 | +
|
| 122 | +IWDG_HandleTypeDef iwdg_handle = {0}; |
| 123 | +
|
| 124 | +//独立看门口初始化 |
| 125 | +void iwdg_init(uint8_t psc, uint16_t rlr) |
| 126 | +{ |
| 127 | + iwdg_handle.Instance = IWDG; |
| 128 | + iwdg_handle.Init.Prescaler = psc; |
| 129 | + iwdg_handle.Init.Reload = rlr; |
| 130 | + HAL_IWDG_Init(&iwdg_handle); |
| 131 | +} |
| 132 | +
|
| 133 | +//喂狗函数 |
| 134 | +void iwdg_feed(void) |
| 135 | +{ |
| 136 | + HAL_IWDG_Refresh(&iwdg_handle); |
| 137 | +} |
| 138 | +
|
| 139 | +
|
| 140 | +``` |
| 141 | + |
| 142 | +iwdg.h |
| 143 | + |
| 144 | +```c |
| 145 | +#ifndef __IWDG_H__ |
| 146 | +#define __IWDG_H__ |
| 147 | + |
| 148 | +#include "sys.h" |
| 149 | + |
| 150 | +//独立看门口初始化 |
| 151 | +void iwdg_init(uint8_t psc, uint16_t rlr); |
| 152 | +//喂狗函数 |
| 153 | +void iwdg_feed(void); |
| 154 | + |
| 155 | +#endif |
| 156 | + |
| 157 | +``` |
| 158 | + |
| 159 | +## 二、窗口看门狗 |
| 160 | + |
| 161 | +### 1. WWDG简介 |
| 162 | + |
| 163 | +窗口看门狗用于监测单片机程序运行时效是否精准,主要检测软件异常,一般用于需要精准检测程序运行时间的场合。 |
| 164 | + |
| 165 | +窗口看门狗的本质是一个能产生系统复位信号和提前唤醒中断的6位计数器。产生复位条件: |
| 166 | + |
| 167 | +* 当递减计数器值从 0x40 减到 0x3F 时复位(即T6位跳变到0)。 |
| 168 | +* 计数器的值大于 W[6:0] 值时喂狗会复位。 |
| 169 | + |
| 170 | +产生中断条件: |
| 171 | + |
| 172 | +* 当递减计数器等于 0x40 时可产生提前唤醒中断 (EWI)。 |
| 173 | +* 在窗口期内重装载计数器的值,防止复位,也就是所谓的喂狗。 |
| 174 | + |
| 175 | +### 2. WWDG工作原理及框图 |
| 176 | + |
| 177 | + |
| 178 | + |
| 179 | + |
| 180 | + |
| 181 | +### 3. WWDG寄存器及函数介绍 |
| 182 | + |
| 183 | + |
| 184 | +  |
| 185 | +  |
| 186 | +  |
| 187 | +  |
| 188 | + |
| 189 | +### 4. WWDG溢出时间计算 |
| 190 | + |
| 191 | + |
| 192 | + |
| 193 | +### 5. WWDG配置步骤 |
| 194 | + |
| 195 | + |
| 196 | + |
| 197 | +### 6. 小实验:窗口看门狗喂狗实验 |
| 198 | + |
| 199 | +**实验目的** |
| 200 | + |
| 201 | +开启窗口看门狗,计数器值设置为 0X7F ,窗口值设置为 0X5F ,预分频系数为 8 。在 while 循环里喂狗,同时翻转 LED1 状态;在提前唤醒中断服务函数进行喂狗,同时翻转 LED2 状态。 |
| 202 | + |
| 203 | + |
| 204 | + |
| 205 | +**代码实现** |
| 206 | + |
| 207 | +main.c |
| 208 | + |
| 209 | +```c |
| 210 | +#include "sys.h" |
| 211 | +#include "uart1.h" |
| 212 | +#include "delay.h" |
| 213 | +#include "led.h" |
| 214 | +#include "uart1.h" |
| 215 | +#include "wwdg.h" |
| 216 | + |
| 217 | +int main(void) |
| 218 | +{ |
| 219 | + HAL_Init(); /* 初始化HAL库 */ |
| 220 | + stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ |
| 221 | + //LED初始化 |
| 222 | + led_init(); |
| 223 | + //串口初始化 |
| 224 | + uart1_init(115200); |
| 225 | + //窗口看门狗初始化 |
| 226 | + wwdg_init(0x7F, 0x5F, WWDG_PRESCALER_8); |
| 227 | + |
| 228 | + if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET){ |
| 229 | + printf("独立看门狗复位\r\n"); |
| 230 | + __HAL_RCC_CLEAR_RESET_FLAGS(); |
| 231 | + }else{ |
| 232 | + printf("其他复位重启\r\n"); |
| 233 | + } |
| 234 | + |
| 235 | + while(1) |
| 236 | + { |
| 237 | + delay_ms(50); |
| 238 | + wwdg_feed(); |
| 239 | + led2_toggle(); |
| 240 | + } |
| 241 | +} |
| 242 | + |
| 243 | +``` |
| 244 | +
|
| 245 | +wwdg.c |
| 246 | +
|
| 247 | +```c |
| 248 | +#include "wwdg.h" |
| 249 | +#include "led.h" |
| 250 | +
|
| 251 | +WWDG_HandleTypeDef wwdg_handle = {0}; |
| 252 | +//窗口看门狗初始化 |
| 253 | +void wwdg_init(uint8_t tr, uint8_t wr , uint32_t psc) |
| 254 | +{ |
| 255 | + wwdg_handle.Instance = WWDG; |
| 256 | + //设置定时器重装载值 |
| 257 | + wwdg_handle.Init.Counter = tr; |
| 258 | + //设置窗口值 |
| 259 | + wwdg_handle.Init.Window = wr; |
| 260 | + //设置分频系数 |
| 261 | + wwdg_handle.Init.Prescaler = psc; |
| 262 | + //提前唤醒中断使能标志 |
| 263 | + wwdg_handle.Init.EWIMode = WWDG_EWI_ENABLE;; |
| 264 | + HAL_WWDG_Init(&wwdg_handle); |
| 265 | +} |
| 266 | +
|
| 267 | +//硬件相关初始化 |
| 268 | +void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg) |
| 269 | +{ |
| 270 | + //打开看门口时钟 |
| 271 | + __HAL_RCC_WWDG_CLK_ENABLE(); |
| 272 | + //设置中断优先级 |
| 273 | + HAL_NVIC_SetPriority(WWDG_IRQn, 2, 2); |
| 274 | + //使能中断 |
| 275 | + HAL_NVIC_EnableIRQ(WWDG_IRQn); |
| 276 | +} |
| 277 | +
|
| 278 | +//中断服务函数 |
| 279 | +void WWDG_IRQHandler(void) |
| 280 | +{ |
| 281 | + //公共服务函数 |
| 282 | + HAL_WWDG_IRQHandler(&wwdg_handle); |
| 283 | +} |
| 284 | +
|
| 285 | +//喂狗函数 |
| 286 | +void wwdg_feed(void) |
| 287 | +{ |
| 288 | + HAL_WWDG_Refresh(&wwdg_handle); |
| 289 | +} |
| 290 | +
|
| 291 | +//中断回调函数 |
| 292 | +void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg) |
| 293 | +{ |
| 294 | + //喂狗 |
| 295 | + //wwdg_feed(); |
| 296 | + led2_toggle(); |
| 297 | +} |
| 298 | +
|
| 299 | +``` |
| 300 | + |
| 301 | +wwdg.h |
| 302 | + |
| 303 | +```c |
| 304 | +#ifndef __WWDG_H__ |
| 305 | +#define __WWDG_H__ |
| 306 | + |
| 307 | +#include "sys.h" |
| 308 | + |
| 309 | + |
| 310 | +//喂狗函数 |
| 311 | +void wwdg_feed(void); |
| 312 | +void wwdg_init(uint8_t tr, uint8_t wr , uint32_t psc); |
| 313 | + |
| 314 | +#endif |
| 315 | + |
| 316 | +``` |
| 317 | + |
| 318 | + |
| 319 | + |
0 commit comments