stm32—watchdog (independent watchdog IWDG, window watchdog WWDG)

Graphical overview:

Independent watchdog:

Code:

#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"

/* Independent watchdog
---By pressing the button and not letting go, it enters the while infinite loop, causing the program to block.
When the timeout time of the independent watchdog is exceeded, the independent watchdog is reset.
The normal phenomenon is that the OLED flashes and displays the "FEED" string, and does not let go when the button is pressed.
After the set timeout period is exceeded, the independent watchdog automatically resets and runs again.
program, and determine whether the reset is caused by the independent watchdog at the beginning of the program.
If so, the OLED flashes and displays "IWDGRST"
*/


int main(void)
{
OLED_Init();
Key_Init();
\t
OLED_ShowString(1, 1, "IWDG TEST");

\t
/*
Use RCC_GetFlagStatus to get the RCC_FLAG_IWDGRST independent watchdog reset flag (if it is an independent watchdog reset)
The flag bit is 1, otherwise it is 0). By judging the RCC_FLAG_IWDGRST flag bit, it is shown that the chip is reset by an independent watchdog.
Or normal button reset?
*/
if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET)
{
OLED_ShowString(2, 1, "IWDGRST");
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(100);
\t\t
RCC_ClearFlag();
}
else
{
OLED_ShowString(3, 1, "RST");
Delay_ms(500);
OLED_ShowString(3, 1, " ");
Delay_ms(100);
}
\t
//Release the independent watchdog write enable protection (write 0x5555 to the key register)
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
\t
/*
The timeout time formula of the independent watchdog: T(IWDG) = T(LSI) × PR prescaler coefficient × (RL + 1)
where T(LSI) = 1 / F(LSI)
It is known that the internal low-speed clock of LSI is 40kHz, so T(LSI) is 0.025ms
Example: To set a timeout of 1000ms (PR has only 3 digits, RL is 12 digits)
Then PR can choose to divide by 16, so RL is 2500-1
*/
//Configure prescaler---select 16 divider
IWDG_SetPrescaler(IWDG_Prescaler_16);
//Configure reload value---write 2499
IWDG_SetReload(2499);
\t
/* Feeding the dog or enabling will internally write a value other than 0x5555 to the key register, which also turns on the write protection operation*/
//Reload the counter value (i.e. dog feeding operation)
IWDG_ReloadCounter();
//Turn on the independent watchdog (after turning it on, the LSI internal low-speed clock will also be forcibly turned on)
IWDG_Enable();
\t
while(1)
{
/*Test whether feeding the dog beyond the set timeout will generate a prompt*/
\t\t
//Press the button and don't let go, entering the while loop stuck state
Key_GetNum();
\t\t
//Feed the dog operation
IWDG_ReloadCounter();
//Show dog feeding operation
OLED_ShowString(4, 1, "FEED");
Delay_ms(500);
OLED_ShowString(4, 1, " ");
Delay_ms(200);
\t\t
}
}

Key code:

 /*
Use RCC_GetFlagStatus to get the RCC_FLAG_IWDGRST independent watchdog reset flag (if it is an independent watchdog reset)
The flag bit is 1, otherwise it is 0). By judging the RCC_FLAG_IWDGRST flag bit, it is shown that the chip is reset by an independent watchdog.
Or normal button reset?
*/
if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET)
{
OLED_ShowString(2, 1, "IWDGRST");
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(100);
\t\t
RCC_ClearFlag();
}
else
{
OLED_ShowString(3, 1, "RST");
Delay_ms(500);
OLED_ShowString(3, 1, " ");
Delay_ms(100);
}


//Release the independent watchdog write enable protection (write 0x5555 to the key register)
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
\t
/*
The timeout time formula of the independent watchdog: T(IWDG) = T(LSI) × PR prescaler coefficient × (RL + 1)
where T(LSI) = 1 / F(LSI)
It is known that the internal low-speed clock of LSI is 40kHz, so T(LSI) is 0.025ms
Example: To set a timeout of 1000ms (PR has only 3 digits, RL is 12 digits)
Then PR can choose to divide by 16, so RL is 2500-1
*/
//Configure prescaler---select 16 divider
IWDG_SetPrescaler(IWDG_Prescaler_16);
//Configure reload value---write 2499
IWDG_SetReload(2499);
\t
/* Feeding the dog or enabling will internally write a value other than 0x5555 to the key register, which also turns on the write protection operation*/
//Reload the counter value (i.e. dog feeding operation)
IWDG_ReloadCounter();
//Turn on the independent watchdog (after turning it on, the LSI internal low-speed clock will also be forcibly turned on)
IWDG_Enable();

Window watchdog:

Code:

#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"

/* Window watchdog
---By pressing the button and not letting go, it enters the while loop, causing the program to block.
It can be used to check the display phenomenon when feeding the dog overtime. If you want to feed the dog too quickly, check the display.
phenomenon, you need to control the running time of the main program to be less than the set window value.
If the window watchdog is configured between the window value and the timeout value, the OLED will flash normally.
"FEED" is displayed. If the dog is fed early or delayed, the chip will be reset and the program will be re-run.
And determine whether it is a manual reset or a window watchdog reset. If the window watchdog is reset,
The OLED will flash and display "WWDGRST"
*/


