打印
[应用相关]

STM32窗口看门狗_原子战舰WWDG例程学习笔记

[复制链接]
589|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

针对学习STM32窗口看门狗和原子战舰所给的WWDG例程时候,存在的问题做如下记录。

1. WWDG超时公式推导1.1 WWDG工作示意图

1.2 WWDG超时公式推导

(1) 上窗口的值可以只有设定,7位二进制数最大只可以设定为127(0x7F),最小又必须大于下窗口的0x40,所以其取值范围为64~127(即:0x40~0x7F)


(2) 配置寄存器WWDG->CFR



窗口看门狗的时钟来自于PCLK1,在时钟配置中,其频率为外部时钟经倍频器后的二分频时钟,即为36MHz

(3)依据上述分析知,窗口时间计算公式为:

上窗口时间: T_min

=  (WWDG_CR[6:0] - WWDG_CFR[6:0])/(Tck/(2^WDGTB))(us)

=  (WWDG_CR[6:0] - WWDG_CFR[6:0])/((Tpck1/4096)/(2^WDGTB))(us)

=  4096 * (2^WDGTB)*(WWDG_CR[6:0] -WWDG_CFR[6:0])/(72/2) (us)

=  4096 *(2^WDGTB)*(WWDG_CR[6:0] - WWDG_CFR[6:0])/36 (us)


下窗口时间: T_max = 4096 * (2^WDGTB)*(WWDG_CR[6:0] - 0x3F)/36(us)


窗口看门狗的超时公式(刷新时间公式):

Twwdg = T_max - T_min

= 4096 *(2^WDGTB)*(WWDG_CFR[6:0] - 0x3F)/36 (us)

= 4096 *(2^WDGTB)*(WWDG_CFR[6:0] - 63)/36 (us)

又因为 WWDG_CFR[6:0]取值范围是:0~127,

(WWDG_CFR[6:0] –63)>0,

所以,

1<= (WWDG_CFR[6:0] – 63) <= 127-63=64

又因为 一个6位二进制X[5:0]数值范围是0~63,

1 <=  X[5:0]+1 <= 64

所以,

上式可以表述为:

Twwdg = 4096 * (2^WDGTB)*(T[5:0]+1)/36 (us)

  

(4)依据上式,可以计算出WWDG的定时时间范围:

WDGTB(计数器分频值)

最早喂狗时间/us

最晚喂狗时间/ms

0

113

7.28

1

227

14.56

2

455

29.12

3

910

58.25



沙发
幸福小强|  楼主 | 2018-6-26 11:40 | 只看该作者
2. 原子战舰WWDG库函数例程存在的问题
2.1 问题描述
        正常情况下,烧录原子战舰所提供的WWDG库函数(v3.5)例程,会看到起初红灯点亮,后熄灭,黄灯开始闪烁。但是,烧录该程序,只看到红灯闪烁。这说明了WWDG产生了中断,但是中断函数中的黄灯闪烁语句(LED1=~LED1)并没有执行。

2.2 问题解决
针对上述问题描述,可排除WWDG初始化错误的问题(因为红灯LED0在闪烁,说明WWDG已经产生的复位),定位到中断初始化失败或中断函数编写错误的问题。中断函数比较简单,检查后可以排除中断函数编写错误的问题。

下面,针对中断初始化函数进行检查。检查后,可以发现原例程中缺失了中断通道使能设置,即“NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;    //通道使能”。代码修改前后对比如下所示。修改后,再次烧录执行,会发现现象正常:起初红灯点亮,后熄灭,黄灯开始闪烁。

(1)中断初始化原始代码:
//WWDG中断初始化  
void WWDG_NVIC_Init()  
{  
         NVIC_InitTypeDef NVIC_InitStructure;  
         NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;    //WWDG中断  
         //抢占2 子优先级3 组2  
         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;   
         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;   
         NVIC_Init(&NVIC_InitStructure);//NVIC 初始化  
}  

