基本概念
独立看门狗
驱动程序分析
//看门狗定时时间计算公式:Tout=(预分频值*重装载值)/40 (单位:ms)
//当前pre为64,rlr为625,计算得到Tout时间为1秒(大概值)。
#define pre IWDG_Prescaler_64 //分频值范围:4,8,16,32,64,128,256
#define rlr 625 //重装载值范围:0~0xFFF(4095)
设置预分频值可对独立看门狗内独立40kHz时钟进行分频
void IWDG_Init(void){ //初始化独立看门狗
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能对寄存器IWDG_PR和IWDG_RLR的写操作
IWDG_SetPrescaler(pre); //设置IWDG预分频值
IWDG_SetReload(rlr); //设置IWDG重装载值
IWDG_ReloadCounter(); //按照IWDG重装载寄存器的值重装载IWDG计数器
IWDG_Enable(); //使能IWDG
}
void IWDG_Feed(void){ //喂狗程序
IWDG_ReloadCounter();//固件库的喂狗函数
}
主函数中的调用
int main (void){//主程序
delay_ms(500); //上电时等待其他器件就绪
RCC_Configuration(); //系统时钟初始化
RELAY_Init();//继电器初始化
LED_Init();//LED
KEY_Init();//KEY
I2C_Configuration();//I2C初始化
OLED0561_Init(); //OLED初始化---------------"
OLED_DISPLAY_8x16_BUFFER(0," IWDG TEST "); //显示字符串
OLED_DISPLAY_8x16_BUFFER(4," RESET! "); //显示字符串
delay_ms(800); //
OLED_DISPLAY_8x16_BUFFER(4," "); //显示字符串
IWDG_Init(); //初始化并启动独立看门狗
while(1){
IWDG_Feed(); //喂狗
if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){
delay_s(2); //延时2秒,使程序不能喂狗而导致复制
}
}
}
主要调用以下两条:
IWDG_Init(); //初始化并启动独立看门狗
IWDG_Feed(); //喂狗
窗口看门狗
设定值不可以小于0x40,否则没有意义
喂狗时间区间位于上窗口边界和下窗口边界之间
中断的意义在于进行一些收尾工作,另外,窗口看门狗的主要作用是检验系统运作的时效性
驱动程序分析
//窗口看门狗定时时间计算公式:
//上窗口超时时间(单位us) = 4096*预分频值*(计数器初始值-窗口值)/APB1时钟频率(单位MHz)
//下窗口超时时间(单位us) = 4096*预分频值*(计数器初始值-0x40)/APB1时钟频率(单位MHz)
#define WWDG_CNT 0x7F //计数器初始值,范围:0x40~0x7F
#define wr 0x50 //窗口值,范围:0x40~0x7F
#define fprer WWDG_Prescaler_8 //预分频值,取值:1,2,4,8
//如上三个值是:0x7f,0x50,8时,上窗口48MS,下窗口64MS。
void WWDG_Init(void){ //初始化窗口看门狗
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能
WWDG_SetPrescaler(fprer); //设置 IWDG 预分频值
WWDG_SetWindowValue(wr); //设置窗口值
WWDG_Enable(WWDG_CNT); //使能看门狗,设置 counter
WWDG_ClearFlag(); //清除提前唤醒中断标志位
WWDG_NVIC_Init(); //初始化窗口看门狗 NVIC
WWDG_EnableIT(); //开启窗口看门狗中断 //若不使用看门狗中断,可删除上述3条
}
void WWDG_NVIC_Init(void){ //窗口看门狗中断服务程序(被WWDG_Init调用)就是看门狗中断初始化程序
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 初始化
}
void WWDG_Feed(void){ //窗口喂狗程序
WWDG_SetCounter(WWDG_CNT); //固件库的喂狗函数
}
void WWDG_IRQHandler(void){ //窗口看门狗中断处理程序
WWDG_ClearFlag(); //清除提前唤醒中断标志位
//此处加入在复位前需要处理的工作或保存数据
}
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能
由于窗口看门狗没有独立时钟,所以在初始化程序中要开启窗口看门狗对应的时钟
主函数中的调用
int main (void){//主程序
delay_ms(500); //上电时等待其他器件就绪
RCC_Configuration(); //系统时钟初始化
RELAY_Init();//继电器初始化
LED_Init();//LED
KEY_Init();//KEY
I2C_Configuration();//I2C初始化
OLED0561_Init(); //OLED初始化---------------"
OLED_DISPLAY_8x16_BUFFER(0," WWDG TEST "); //显示字符串
OLED_DISPLAY_8x16_BUFFER(4," RESET! "); //显示字符串
delay_ms(800); //
OLED_DISPLAY_8x16_BUFFER(4," "); //显示字符串
WWDG_Init(); //初始化并启动独立看门狗
while(1){
delay_ms(54); //用延时找到喂狗的窗口时间
WWDG_Feed(); //喂狗
if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){
delay_s(2); //延时2秒,使程序不能喂狗而导致复制
}
}
}
WWDG_Init(); //初始化并启动独立看门狗
WWDG_Feed(); //喂狗