(实验六,实验七)单片机,STM32F4学习笔记,代码讲解【看门狗】【正点原子】【原创】

文章目录

  • 实验现象(实验六)
  • 主程序(实验六)
  • 独立看门狗程序(实验六)
  • 代码讲解(实验六)
  • 实验现象(实验七)
  • 主程序(实验七)
  • 窗口看门狗程序(实验七)
  • 代码讲解(实验七)


实验现象(实验六)

本实验,如果看门狗没有复位,开发板的DS0将常亮,如果WK_UP按键按下,就喂狗,只
要WK_UP不停的按,看门狗就一直不会产生复位,保持DS0的常亮,一旦超过看门狗定溢
出时间(Tout=1s)还没按,那么将会导致程序重启,这将导致DS0熄灭一次。

主程序(实验六)

int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	LED_Init();				//初始化LED端口
	KEY_Init();		  	//初始化按键
	delay_ms(100);    //延时100ms 
	IWDG_Init(4,500); //与分频数为64,重载值为500,溢出时间为1s	
	LED0=0;					  //先点亮红灯
	while(1)
	{
		if(KEY_Scan(0)==WKUP_PRES)//如果WK_UP按下,则喂狗
		{
			IWDG_Feed();//喂狗
		}
		delay_ms(10);
	};
}

独立看门狗程序(实验六)

//初始化独立看门狗
//prer:分频数:0~7(只有低3位有效!)
//rlr:自动重装载值,0~0XFFF.
//分频因子=4*2^prer.但最大值只能是256!
//rlr:重装载寄存器值:低11位有效.
//时间计算(大概):Tout=((4*2^prer)*rlr)/32 (ms).
void IWDG_Init(u8 prer,u16 rlr)
{
	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能对IWDG->PR IWDG->RLR的写
	
	IWDG_SetPrescaler(prer); //设置IWDG分频系数

	IWDG_SetReload(rlr);   //设置IWDG装载值

	IWDG_ReloadCounter(); //reload
	
	IWDG_Enable();       //使能看门狗
}

//喂独立看门狗
void IWDG_Feed(void)
{
	IWDG_ReloadCounter();//reload
}

int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	LED_Init();				//初始化LED端口
	KEY_Init();		  	//初始化按键
	delay_ms(100);    //延时100ms 
	IWDG_Init(4,500); //与分频数为64,重载值为500,溢出时间为1s	
	LED0=0;					  //先点亮红灯
	while(1)
	{
		if(KEY_Scan(0)==WKUP_PRES)//如果WK_UP按下,则喂狗
		{
			IWDG_Feed();//喂狗
		}
		delay_ms(10);
	};
}

代码讲解(实验六)

//独立看门狗,内部专门32Khz(注意不是精确32Khz)低速时钟驱动,即主时钟发生故障,它仍然有效
//分为三个寄存器,分别是关键字寄存器,预分频寄存器,重装载寄存器
//关键字寄存器32位只用0-15位,主要用来,启动独立看门狗
//预分频寄存器32位只用0-2位,主要用来,设置看门狗时钟的分频系数,000-111依次为4分频-8分频–256分频
//重装载寄存器32位只用0-11位,主要用来,保存重装载到计数器中的值
//注意,独立看门狗是的计数器,是递减计数的
//独立看门狗计算时间=42的prer次方rlr/40=416500/40=800(开发指南中写的是40,不知道为啥上面是32?)

实验现象(实验七)

本实验, 程序一运行则开启WWDG,并使得DS0亮300ms后关闭,进入死循环。等待WWDG中断的
到来,在中断里面,喂狗,并执行DS1的翻转操作。所以可以看到DS1不停的闪烁,而DS0只在 刚启动的时候闪一下。

主程序(实验七)

int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	LED_Init();				//初始化LED端口
	KEY_Init();		  	//初始化按键
	LED0=0;				   //点亮LED0
	delay_ms(300);
	WWDG_Init(0x7F,0X5F,WWDG_Prescaler_8); 	//计数器值为7f,窗口寄存器为5f,分频数为8	   
	
	while(1)
	{
		LED0=1;  //熄灭LED灯
	}
}

窗口看门狗程序(实验七)

//保存WWDG计数器的设置值,默认为最大. 
u8 WWDG_CNT=0X7F;
//初始化窗口看门狗 	
//tr   :T[6:0],计数器值 
//wr   :W[6:0],窗口值 
//fprer:分频系数(WDGTB),仅最低2位有效 
//Fwwdg=PCLK1/(4096*2^fprer). 一般PCLK1=42Mhz
void WWDG_Init(u8 tr,u8 wr,u32 fprer)
{
 
	NVIC_InitTypeDef NVIC_InitStructure;
 
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); //使能窗口看门狗时钟
	
	WWDG_CNT=tr&WWDG_CNT;   //初始化WWDG_CNT. 
	WWDG_SetPrescaler(fprer); //设置分频值
	WWDG_SetWindowValue(wr); //设置窗口值
//	WWDG_SetCounter(WWDG_CNT);//设置计数值
	WWDG_Enable(WWDG_CNT);  //开启看门狗
	
	NVIC_InitStructure.NVIC_IRQChannel=WWDG_IRQn;  //窗口看门狗中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;  //抢占优先级为2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;					//子优先级为3
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;  //使能窗口看门狗
	NVIC_Init(&NVIC_InitStructure);
	
	WWDG_ClearFlag();//清除提前唤醒中断标志位
  WWDG_EnableIT();//开启提前唤醒中断
}



//窗口看门狗中断服务程序 
void WWDG_IRQHandler(void)
{
	WWDG_SetCounter(WWDG_CNT); //重设窗口看门狗值
	WWDG_ClearFlag();//清除提前唤醒中断标志位
	LED1=!LED1;
}

代码讲解(实验七)

//窗口看门狗通常用来监测由外部干扰或不可预见的逻辑条件造成的程序跑飞而产生的软件故障
//递减计数器T6(其实是第七位,T0开始)位变成0之前被刷新会造成MCU复位,如果没有就是正常按照预设置的时间周期复位
//上面那句话写得不对,懒得改了,总共有两种刷新方式,具体可看开发指南
//窗口看门狗分为三个寄存器,控制寄存器,配置寄存器,状态寄存器
//控制寄存器,32位,低8位有效,只用低8位,T0-T6存储看门狗计数器值,第7位置1启动看门狗,改位只能硬件复位清0
//配置寄存器,32位,只用0-9位,7-8位00–11分别是分频1,分频2,分频4,分频8,0-6位设置窗口值=0x40
//就是说,如果在快复位前的窗口值=0x40时间时,会提醒你还有0x40时间就要复位了,赶紧喂狗
//于是一般在这个时间点设置中断进行喂狗,重新写入计数器值,否则时间一到就会引起看门狗自动复位
//状态寄存器,32位,只用0位,用来记录当前是否有提前唤醒的标志,也就是说当计数器值减到0x40窗口值时
//此位硬件置1,它必须由软件置0(无法软件写1,只能写0)

//超时公式==开发指南中写的和上面不一样,不知道哪个正确,//Fwwdg=PCLK1/(4096*2^fprer).
一般PCLK1=42Mhz中的Fwwdg就是超时时间

你可能感兴趣的:(32单片机,opencv,python,经验分享)