2)中断初始化修改后代码:
//WWDG中断初始化  
void WWDG_NVIC_Init()  
{  
         NVIC_InitTypeDef NVIC_InitStructure;  
         NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;    //WWDG中断  
     //抢占2 子优先级3 组2  
         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;   
         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;   
         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;    //通道使能  
         NVIC_Init(&NVIC_InitStructure);//NVIC 初始化  
}  

使用特权

评论回复
板凳
幸福小强|  楼主 | 2018-6-26 11:41 | 只看该作者
2.3 问题补充——WWDG初始化时库函数调用顺序
(1)对于下述的WWDG初始化函数,烧录后,运行正常。但是,将WWDG使能并装载初始值语句WWDG_Enable(WWDG_CNT)放于清除提前唤醒中断标志位语句WWDG_ClearFlag()和开启窗口看门狗中断语句WWDG_EnableIT()之后,再次执行,现象异常:只有红色灯在闪烁,黄色灯一直熄灭。

正确程序:
//保存WWDG计数器的设置值,默认为最大.  
u8 WWDG_CNT=0x7f;  
//初始化窗口看门狗      
//tr   :T[6:0],计数器值  
//wr   :W[6:0],窗口值  
//fprer:分频系数(WDGTB),仅最低2位有效  
//Fwwdg=PCLK1/(4096*2^fprer).  
void WWDG_Init(u8 tr,u8 wr,u32 fprer)  
{  
         RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);  //   WWDG时钟使能  
   
         WWDG_CNT=tr&WWDG_CNT;   //初始化WWDG_CNT.   
         WWDG_SetPrescaler(fprer);////设置IWDG预分频值  
         WWDG_SetWindowValue(wr);//设置窗口值  
         WWDG_NVIC_Init();//初始化窗口看门狗 NVIC  
WWDG_Enable(WWDG_CNT);    //使能WWDG 并装载初始值  
         WWDG_ClearFlag();//清除提前唤醒中断标志位  
         WWDG_EnableIT(); //开启窗口看门狗中断  
}  

异常程序:
//保存WWDG计数器的设置值,默认为最大.  
u8 WWDG_CNT=0x7f;  
//初始化窗口看门狗      
//tr   :T[6:0],计数器值  
//wr   :W[6:0],窗口值  
//fprer:分频系数(WDGTB),仅最低2位有效  
//Fwwdg=PCLK1/(4096*2^fprer).  
void WWDG_Init(u8 tr,u8 wr,u32 fprer)  
{  
         RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);  //   WWDG时钟使能  
   
         WWDG_CNT=tr&WWDG_CNT;   //初始化WWDG_CNT.   
         WWDG_SetPrescaler(fprer);////设置IWDG预分频值  
         WWDG_SetWindowValue(wr);//设置窗口值  
         WWDG_NVIC_Init();//初始化窗口看门狗 NVIC  
         WWDG_ClearFlag();//清除提前唤醒中断标志位  
         WWDG_EnableIT(); //开启窗口看门狗中断  
         WWDG_Enable(WWDG_CNT);    //使能WWDG 并装载初始值  
}  

(2)错因分析

执行WWDG_Enable(WWDG_CNT)语句,会使能WWDG,并将初始值CNT装载至计数器中。执行此句,还会将WWDG_SR的EWIF置1,造成程序无法进入中断处理函数。

用JLINK在keil中对此进行单步调试可以发现,执行WWDG_Enable(WWDG_CNT)语句之后,WWDG_SR的EWIF被置1,如下图所示。

第一步:执行WWDG_Enable(WWDG_CNT)语句之前,状态寄存器WWDG_SR=0x0000,即EWIF=0

第二步: 执行WWDG_Enable(WWDG_CNT)语句之后,状态寄存器WWDG_SR=0x0001,即EWIF=1



使用特权

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

本版积分规则

120

主题

1464

帖子

2

粉丝