提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
提示:这里可以添加本文要记录的大概内容:
已经写了不少32程序了,程序都是直接运行,出了问题然后人工复位。有没有一种代替人工复位的方法呢?32里面是有的,而且很简单。
提示:以下是本篇文章正文内容,下面案例可供参考
STM32的看门狗(Watchdog)是一种硬件定时器,用于监控系统的运行状态。它的主要功能是定期检查系统是否正常运行,并在系统出现问题时采取措施以恢复正常操作。STM32系列单片机通常配备了内置的看门狗定时器(独立看门狗,IWDG)和窗口看门狗定时器(WWDG),以提供更可靠的系统保护。
独立看门狗(IWDG)是STM32中常用的看门狗,它是一个独立的硬件模块,可以在系统内部独立运行。通过配置IWDG定时器的计数器和预分频器,可以设置看门狗的定时时间。当看门狗定时器计数器达到预设的值时,会产生看门狗超时事件,触发系统复位。
独立时钟LSI时钟不需要开启
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_8);
IWDG_SetReload(0x0FFF); //1638.4 OVER
IWDG_ReloadCounter();
IWDG_Enable();
IWDG_ReloadCounter();
...
void main()
{
//独立看门狗初始化
// 亮灯 //这段程序复位之后只运行一遍
while(1){
//灭灯
if(key0==0)
{
//喂狗
}
}
}
根据自己的设定,确定看门狗溢出时间,再配置一个定时器,在溢出时间之前喂狗
...
void main()
{
//独立看门狗初始化 200ms 溢出
// 亮灯 //这段程序复位之后只运行一遍
// 初始定时器 小于200ms溢出定时器中断
while(1){
//灭灯
}
}
void timer() //定时器溢出中断
{
//喂狗
}
void LED_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_8;
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct); //&x
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_2;
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStruct); //&x
}
void KEY_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStruct); //&x
}
void iwdg_init()
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//使能
IWDG_SetPrescaler(IWDG_Prescaler_8);//
IWDG_SetReload(0x0FFF); //1638.4 ms OVER
IWDG_ReloadCounter();
IWDG_Enable();
}
void iwdg_init()
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//使能
IWDG_SetPrescaler(IWDG_Prescaler_8);//
IWDG_SetReload(0x0FFF); //1638.4 OVER
IWDG_ReloadCounter();
IWDG_Enable();
}
void main()
{
LED_Init();
iwdg_init();
KEY_Init();
GPIO_SetBits(GPIOD, GPIO_Pin_2);
delay(1000);
GPIO_ResetBits(GPIOD, GPIO_Pin_2);
delay(1000);
GPIO_SetBits(GPIOD, GPIO_Pin_2);
while(1)
{
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5)==0)
{
IWDG_ReloadCounter();
}
}
}
定时器初始化 50ms溢出一次 20次则为1s =1000ms
独立看门狗溢出时间为 1638.4 ms
1s 1000ms 比1638.4 ms 小,1s喂狗一次,就不会复位
反正大于 就会复位
void timer6()
{
/*
1.开启APB1时钟 72MHz
2.配置定时器6 TimeInit() 72预分配,0-65535 1000000us/50000us =CNT=20 定时时间/中断溢出时间=计数值
3.中断配置 分组,优先级 。开启中断源
4.中断服务函数 计数值, 1us ,计数20次后让一个LED取反
*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
//TIM_TimeBaseInitStruct.TIM_ClockDivision=
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period=50000-1;
TIM_TimeBaseInitStruct.TIM_Prescaler= 72-1;
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter=
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStruct);
//开启中断:
TIM_ITConfig( TIM6, TIM_IT_Update, ENABLE);
TIM_Cmd( TIM6, ENABLE); //使能
NVIC_InitStruct.NVIC_IRQChannel=TIM6_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd= ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0; //0-3
NVIC_InitStruct.NVIC_IRQChannelSubPriority= 1; //0-3
NVIC_Init(&NVIC_InitStruct);
}
void TIM6_IRQHandler()
{
if(TIM_GetITStatus( TIM6, TIM_IT_Update))
{
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
num++;
if(num==20) // 1s 1000ms 比1638.4 ms 小,1s喂狗一次
{
num=0;
IWDG_ReloadCounter();
//led取反
GPIOA->ODR^=0x0100; // 1111 1110 1111 1111
// 异或,相同为0,不同为1
//拿0 去异或,原来是0,还是0;原来是1,还是1。既可以保持不变
//拿1 去异或,原来是0,变成1;原来是0,变成1。起到取反的作用
second++;
one_second_flag=1;
if(second==60)
{
second=0;
minute++;
if(minute==60)
{
minute=0;
hour++;
if(hour==24)
{
hour=0;
}
}
}
}
}
}
1s定时喂狗竟然溢出,看来误差真的很大
50ms喂狗成功
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了STM32独立看门狗的功能,后续将代码测试。