打印
[STM32F1]

STM32F103独立看门狗不复位

[复制链接]
5384|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhenxing2000|  楼主 | 2016-8-20 18:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
void IWDG_Init()
{
        IWDG->KR   = 0X5555;   
        IWDG->PR   = 2;        
        IWDG->RLR  = 0X7FF;     
        IWDG->KR   = 0XAAAA;   
        IWDG->KR   = 0XCCCC;   
}

void IWDG_Feed()
{
        IWDG->KR   = 0XAAAA;   
}

int main(void)
{
        KEY_Init();
        Timer2_Init();
        HC595_Init();
        IWDG_Init();
        while(1)
        {       
                Disp_Data(dis_data);
        }
}


以上是独立看门狗的配置函数,以及main函数。
Disp_Data(dis_data)是一个显示函数,显示的数值每秒加1,如果没有喂狗指令的话,应该是一直复位,也就是显示的数字一直复位,但是现在看不到复位效果,已经试验了好几块板子了,都是这种情况。反复查看了数据手册,认为寄存器配置没有什么错误。
请大家帮忙分析一下原因。谢谢大家。
沙发
天灵灵地灵灵| | 2016-8-21 08:57 | 只看该作者

实验现象:

开始LED1亮,LED2熄灭,若不隔时间按KEY1则发现LED2因独立看门狗的作用使系统复位而不断闪烁,若间断的按KEY1则发现LED2不会闪烁,表明没有复位。

实验平台:

基于STM32F103C8T6的彩屏开发板

操作步骤:

1)向IWDG_KR 写入0X5555。
通过这步,我们取消IWDG_PR 和IWDG_RLR 的写保护,使后面可以操作这两个寄存器。
设置 IWDG_PR 和IWDG_RLR 的值。
这两步设置看门狗的分频系数,和重装载的值。由此,就可以知道看门狗的喂狗时间(也
就是看门狗溢出时间),该时间的计算方式为:
Tout=((4×2^prer) ×rlr) /40
其中Tout 为看门狗溢出时间(单位为ms);prer 为看门狗时钟预分频值(IWDG_PR 值),
范围为0~7;rlr 为看门狗的重装载值(IWDG_RLR 的值);
比如我们设定 prer 值为4,rlr 值为625,那么就可以得到Tout=64×625/40=1000ms,这样,
看门狗的溢出时间就是1s,只要你在一秒钟之内,有一次写入0XAAAA 到IWDG_KR,就不会导致看门狗复位(当然写入多次也是可以的)。这里需要提醒大家的是,看门狗的时钟不是准
确的40Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。

2)向IWDG_KR 写入0XAAAA。
通过这句,将使STM32 重新加载IWDG_RLR 的值到看门狗计数器里面。也可以用该命令
来喂狗。
3)向IWDG_KR 写入0XCCCC。
通过这句,来启动 STM32 的看门狗。注意IWDG 在一旦启用,就不能再被关闭!想要关
闭,只能重启,并且重启之后不能打开IWDG,否则问题依旧,所以在这里提醒大家,如果不
用IWDG 的话,就不要去打开它,免得麻烦。
通过上面 3 个步骤,我们就可以启动STM32 的看门狗了,使能了看门狗,在程序里面就
必须间隔一定时间喂狗,否则将导致程序复位。利用这一点,我们通过一个LED 灯来指
示程序是否重启,来验证STM32 的独立看门狗。

程序部分代码:

     watchdong.h

#ifndef WATCHDOG_H
#define WATCHDOG_H
void WatchDog_Init(u8, u16);//申明看门狗的初始化函数
void WatchDog_Feed(void);//申明喂狗的函数
#endif

    watchdong.c

#include"common.h"
#include"watchdog.h"
//看门狗初始化,参数:prer-分频,reld-计数器重装载值
void WatchDog_Init(u8 prer, u16 reld)
{
   IWDG->KR=0x5555; //允许访问PR和RLR寄存器
   IWDG->PR=prer;  //设置分频
   IWDG->RLR=reld; //设定计数器初值
   IWDG->KR=0xaaaa; //初次装初值
   IWDG->KR=0xcccc;  //启动看门狗定时器
}