int main(void)
{
OLED_Init();
Key_Init();
\t
OLED_ShowString(1, 1, "WWDG TEST");

\t
/*
Use RCC_GetFlagStatus to get the RCC_FLAG_IWDGRST independent watchdog reset flag (if it is an independent watchdog reset)
The flag bit is 1, otherwise it is 0). By judging the RCC_FLAG_IWDGRST flag bit, it is shown that the chip is reset by an independent watchdog.
Or normal button reset?
*/
if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET)
{
OLED_ShowString(2, 1, "WWDGRST");
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(100);
\t\t
RCC_ClearFlag();
}
else
{
OLED_ShowString(3, 1, "RST");
Delay_ms(500);
OLED_ShowString(3, 1, " ");
Delay_ms(100);
}
\t
/* Initialize window watchdog WWDG */
//1. Turn on the clock PCLK1 of the WWDG peripheral (i.e. APB1)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
\t
//2. Set the prescaler value and window value
\t
/*
Timeout time: T(WWDG) = T(PCLK1) × 4096 × WDGTB prescaler coefficient × (T[5:0] + 1)
Window time: T(WIN) = T(PCLK1) × 4096 × WDGTB prescaler coefficient × (T[5:0] - W[5:0])
Where: T(PCLK1) = 1 / F(PCLK1)
It is known that the frequency of PCLK1 is 36MHz, so T(PCLK1) is 0.02777us
Example: When you want to set a timeout of 50ms and the window time is 30ms, select the prescaler coefficient as 8
50000us = 0.02777us × 4096 × 8 × (T[5:0] + 1)
So the lower 6 bits of the down counter T are 54
30000us = 0.02777us × 4096 × 8 × (54 - W[5:0])
So the lower 6 bits of the window configuration counter W are 21
*/
\t
//Prescale to 8
WWDG_SetPrescaler(WWDG_Prescaler_8);
//Set the window value of 30ms
WWDG_SetWindowValue(0x40 | 21); //The second highest bit of the configuration register control register needs to be set to 1
//3. Enable WWDG and set the initial counter to 50ms
WWDG_Enable(0x40 | 54); //The second highest bit of the control register needs to be set to 1 (if the default is 0, the reset will be triggered directly)
\t
\t
while(1)
{
/*Test the phenomenon of early or delayed dog feeding operation within 30ms~50ms (30ms is the window value, 50ms is the timeout time)*/
\t\t
//Press the button and don't let go, entering the while loop stuck state
Key_GetNum();
\t\t
\t\t
//Show dog feeding operation
// OLED_ShowString(4, 1, "FEED");
//Delay_ms(20);
// OLED_ShowString(4, 1, " ");
Delay_ms(50);
\t\t
//Set the counter to 50ms (dog feeding operation)
WWDG_SetCounter(0x40 | 54);
}
}

Key code:

 /*
Use RCC_GetFlagStatus to get the RCC_FLAG_IWDGRST independent watchdog reset flag (if it is an independent watchdog reset)
The flag bit is 1, otherwise it is 0). By judging the RCC_FLAG_IWDGRST flag bit, it is shown that the chip is reset by an independent watchdog.
Or normal button reset?
*/
if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET)
{
OLED_ShowString(2, 1, "WWDGRST");
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(100);
\t\t
RCC_ClearFlag();
}
else
{
OLED_ShowString(3, 1, "RST");
Delay_ms(500);
OLED_ShowString(3, 1, " ");
Delay_ms(100);
}


/* Initialize window watchdog WWDG */
//1. Turn on the clock PCLK1 of the WWDG peripheral (i.e. APB1)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);


//2. Set the prescaler value and window value
\t
/*
Timeout time: T(WWDG) = T(PCLK1) × 4096 × WDGTB prescaler coefficient × (T[5:0] + 1)
Window time: T(WIN) = T(PCLK1) × 4096 × WDGTB prescaler coefficient × (T[5:0] - W[5:0])
Where: T(PCLK1) = 1 / F(PCLK1)
It is known that the frequency of PCLK1 is 36MHz, so T(PCLK1) is 0.02777us
Example: When you want to set a timeout of 50ms and the window time is 30ms, select the prescaler coefficient as 8
50000us = 0.02777us × 4096 × 8 × (T[5:0] + 1)
So the lower 6 bits of the down counter T are 54
30000us = 0.02777us × 4096 × 8 × (54 - W[5:0])
So the lower 6 bits of the window configuration counter W are 21
*/
\t
//Prescale to 8
WWDG_SetPrescaler(WWDG_Prescaler_8);
//Set the window value of 30ms
WWDG_SetWindowValue(0x40 | 21); //The second highest bit of the configuration register control register needs to be set to 1
//3. Enable WWDG and set the initial counter to 50ms
WWDG_Enable(0x40 | 54); //The second highest bit of the control register needs to be set to 1 (if the default is 0, the reset will be triggered directly)


//Set the counter to 50ms (dog feeding operation)
WWDG_SetCounter(0x40 | 54);