利用基本定时器TIM6,中断定时40ms喂狗,不产生复位
1、配置WWDG的属性
开启 WWDG 时钟
设置 WWDG 预分频器值
设置 WWDG 窗口值(这里设置成80)
启用 WWDG 并加载计数器值(这里设置成127)
/*
*--------WWDG初始化--------
* Prescaler:预分频器值,取值可以是
* WWDG_Prescaler_1: WWDG counter clock = (PCLK1/4096)/1 约10968Hz 91us
* WWDG_Prescaler_2: WWDG counter clock = (PCLK1/4096)/2 约5484Hz 182us
* WWDG_Prescaler_4: WWDG counter clock = (PCLK1/4096)/4 约2742Hz 364us
* WWDG_Prescaler_8: WWDG counter clock = (PCLK1/4096)/8 约1371Hz 728us
*
* Counter :递减计时器的值, 取值范围为: 0x7f~0x40。一般取最大值0x7f
*
* WindowValue :窗口值,取值范围为: 0x7f~0x40。最小值0x40到窗口值之间的时间内有喂狗,就不会产生复位。
*
*
* 例: Counter = 127(0x7f) (计数器最大值)
* WindowValue = 80(0x50)(用户定义的窗口上限值)
* Prescaler = WWDG_Prescaler_8(预分频器值)
*
* 728 us * (127-80) = 34216 us = 34.2ms < 刷新窗口,不产生复位 < 728 us * 64(内部下窗口的临界值,不变) = 46.6ms
* 1、在34.2ms前喂狗,系统会复位。
* 2、在46.6ms后无论怎样,系统都会复位。
* 3、在34.2ms - 46.6ms之间,喂狗,刷新计数器值,重新开始计数,系统不会复位。
*/
void WWDG_Init(uint8_t Counter, uint8_t WindowValue, uint32_t Prescaler)
{
/* 开启 WWDG 时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
/* 设置 WWDG 预分频器值 */
WWDG_SetPrescaler(Prescaler);
/* 设置 WWDG 窗口值 */
WWDG_SetWindowValue(WindowValue);
/* 启用 WWDG 并加载计数器值 */
WWDG_Enable(Counter);
}
2、喂狗操作
启用 WWDG 并加载计数器值
/* 喂狗,防止WWDG复位 */
void WWDG_Feed(void)
{
/* 启用 WWDG 并加载计数器值 */
WWDG_SetCounter(UserCounter);
}
3、配置TIM6的模式
开启TIM6的时钟
累计 TIM_Period个后产生一个更新或者中断。当定时器从0计数到399,即为400次,为一个定时周期
定时器时钟源TIMxCLK = 2 * PCLK1
PCLK1 = HCLK / 4
=> TIMxCLK=HCLK/2=SystemCoreClock/2=90MHz
设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10000Hz
初始化定时器TIM6
清除定时器更新中断标志位
开启定时器更新中断
使能定时器
void TIMx_Mode_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 开启TIMx_CLK,x[6,7]
RCC_APB1PeriphClockCmd(BASIC_TIM6_CLK, ENABLE);
/* 累计 TIM_Period个后产生一个更新或者中断*/
//当定时器从0计数到4999,即为5000次,为一个定时周期
TIM_TimeBaseStructure.TIM_Period = 400-1;
//定时器时钟源TIMxCLK = 2 * PCLK1
// PCLK1 = HCLK / 4
// => TIMxCLK=HCLK/2=SystemCoreClock/2=90MHz
// 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10000Hz
TIM_TimeBaseStructure.TIM_Prescaler = 9000-1;
// 初始化定时器TIMx, x[2,3,4,5]
TIM_TimeBaseInit(BASIC_TIM6, &TIM_TimeBaseStructure);
// 清除定时器更新中断标志位
TIM_ClearFlag(BASIC_TIM6, TIM_FLAG_Update);
// 开启定时器更新中断
TIM_ITConfig(BASIC_TIM6,TIM_IT_Update,ENABLE);
// 使能定时器
TIM_Cmd(BASIC_TIM6, ENABLE);
}
4、配置TIM6的中断模式
设置中断组为2
设置中断来源TIM6_DAC_IRQn
设置抢占优先级2
设置子优先级2
启用NVIC_IRQChannel中定义的IRQ通道
void TIMx_NVIC_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
//设置中断组为2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
//设置中断来源TIM6_DAC_IRQn
NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
//设置抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
//设置子优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
5、TIM6中断服务函数
检查TIM中断是否发生
LED电平反转
喂狗
清除TIMx的中断挂起位
void TIM6_DAC_IRQHandler(void)
{
if(TIM_GetITStatus(BASIC_TIM6, TIM_IT_Update) != RESET )
{
LEDR_TOGGLE;
WWDG_Feed();
TIM_ClearITPendingBit(BASIC_TIM6 , TIM_IT_Update);
}
}