(88)IWDG 例题:
++以上是开启 IWDG 的步骤,接着是使用的库函数:
++
voidIWDG_WriteAccessCmd(uint16_tIWDG_WriteAccess);//写使能控制,操作键寄存器voidIWDG_SetPrescaler(uint8_tIWDG_Prescaler);//写预分频器voidIWDG_SetReload(uint16_tReload);//写重装值voidIWDG_ReloadCounter(void);//读取重装寄存器到递减计数器,喂狗voidIWDG_Enable(void);//启动独立看门狗FlagStatusIWDG_GetFlagStatus(uint16_tIWDG_FLAG);//获取标志位状态++
++
++dou 包的解释:
++原来库函数的内容还是关联到了寄存器里:
++
intmain(void){/*模块初始化*/OLED_Init();//OLED初始化Key_Init();//按键初始化/*显示静态字符串*/OLED_ShowString(1,1,"IWDG TEST");/*判断复位信号来源*/// 比如不喂狗导致了复位if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST)==SET)//如果是独立看门狗复位{OLED_ShowString(2,1,"IWDGRST");//OLED 闪烁 IWDGRST 字符串Delay_ms(500);OLED_ShowString(2,1," ");Delay_ms(100);RCC_ClearFlag();//清除标志位,这里必须手动清除,否则该 IWDGRST 标志不会消失}else//否则,即为其他复位{OLED_ShowString(3,1,"RST");//OLED 闪烁 RST 字符串Delay_ms(500);OLED_ShowString(3,1," ");Delay_ms(100);}/* IWDG 初始化*/IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//独立看门狗写使能IWDG_SetPrescaler(IWDG_Prescaler_16);//设置预分频为 16IWDG_SetReload(2499);//设置重装值为 2499,独立看门狗的超时时间为 1000ms// 1000ms = 0.025ms * 16 * ( 2499 + 1)// 超时时间:TIWDG = TLSI × PR预分频系数 × (RL + 1)IWDG_ReloadCounter();//重装递减计数器,喂狗.启动前先喂一次狗, 0xAAAAIWDG_Enable();//独立看门狗使能,这里会附带主动开启 LSI 时钟的,0xCCCC// 以上两句,给 key 寄存器写入了非 0x5555 的值,已经相当于重新加上写保护了,psc 与 RLwhile(1){Key_GetNum();//调用阻塞式的按键扫描函数,模拟主循环卡死IWDG_ReloadCounter();//重装递减计数器,喂狗OLED_ShowString(4,1,"FEED");//OLED 闪烁 FEED 字符串Delay_ms(200);//喂狗间隔为 200 + 600 = 800msOLED_ShowString(4,1," ");Delay_ms(600);}}++附带给出 Key_GetNum ( ) ; 的代码,以便参考:
/** * 函 数:按键获取键码 * 参 数:无 * 返 回 值:按下按键的键码值,范围:0~2,返回0代表没有按键按下 * 注意事项:此函数是阻塞式操作,当按键按住不放时,函数会卡住,直到按键松手 */uint8_tKey_GetNum(void){uint8_tKeyNum=0;//定义变量,默认键码值为0if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0)//读PB1输入寄存器的状态,如果为0,则代表按键1按下{Delay_ms(20);//延时消抖while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0);//等待按键松手Delay_ms(20);//延时消抖KeyNum=1;//置键码为1}if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==0)//读PB11输入寄存器的状态,如果为0,则代表按键2按下{Delay_ms(20);//延时消抖while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==0);//等待按键松手Delay_ms(20);//延时消抖KeyNum=2;//置键码为2}returnKeyNum;//返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0}(89)例题 2 , WWDG:
++
++WWDG 的库函数还是很大不同于 IWDG 的:
voidWWDG_DeInit(void);//恢复缺省配置voidWWDG_SetPrescaler(uint32_tWWDG_Prescaler);//写入预分频器voidWWDG_SetWindowValue(uint8_tWindowValue);//写入窗口值,value must be lower than 0x80voidWWDG_EnableIT(void);//使能中断voidWWDG_SetCounter(uint8_tCounter);//写入计数器,between 0x40 and 0x7FvoidWWDG_Enable(uint8_tCounter);//使能窗口看门狗,同时喂狗,between 0x40 and 0x7F// 使能的时候顺便喂狗,以防止复位 //同时也可以看出,这个计数器赋值,是包含了 T[6] 的FlagStatusWWDG_GetFlagStatus(void);//获取标志位voidWWDG_ClearFlag(void);//清除标志位++
++补充俩库函数的实现:
++
intmain(void){/*模块初始化*/OLED_Init();//OLED 初始化Key_Init();//按键初始化/*显示静态字符串*/OLED_ShowString(1,1,"WWDG TEST");/*判断复位信号来源*/if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST)==SET)//如果是窗口看门狗复位{OLED_ShowString(2,1,"WWDGRST");//OLED闪烁 WWDGRST 字符串Delay_ms(500);OLED_ShowString(2,1," ");Delay_ms(100);RCC_ClearFlag();//清除标志位}else//否则,即为其他复位{OLED_ShowString(3,1,"RST");//OLED 闪烁 RST 字符串Delay_ms(500);OLED_ShowString(3,1," ");Delay_ms(100);}/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);//开启 WWDG 的时钟/*WWDG初始化*/WWDG_SetPrescaler(WWDG_Prescaler_8);//设置预分频为 8,则极限喂狗区间 910us ~ 58.25ms// 以下的设计是超时时间 50ms,在剩余的 20ms 内完成喂狗,即窗口时间是第 30 ms,剩余 20 msWWDG_SetWindowValue(0x40|21);//设置窗口值,窗口时刻为第 30ms// TWIN = TPCLK1 × 4096 × WDGTB 预分频系数 × (W[5:0] + 1)// 类比,窗口值的计算 55 * 2 / 5 = 22,所以 W[5:0] = 21WWDG_Enable(0x40|54);//使能并第一次喂狗,喂狗值为 50ms// 喂狗值 50ms 的计算 50ms = 1/36000 * 4096 * 8 * (54 + 1)--> // T[5 : 0] = 54// TWWDG = TPCLK1 × 4096 × WDGTB预分频系数 × (T[5:0] + 1)/* ++++++ 以下演示的是正常情况 ++++++++*/while(1){Key_GetNum();//调用阻塞式的按键扫描函数,模拟主循环卡死OLED_ShowString(4,1,"FEED");//OLED 闪烁 FEED 字符串Delay_ms(20);//喂狗间隔为 20 + 20 = 40msOLED_ShowString(4,1," ");Delay_ms(20);// 在第 40ms 喂狗,是合法的,在喂狗窗口内WWDG_SetCounter(0x40|54);// 重装计数器,喂狗}}++
(90)
谢谢