//喂狗
void WatchDog_Feed(void)
{
IWDG->KR=0xaaaa;
}
该代码就2 个函数,void IWDG_Init(u8 prer,u16 rlr)是独立看门狗初始化函数,就是按照
上面介绍的步骤来初始化独立看门狗的。该函数有2 个参数,分别用来设置与预分频数与重装
寄存器的值的。通过这两个参数,就可以大概知道看门狗复位的时间周期为多少了。其计算方
式上面有详细的介绍,这里不再多说了。
void IWDG_Feed(void)函数,该函数用来喂狗,因为STM32 的喂狗只需要向键值寄存器写
入0XAAAA 即可,

    主函数
#include<stm32f10x_lib.h>
#include"common.h"
#include"led.h"
#include"key.h"
#include"watchdog.h"
int main(void)
{
u8 temp2;
Stm32_Clock_Init(9);   //系统时钟设置
delay_init(72);    //延时初始化
LED_Init();    //LED初始化
KEY_Init();
WatchDog_Init(4,625); //看门狗初始化
LED1=1;
LED2=0;
while(1)
{
   temp2=KEY_Scan(); //读取按键值
   if(temp2==1)
    WatchDog_Feed(); //喂狗
  
}
}


使用特权

评论回复
板凳
天灵灵地灵灵| | 2016-8-21 08:58 | 只看该作者

STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效。

看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路就是为了避免这种情况的发生。看门狗的作用就是在一定时间内(通过定时计数器实现)没有接收喂狗信号(表示 MCU 已经挂了),便实现处理器的自动复位重启(发送复位信号) 。

在键值寄存器(IWDG_KR)中写入 0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值 0xFFF 递减计数。当计数器计数到末尾 0x000 时,会产生一个复位信号(IWDG_RESET)。无论何时,只要键寄存器 IWDG_KR 中被写入 0xAAAA,  IWDG_RLR 中的值就会被重新加载到计数器中从而避免产生看门狗复位  。

IWDG_PR 和 IWDG_RLR 寄存器具有写保护功能。要修改这两个寄存器的值,必须先向IWDG_KR 寄存器中写入 0x5555。将其他值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入 0xAAAA)也会启动写保护功能。

只要对以上三个寄存器进行相应的设置,我们就可以启动 STM32 的独立看门狗,启动过程可以按如下步骤实现(独立看门狗相关的库函数和定义分布在文件 stm32f10x_iwdg.h 和stm32f10x_iwdg.c 中) :

1)取消寄存器写保护(向 IWDG_KR 写入 0X5555)

通过这步,我们取消 IWDG_PR 和 IWDG_RLR 的写保护,使后面可以操作这两个寄存器,设置 IWDG_PR 和 IWDG_RLR 的值。这在库函数中的实现函数是:

IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);

2)设置独立看门狗的预分频系数和重装载值

设置看门狗的分频系数的函数是:

void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);  //设置 IWDG 预分频值

设置看门狗的重装载值的函数是:

void IWDG_SetReload(uint16_t Reload); //设置 IWDG 重装载值

设置好看门狗的分频系数 prer 和重装载值就可以知道看门狗的喂狗时间 (也就是看门狗溢出时间) ,该时间的计算方式为:

Tout=((4×2^prer)  ×rlr) /40

其中 Tout 为看门狗溢出时间(单位为 ms) ;prer 为看门狗时钟预分频值(IWDG_PR 值),范围为 0~7;rlr 为看门狗的重装载值(IWDG_RLR 的值) ;

比如我们设定 prer 值为 4, rlr 值为 625,那么就可以得到 Tout=64×625/40=1000ms,这样,看门狗的溢出时间就是 1s,只要你在一秒钟之内,有一次写入 0XAAAA 到 IWDG_KR,就不会导致看门狗复位(当然写入多次也是可以的)。这里需要提醒大家的是,看门狗的时钟不是准确的 40Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。

