单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路就是为了避免 这种情况的发生。STM32 的独立看门狗由内部专门的时钟驱动,所以即使主时钟发生故障,它也仍然有效,十分适合用来检测系统程序的执行。看门狗的作用就是在一定时间内(通过定时计数器实现)没有接收"喂狗"信号 (表示 MCU 已经挂了),便实现处理器的自动复位重启(发送复位信号)。
STM32F10x内置两个看门狗:独立看门狗和窗口看门狗,这次我们主要使用独立看门狗。
要启用独立看门狗(IWDG),首先需要在键值寄存器(IWDG_KR)中写入 0xCCCC
,此操作将启动看门狗计数器,该计数器会从复位值 0xFFF
开始递减。当计数器递减到 0x000
时,会产生一个复位信号(IWDG_RESET)。
为了避免产生看门狗复位,可以随时向键值寄存器 IWDG_KR 写入 0xAAAA
,这会将 IWDG_RLR 中的值重新加载到计数器中。
IWDG_PR 和 IWDG_RLR 寄存器具有写保护功能。要修改这两个寄存器的值,必须先向 IWDG_KR 寄存器中写入 0x5555
。将其他值写入这个寄存器会使操作无效,并重新启用写保护功能。重装载操作(即写入 0xAAAA
)也会重新启动写保护功能。
独立看门狗还有两个重要寄存器:
- 预分频寄存器(IWDG_PR):用于设置看门狗时钟的分频系数。
- 重装载寄存器(IWDG_RLR):用于保存将重装载到计数器中的值。该寄存器为32位,但只有低12位有效。
只要对这三个寄存器(IWDG_KR、IWDG_PR 和 IWDG_RLR)进行相应的设置,就可以启动STM32的独立看门狗。启动过程可以按如下步骤实现:
- 向 IWDG_KR 写入
0xCCCC
,启动看门狗。 - 根据需要向 IWDG_PR 和 IWDG_RLR 写入相应的值,修改前先写入
0x5555
以解除写保护。 - 定期向 IWDG_KR 写入
0xAAAA
以重装载计数器,避免复位。
独立看门狗相关的库函数和定义分布在文件 stm32f10x_iwdg.h
和 stm32f10x_iwdg.c
中。
下面我们利用IWDG进行检测,主函数让LED灯常亮,按下按键代表喂狗,如果在1s内没有喂狗,则系统复位后LED会重新点亮。
1.配置IWDG
void IWDG_Config(uint8_t prv ,uint16_t rlv)
{
/* 使能 预分频寄存器PR和重装载寄存器RLR可写 */
IWDG_WriteAccessCmd( IWDG_WriteAccess_Enable );
/* 设置预分频器值 */
IWDG_SetPrescaler( prv );
/* 设置重装载寄存器值 */
IWDG_SetReload( rlv );
/* 把重装载寄存器的值放到计数器中 */
IWDG_ReloadCounter();
/* 使能 IWDG */
IWDG_Enable();
}
2.喂狗函数
void IWDG_Feed(void)
{
/* 把重装载寄存器的值放到计数器中,喂狗,防止IWDG复位
当计数器的值减到0的时候会产生系统复位 */
IWDG_ReloadCounter();
}
3.主函数
int main(void)
{
/* 初始化板载LED灯 */
LED_GPIO_Init();
/* 初始化按键 */
KEY_GPIO_Init();
Delay(1000);
/* IWDG 1s 超时溢出 */
IWDG_Config(IWDG_Prescaler_64 ,625); //预分频系数为64,重载值为25,对应的溢出时间为1秒
//点亮两个LED灯
LED1_ON;
LED2_ON;
while(1)
{
/*------------------------------------------------------------------------*/
if( KEY1_StateRead() == KEY_DOWN )
{
/*喂狗,如果不喂狗,系统则会复位,LD1则会灭一次,如果在1s
时间内准时喂狗的话,则LED1会常亮 */
IWDG_Feed();
}
}
/*------------------------------------------------------------------------*/
}
看看效果: