独立看门狗就是一个12位的递减计数器,最大值0xFFF;
计数器的值从某一个值减到0时,系统产生一个复位信号(IWDG_RESET);
在计数器没减到0之前,刷新计数器的值,就不会产生复位信号(就是要喂狗)。
(1)自由运行的递减计数器
(2)时钟由独立的RC振荡器提供(停止和待机模式下仍可工作)
如果启用了“硬件看门狗”,系统上电复位后,看门狗自行运行;
如果计数器计数结束前,软件没有向键寄存器写入相应的值,系统就会复位。
12位寄存器,存储(要刷新到计数器的值),决定了看门狗溢出的时间。
独立看门狗的控制寄存器
软件启动看门狗:键寄存器中写入0xCCCC,看门狗启动后就关不掉,只有复位才能关掉。
0xAAAA | 把RLR中的值重装载到计数器 |
0x555 | PR和RLR这两个寄存器可写 |
0xCCCC | 启动看门狗 |
RVU:看门狗计数器重新装载值更新
PVU:看门狗预分频值更新
(1)取消寄存器写保护
取消PR和RLR的写保护,使得后面可以操作者两个寄存器
- /* 使能对寄存器 IWDG_PR 和 IWDG_RLR 的写操作 */
- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
(2)设置IWDG的预分频系数和重装载值
- void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //设置 IWDG 预分频值
- void IWDG_SetReload(uint16_t Reload); //设置 IWDG 重装载值
溢出时间的计算方法
Tout=((4×2^prer) ×rlr) /4
prer:分频
rlr:加载值
(3)重载计数值喂狗
向IWDG_KR写入0xAAAA,刷新计数器的值,喂狗
IWDG_ReloadCounter();
(4)启动看门狗
向 IWDG_KR 写入 0XCCCC
IWDG_Enable(); //使能 IWDG
- void IWDG_Init(u8 prer,u16 rlr)
- {
- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
- IWDG_SetPrescaler(uint8_t IWDG_Prescaler);
- IWDG_SetReload(uint16_t Reload);
- IWDG_ReloadCounter();
- IWDG_ReloadCounter();
- }
- void IWDG_Feed(void)
- {
- IWDG->KR=0xAAAA;
- }
通过按键来喂狗,如果喂狗成功,则亮绿灯,如果喂狗失败的话,系统重启, 程序重新执行。
- int main(void)
- {
- LED_GPIO_Config();
-
- /* 检测独立看门狗复位是否被设置 */
- if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST)!= RESET)
- {
- /*独立看门狗复位了,红灯亮*/
- LED_RED;
- RCC_ClearFlag();
- }
- else
- {
- lED_BLUE;
- }
-
- Key_GPIO_Config();
-
- /*4分频,重载值625,溢出时间1s*/
- IWDG_Init(4,625);
-
- while(1)
- {
- if(Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON)
- {
- IWDG_Feed();
- LED_GREEN;
- }
- }
- }
while 部分是我们在项目中具体需要写的代码,这部分的程序可以用独立看门狗来监控,
- 如果我们知道这部分代码的执行时间,比如是 500ms,那么我们可以设置独立看门狗的溢出时间是510ms,比 500ms 多一点;
- 如果要被监控的程序没有跑飞正常执行的话,那么执行完毕之后就会执行喂狗的程序,如果程序跑飞了那程序就会超时,到达不了喂狗的程序,此时就会产生系统复位;
- 但是也不排除程序跑飞了又跑回来了,刚好喂狗了,歪打正着。所以要想更精确的监控程序,可以使用窗口看门狗,窗口看门狗规定必须在规定的窗口时间内喂狗,早了不行,晚了也不行。
- 项目中遇到的问题:
- 问题:板子第一次烧程序是好的,第二次烧程序,板子挂掉;
- 第一次烧好代码,喂狗程序启动,代码不会复位,代码正常运行
- 第二次要把代码烧进入,必须把看门狗断开,让板子复位,重启一下,烧入新代码。