7. 窗口看门狗配置过程
7.1 使能看门狗时钟:
- RCC_APB1PeriphClockCmd();
复制代码
7.2 设置分频系数:
复制代码
7.3 设置上窗口值:
复制代码
7.4 开启提前唤醒中断并分组(可选):
- WWDG_EnableIT();
- NVIC_Init();
复制代码
7.5 使能看门狗:
复制代码
7.6 喂狗:
复制代码
7.7 编写中断服务函数
复制代码
8. 实验代码部分解读
跑马灯、蜂鸣器、按键输入、串口等相关代码可参考以前的文章。
8.1 exti.c代码解读
将KEY2键作为外部中断,按下时,
- #include "led.h"
- #include "beep.h"
- #include "key.h"
- #include "exti.h"
- #include "usart.h"
- #include "sys.h"
- //编写EXTIx_Init初始化函数,包括中断线配置和每个中断线的优先级配置//
- void EXTIx_Init(void)
- {
- //*申明一个结构体,名字为EXTI_InitStructure,结构体原型由EXTI_InitTypeDef确定*//
- EXTI_InitTypeDef EXTI_InitStructure;
- //*申明一个结构体,名字为NVIC_InitStructure,结构体原型由NVIC_InitTypeDef确定*//
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟AFIO//
- //设置I/O口与中断线的映射关系//
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2); //PE2对应KEY2//
- //PE2中断线初始化配置,中断模式,下降沿触发,使能//
- EXTI_InitStructure.EXTI_Line=EXTI_Line2; //GPIOx,Pin2对应EXTI2中断线//
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式//
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //双边沿触发//
- EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能//
- //中断线初始化,GPIOE,Pin2映射到EXTI2中断线,中断模式,下降沿触发,使能//
- EXTI_Init(&EXTI_InitStructure);
- //对上述配置好的每个中断进行优先级初始化//
- NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //选择EXTI2外部中断通道,即PE2,即KEY2
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //响应优先级2
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能//
- NVIC_Init(&NVIC_InitStructure);
- }
- //编写EXTI2中断服务函数,对应KEY2按键,对独立看门狗的相应工作//
- void EXTI2_IRQHandler(void)
- {
- if(KEY2==0) //判断KEY2按键是按下还是松开,按下则KEY2==0,if(1)
- {
- BEEP=1; //按下时蜂鸣器叫//
- LED0=1; //按下时LED0灭//
- printf("KEY2按下,对独立看门狗进行手动喂狗(在main.c中执行),LED0灭,蜂鸣器叫\r\n");
- }
- else
- {
- BEEP=0; //松开时蜂鸣器不叫//
- LED0=0; //松开时LED0亮//
- IWDG_ReloadCounter();
- printf("KEY2松开,对独立看门狗进行手动喂狗,LED0亮,蜂鸣器不叫\r\n");
- }
- EXTI_ClearITPendingBit(EXTI_Line2); //清除LINE0上的中断标志位
- }
复制代码
8.2 wwdg.c代码解读
包括IWDG_Init和WWDG_Init初始化函数,并编写了窗口看门狗早期唤醒中断服务函数。
- #include "wdg.h"
- #include "led.h"
- #include "key.h"
- #include "usart.h"
- //编写IWDG_Init初始化函数//
- void IWDG_Init(u8 IWDG_PR,u16 IWDG_RLR)
- {
- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//取消寄存器写保护//
- IWDG_SetPrescaler(IWDG_PR); //设置独立看门狗的预分频系数//
- IWDG_SetReload(IWDG_RLR); //设置看门狗重装载值//
- IWDG_ReloadCounter(); //喂狗,否则将从0xFFF算起//
- IWDG_Enable(); //使能独立看门狗//
- }
- //定WWDG_CR控制寄存器第0~6位值,默认为最大0111 1111//
- u8 WWDG_CNT=0x7f;
- //窗口看门狗计数频率的计算公式为:Fwwdg=PCLK1/(4096*2^fprer)//
- //编写WWDG_Init初始化函数,WWDG_TV(CR寄存器0~6位计数值),WWDG_WV(用来设置上窗口值)和WWDG_PR(用来设置预分频系数)//
- void WWDG_Init(u8 WWDG_TV,u8 WWDG_WV,u32 WWDG_PR)
- {
- //先WWDG时钟使能//
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
- WWDG_CNT=WWDG_TV&WWDG_CNT; //初始化WWDG_CNT,一般0x40≤WWDG_TV≤0x7F,则实际意思是将WWDG_TV赋值给WWDG_CNT//
- WWDG_SetPrescaler(WWDG_PR); //设置WWDG预分频值//
- WWDG_SetWindowValue(WWDG_WV); //设置上窗口值,且0x40≤WWDG_WV≤0x7F//
- WWDG_Enable(WWDG_CNT); //使能看门狗,并载入计数值,且0x40≤WWDG_CNT≤0x7F//
- WWDG_ClearFlag(); //清除提前唤醒中断标志位
- WWDG_NVIC_Init(); //初始化窗口看门狗中断服务函数//
- WWDG_EnableIT(); //开启窗口看门狗中断,即到计数到0x40时,发生一次中断//
- }
- //重置WWDG计数器的值,即执行WWDG_Enable(cnt)函数//
- void WWDG_Set_Counter(u8 cnt)
- {
- WWDG_Enable(cnt); //使能看门狗,并载入计数值,且0x40≤cnt≤0x7F//
- }
- //编写窗口看门狗中断服务初始化函数//
- void WWDG_NVIC_Init()
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //WWDG中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级为2
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //响应优先级为3
- NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- //编写窗口看门狗中断服务函数//
- void WWDG_IRQHandler(void)
- {
- //喂狗,实际执行 WWDG_Enable(cnt)函数//
- WWDG_SetCounter(WWDG_CNT); //当禁掉此句后,窗口看门狗将产生复位//
- WWDG_ClearFlag(); //清除提前唤醒中断标志位//
- LED1=!LED1; //LED状态翻转
- if(KEY1==0) //判断KEY1按键是否按下,按下则KEY2==0,if(1)
- {
- printf("对窗口看门狗进行手动喂狗,LED1闪烁\r\n");
- }
- }
复制代码
8.3 main.c代码解读
主函数中,死循环里写了KEY2按下时,对独立看门狗的喂狗方式。
- #include "led.h"
- #include "beep.h"
- #include "key.h"
- #include "wdg.h"
- #include "exti.h"
- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- int main(void)
- {
- u8 key;
- delay_init(); //延时函数初始化//
- //设置中断优先级分组为组2:2位抢占优先级,2位响应优先级//
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- //usart1串口初始化,波特率为115200//
- LED_Init(); //LED端口初始化,LED0和LED0默认灭//
- BEEP_Init(); //初始化蜂鸣器端口,不叫//
- KEY_Init(); //按键初始化//
- EXTIx_Init(); //外部中断初始化//
- uart_init(115200); //串口USART1初始化//
- delay_ms(300);
- LED0=0; //LED0点亮//
- IWDG_Init(4,3125); //根据预分配值和重装载值确定溢出时间,根据参数,溢出时间大约为//
- WWDG_Init(0X7F,0X4F,WWDG_Prescaler_8); //设置计数器值,上窗口值,分频系数为8//
- //系统进入死循环后,LED0是亮的//
- while(1)
- {
- key=KEY_Scan(1); //支持连按//
- if(key)
- {
- switch(key)
- {
- case 3: //若KEY2按下,则对独立看门狗进行喂狗//
- IWDG_ReloadCounter();
- break;
- }
- }
- }
- }
复制代码
最后调试效果如下图
|