本帖最后由 kingpage 于 2016-3-4 15:23 编辑
按照原子所提供的窗口看门狗的代码如下:
[mw_shl_code=c,true]//保存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,u8 fprer)
{
RCC->APB1ENR|=1<<11; //使能wwdg时钟
WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT.
WWDG->CFR|=fprer<<7; //PCLK1/4096再除2^fprer
WWDG->CFR&=0XFF80;
WWDG->CFR|=wr; //设定窗口值
WWDG->CR|=WWDG_CNT; //设定计数器值
WWDG->CR|=1<<7; //开启看门狗
MY_NVIC_Init(2,3,WWDG_IRQn,2);//抢占2,子优先级3,组2
WWDG->SR=0X00; //清除提前唤醒中断标志位
WWDG->CFR|=1<<9; //使能提前唤醒中断
}
//重设置WWDG计数器的值
void WWDG_Set_Counter(u8 cnt)
{
WWDG->CR =(cnt&0x7F);//重设置7位计数器
}
//窗口看门狗中断服务程序
void WWDG_IRQHandler(void)
{
WWDG_Set_Counter(WWDG_CNT);//重设窗口看门狗的值!
WWDG->SR=0X00;//清除提前唤醒中断标志位
LED1=!LED1;
}[/mw_shl_code]
其中,在看门狗初始化WWDG_Init函数中,按照这样的代码顺序是没问题的,能正常地进入WWDG_IRQHandler函数进行喂狗。但如果把WWDG_Init函数中的WWDG->CR|=1<<7; //开启看门狗.这一行代码的位置放到同样是WWDG_Init函数:
[mw_shl_code=c,true]MY_NVIC_Init(2,3,WWDG_IRQn,2);//抢占2,子优先级3,组2
WWDG->SR=0X00; //清除提前唤醒中断标志位
WWDG->CFR|=1<<9; //使能提前唤醒中断[/mw_shl_code]
中的任何一行代码后面,例如初始化代码改为:
[mw_shl_code=c,true]void WWDG_Init(u8 tr,u8 wr,u8 fprer)
{
RCC->APB1ENR|=1<<11; //使能wwdg时钟
WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT.
WWDG->CFR|=fprer<<7; //PCLK1/4096再除2^fprer
WWDG->CFR&=0XFF80;
WWDG->CFR|=wr; //设定窗口值
WWDG->CR|=WWDG_CNT; //设定计数器值
MY_NVIC_Init(2,3,WWDG_IRQn,2);//抢占2,子优先级3,组2
WWDG->SR=0X00; //清除提前唤醒中断标志位
WWDG->CFR|=1<<9; //使能提前唤醒中断
WWDG->CR|=1<<7; //开启看门狗
} [/mw_shl_code]
看门狗就会出现不断地产生复位的情况。按照我的理解应该是把看门狗所有的配置(包括它相关的寄存器以及中断分组等)都设置好,再开启看门狗才是个正确的代码运行顺序啊,为何"开启看门狗"这句代码放在后面就会产生不断复位的问题?
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
使能窗口看门狗的时候,WWDG_SR中的EWIF位就马上被置位了(具体为什么我也不清楚),加上我们使能了中断,所以程序会马上进入中断。我们在中断服务程序里面喂狗,按原子哥的看门狗例程[mw_shl_code=c,true]WWDG_Init(0X7F,0X5F,3); //计数器值为7f,窗口寄存器为5f,分频数为8 [/mw_shl_code] ,窗口的值比计数器的值小(我们的中断服务程序是在窗口外重新加载计数器),所以就马上复位了。
解决方法有两个:
一、在初始化看门狗的时候,窗口的值比计数器的重装值大。[mw_shl_code=c,true]WWDG_Init(0x70,0x7e,WWDG_Prescaler_8);[/mw_shl_code]
二、在使能看门狗之后,先清除一下中断标志位,然后再使能中断。(这时候窗口的值在初始化的时候就可以比计数器的值小)
[mw_shl_code=c,true]uint8_t WWDG_CNT = 0x7f;
void WWDG_Init(uint8_t tr,uint8_t wr,uint32_t fprer)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
WWDG_CNT = tr & WWDG_CNT; ///设置重装值
WWDG_SetPrescaler(fprer);//设置分频系数
WWDG_SetWindowValue(wr);//设置窗口的值
WWDG_NVIC_Init(); //配置中断优先级
WWDG_Enable(WWDG_CNT);//使能看门狗
WWDG_ClearFlag(); //清除中断标志位
WWDG_EnableIT(); //使能中断
}[/mw_shl_code]
一周热门 更多>