目录
独立看门狗(IWDG)
IWDG初始化
喂狗函数(该函数在stm32f10x_iwdg.h)
窗口看门狗(WWDG)
WWDG初始化
中断函数
main函数
简单而言,看门狗就是设置计数值,计数值在每个时钟跳变沿减一,减到零时把系统复位
复位时间=( 1/( 看门狗RC振荡器频率 / 分频值 ))×重载值
1s复位代码如下:
计算:1s=(1/ (40,000/32) ) × 1250
void IWDG_Configuration(void)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能或者失能对寄存器 IWDG_PR 和 IWDG_RLR 的写操作,写入0x5555使能写操作,写入0x0000失能写操作
IWDG_SetPrescaler(IWDG_Prescaler_32); //设置 IWDG 预分频值,分频值可以是4,8,16,32,64,128,256(PR寄存器)
IWDG_SetReload(1250); //设置 IWDG 重装载值(RLR寄存器)
IWDG_ReloadCounter(); //把IWDG 重装载寄存器的值重装载 IWDG 计数器,喂狗(具体是把0xAAAA写入KR寄存器,使得重载值写入IWDG计数器)
IWDG_Enable(); //使能 IWDG(具体是入0xCCCC到KR寄存器,使能看门狗)
}
IWDG_ReloadCounter();
中断和非中断方法都需要喂狗
默认APB1时钟频率(PCLK1)=AHB时钟频率(HCLK)/2
复位时间=(1/((APB1时钟频率/4096)/分频值 ))×(计数值-窗口值)
以下为LED亮0.5秒,灭0.5秒的代码
void WWDG_Init(u8 count,u8 window)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); //使能WWDG时钟
count&=0x7F; //防止count的值超过0x7F
WWDG_SetPrescaler(WWDG_Prescaler_8);//设置IWDG预分频值
WWDG_SetWindowValue(window);//设置窗口值,此值要要在0x40~0x7F之间,使用窗口看门狗中断时,该值固定为0x40
WWDG_Enable(count); //使能看门狗,设置count,count值要在0x40~0x7F之间
WWDG_ClearFlag();//清除提前唤醒中断标志位
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //WWDG中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占2,子优先级3,组2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //抢占2,子优先级3,组2
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);//NVIC初始化
WWDG_EnableIT(); //开启窗口看门狗中断
}
void WWDG_IRQHandler(void)
{
static unsigned char i=0;
WWDG_SetCounter(0x7F); //当禁掉此句后,窗口看门狗将产生复位
WWDG_ClearFlag(); //清除提前唤醒中断标志位
i++;
if(i>0&&i<=10)
{
GPIO_SetBits(GPIOA,GPIO_Pin_0);
}
else if(i>10&&i<=20)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}
else
{
i=0;
}
}
void GPIO_Configuration(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
int main()
{
GPIO_Configuration();
WWDG_Init(0x7F,0x40);
while(1)
{
}
}
58ms≈(1/((36,000,000/4096)/8 ))×(0x7F-0x40)
所以以上代码实现的是58ms电平翻转一次。