STM32F767 IWDG的基本用法

 本文介绍STM32F767 IWDG(Independent watchdog)的基本用法。

开发环境

硬件环境

  • 电脑:Windows 10 Home x64
  • Apollo STM32F767开发板(ST-LINK V2仿真器)

软件环境

  • Keil Version 5.24.1 (Pack Installer:Keil.STM32F7xx_DFP.2.9.0.pack)
  • STM32CubeMX Version 4.25.0(Packages Manager:STM32CubeF7)

IWDG的基本特性

系统框图

 IWDG的系统框图如下所示。

主要特性

  • 自由计数递减计数器
  • 时钟源为独立LSI RC振荡器(可以在待机与停止模式下运行)
  • 复位条件
    • 递减计数器值小于0x000时(看门狗激活状态下)
    • 递减计数器在窗口之外时被重载(看门狗激活状态下)

LSI特性

 IWDG使用LSI作为时钟源,LSI的基本特性如下所示。

 由LSI参数可以,其时钟频率并不准确。因此其作为时钟源时必须充分考虑其参数范围,计算出IWDG复位的最短时间,并在此时间内进行重载操作。

IWDG溢出时间计算

 独立看门狗的溢出时间计算公式如下所示:

$$T_{overflow}=\frac{1}{f_{IWDG}}\cdot Period=\frac{1}{\frac{f_{LSI}}{Prescaler}}\cdot Period$$

 即为:

$$T_{overflow}=\frac{Prescaler}{f_{LSI}}\cdot Period$$

 举例来说,假定LSI时钟频率为32kHz,设置预分频值为64,Period值为500,则IWDG周期为1s;如果LSI时钟频率为17kHz,则IWDG周期为1.882s;如果LSI时钟频率为47kHz,则IWDG周期为0.681s。

 考虑到必须取最小溢出时间,则需要在0.681m内完成喂狗操作

IWDG的基本用法

IWDG参数设置

 IWDG的初始化代码如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
IWDG_HandleTypeDef hiwdg;
/* IWDG init function */
void MX_IWDG_Init(void)
{
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER_64;
hiwdg.Init.Window = IWDG_WINDOW_DISABLE;
hiwdg.Init.Reload = 500;
if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}

 其参数设置如下:

  • 预分频系数设置为64,周期值设置为500,则IWDG溢出时间为0.681~1.882s
  • 窗口值设置为0xfff,则等效于禁用看门狗窗口功能。

