转载自https://blog.csdn.net/lbsgrowup/article/details/47428627
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
(3)结论
WWDG使能函数必须在WWDG清除提前唤醒中断标志位和开启窗口看门狗中断之前执行。