3)重载计数值喂狗(向 IWDG_KR 写入 0XAAAA)

库函数里面重载计数值的函数是:

IWDG_ReloadCounter();   //按照 IWDG 重装载寄存器的值重装载 IWDG 计数器

通过这句,将使 STM32 重新加载 IWDG_RLR 的值到看门狗计数器里面。 即实现独立看门狗的喂狗操作。

4)  启动看门狗(向 IWDG_KR 写入 0XCCCC)

库函数里面启动独立看门狗的函数是:

IWDG_Enable();   //使能 IWDG

通过这句,来启动 STM32 的看门狗。注意 IWDG 在一旦启用,就不能再被关闭!想要关闭,只能重启,并且重启之后不能打开 IWDG,否则问题依旧,所以在这里提醒大家,如果不用 IWDG 的话,就不要去打开它,免得麻烦。


使用特权

评论回复
地板
天灵灵地灵灵| | 2016-8-21 08:59 | 只看该作者
#include "sys.h"
#include "iwdg.h"

/**
* 初始化独立看门狗
* prer:分频数:0~7(只有低 3 位有效!)
* 分频因子=4*2^prer.但最大值只能是 256!
* rlr:重装载寄存器值:低 11 位有效.
* 时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
*/
void IWDG_Init(u8 prer,u16 rlr)
{
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); /* 使能对寄存器IWDG_PR和IWDG_RLR的写操作*/
    IWDG_SetPrescaler(prer);    /*设置IWDG预分频值:设置IWDG预分频值*/
    IWDG_SetReload(rlr);     /*设置IWDG重装载值*/
    IWDG_ReloadCounter();    /*按照IWDG重装载寄存器的值重装载IWDG计数器*/
    IWDG_Enable();        /*使能IWDG*/
}

/**
* 喂独立看门狗
*/
void IWDG_Feed(void)
{
    IWDG_ReloadCounter();    /*reload*/
}

使用特权

评论回复
5
lefeng| | 2016-8-21 21:19 | 只看该作者
看门狗的时钟不是准确的 40Khz,所以在喂狗的时候,最好不要太晚了

使用特权

评论回复
6
Snow7| | 2016-8-21 22:25 | 只看该作者
是否正常启动了,是否正确喂狗了

使用特权

评论回复
7
zhenxing2000|  楼主 | 2016-8-25 16:21 | 只看该作者
天灵灵地灵灵 发表于 2016-8-21 08:57
实验现象:开始LED1亮,LED2熄灭,若不隔时间按KEY1则发现LED2因独立看门狗的作用使系统复位而 ...

咱复制原子的就没有意思了,讨论讨论自己的想法多好。

使用特权

评论回复
8
zhenxing2000|  楼主 | 2016-8-25 16:22 | 只看该作者
Snow7 发表于 2016-8-21 22:25
是否正常启动了,是否正确喂狗了

正常启动了

使用特权

评论回复
9
zhenxing2000|  楼主 | 2016-8-25 16:23 | 只看该作者
lefeng 发表于 2016-8-21 21:19
看门狗的时钟不是准确的 40Khz,所以在喂狗的时候,最好不要太晚了

40Khz是不稳定的,喂狗时间控制的应该没问题

使用特权

评论回复
10
neeringstu| | 2016-8-25 21:07 | 只看该作者
天灵灵地灵灵 发表于 2016-8-21 08:57
实验现象:开始LED1亮,LED2熄灭,若不隔时间按KEY1则发现LED2因独立看门狗的作用使系统复位而 ...

电路图是什么样子的,感觉电路是不是焊接有问题

使用特权

评论回复
11
kekaodexushi| | 2017-7-12 10:31 | 只看该作者
搞定没,是啥原因导致不喂狗也不会复位的?

使用特权

评论回复
12
tangshengye007| | 2018-5-4 11:04 | 只看该作者

怎么解决的?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

217

帖子

1

粉丝