IWDG初始化

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
/**
* @brief Initialize the IWDG according to the specified parameters in the
* IWDG_InitTypeDef and start watchdog. Before exiting function,
* watchdog is refreshed in order to have correct time base.
* @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
* the configuration information for the specified IWDG module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)
{
uint32_t tickstart;
/* Check the IWDG handle allocation */
if(hiwdg == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_IWDG_ALL_INSTANCE(hiwdg->Instance));
assert_param(IS_IWDG_PRESCALER(hiwdg->Init.Prescaler));
assert_param(IS_IWDG_RELOAD(hiwdg->Init.Reload));
assert_param(IS_IWDG_WINDOW(hiwdg->Init.Window));
/* Enable IWDG. LSI is turned on automaticaly */
__HAL_IWDG_START(hiwdg);
/* Enable write access to IWDG_PR, IWDG_RLR and IWDG_WINR registers by writing
0x5555 in KR */
IWDG_ENABLE_WRITE_ACCESS(hiwdg);
/* Write to IWDG registers the Prescaler & Reload values to work with */
hiwdg->Instance->PR = hiwdg->Init.Prescaler;
hiwdg->Instance->RLR = hiwdg->Init.Reload;
/* Check pending flag, if previous update not done, return timeout */
tickstart = HAL_GetTick();
/* Wait for register to be updated */
while(hiwdg->Instance->SR != RESET)
{
if((HAL_GetTick() - tickstart ) > HAL_IWDG_DEFAULT_TIMEOUT)
{
return HAL_TIMEOUT;
}
}
/* If window parameter is different than current value, modify window
register */
if(hiwdg->Instance->WINR != hiwdg->Init.Window)
{
/* Write to IWDG WINR the IWDG_Window value to compare with. In any case,
even if window feature is disabled, Watchdog will be reloaded by writing
windows register */
hiwdg->Instance->WINR = hiwdg->Init.Window;
}
else
{
/* Reload IWDG counter with value defined in the reload register */
__HAL_IWDG_RELOAD_COUNTER(hiwdg);
}
/* Return function status */
return HAL_OK;
}
* @brief Enable the IWDG peripheral.
* @param __HANDLE__ IWDG handle
* @retval None
*/
#define __HAL_IWDG_START(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_ENABLE)
* @brief Enable write access to IWDG_PR, IWDG_RLR and IWDG_WINR registers.
* @param __HANDLE__ IWDG handle
* @retval None
*/
#define IWDG_ENABLE_WRITE_ACCESS(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_WRITE_ACCESS_ENABLE)
* @brief Reload IWDG counter with value defined in the reload register
* (write access to IWDG_PR, IWDG_RLR & IWDG_WINR registers disabled).
* @param __HANDLE__ IWDG handle
* @retval None
*/
#define __HAL_IWDG_RELOAD_COUNTER(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_RELOAD)
1
2
3
4
5
6
7
/**
* @brief IWDG Key Register BitMask
*/
#define IWDG_KEY_RELOAD 0x0000AAAAu /*!< IWDG Reload Counter Enable */
#define IWDG_KEY_ENABLE 0x0000CCCCu /*!< IWDG Peripheral Enable */
#define IWDG_KEY_WRITE_ACCESS_ENABLE 0x00005555u /*!< IWDG KR Write Access Enable */
#define IWDG_KEY_WRITE_ACCESS_DISABLE 0x00000000u /*!< IWDG KR Write Access Disable */

 IWDG初始化流程如下:

  • IWDG_KR寄存器写入IWDG_KEY_ENABLE(0x0000CCCCu)值,则启动IWDG,计数器开始从复位值0xfff递减技术;
  • IWDG_KR寄存器写入IWDG_KEY_WRITE_ACCESS_ENABLE(0x00005555u)值,则使能寄存器访问;
  • IWDG_PR寄存器写入Prescaler值;
  • IWDG_RLR寄存器写入Period(Reload)值;
  • 通过读取IWDG_SR寄存器值,等待寄存器更新完成;
  • IWDG_KR寄存器写入IWDG_KEY_RELOAD(0x0000AAAAu)值,刷新IWDG计数器值。

刷新IWDG函数

 刷新IWDG的函数如下,即通过向IWDG_KR寄存器写入IWDG_KEY_RELOAD(0x0000AAAAu)值,刷新IWDG计数器值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* @brief Refresh the IWDG.
* @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
* the configuration information for the specified IWDG module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
{
/* Reload IWDG counter with value defined in the reload register */
__HAL_IWDG_RELOAD_COUNTER(hiwdg);
/* Return function status */
return HAL_OK;
}
/**
* @brief Reload IWDG counter with value defined in the reload register
* (write access to IWDG_PR, IWDG_RLR & IWDG_WINR registers disabled).
* @param __HANDLE__ IWDG handle
* @retval None
*/
#define __HAL_IWDG_RELOAD_COUNTER(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_RELOAD)

测试程序

 在主程序中测试IWDG,程序设计如下:

1
2
3
4
5
6
7
8
9
10
while (1)
{
mainloop++;
oled_putuint32(0, 2, mainloop);
HAL_IWDG_Refresh(&hiwdg);
SYS_Delay_US(600*1000);
}
  • Delay时间设置为600ms,运行测试程序,可以看到mainloop不断增加,程序正常运行。说明在IWDG计数值溢出前完成刷新,看门狗未导致系统复位
  • Delay时间设置为1900ms,运行测试程序,可以看到mainloop显示为1后系统复位,如此反复。说明未在IWDG计数值溢出前完成刷新,看门狗导致了系统复位
文章目录
  1. 1. 开发环境
    1. 1.1. 硬件环境
    2. 1.2. 软件环境
  2. 2. IWDG的基本特性
    1. 2.1. 系统框图
    2. 2.2. 主要特性
    3. 2.3. LSI特性
    4. 2.4. IWDG溢出时间计算
  3. 3. IWDG的基本用法
    1. 3.1. IWDG参数设置
    2. 3.2. IWDG初始化
    3. 3.3. 刷新IWDG函数
    4. 3.4. 测试程序
|