STM32 | 您所在的位置:网站首页 › 看门狗用51环绕声听不到对话 › STM32 |
写在前面:本节我们学习STM32中一个很有趣的东西——看门狗,其实在我上大学的时候,当时还没有系统学习STM32的时候,就听到过看门狗这个词语,当时老师上课不断在说看门狗,只是觉得很有意思。但是没有真正了解过,今天同大家一起学习看门狗的内容。看门狗并不难,大家跟着我的思路学习即可。 一、IWDG简介IWDG全称(Independent watchdog)独立看门狗。 本质:一个能够产生复位信号的计数器。 那么什么是复位信号呢?复位就是使MCU回到初始状态。对于单片机来说,开机的时候需要复位,以便使得CPU和其他功能部件处于一个正确的初始状态,并以此为起点开始工作,当出现死机的情况也应当对其进行复位,用以摆脱死机状态。 系统复位方式共有5种,分别为: 1、硬件复位。 2、WWGD复位。 3、IWDG复位。 4、软件复位。 5、低功耗复位。 独立看门狗复位:这种方式使用独立的看门狗来监控单片机系统的工作状态,当单片机工作异常时,看门狗会产生复位信号,将单片机系统复位。 特征:1、独立看门狗是一个递减计数器产生的复位。2、时钟信号是有独立RC振荡器产生。3、可以在待机和停止模式下运行。4、当看门狗被激活后,当递减为0是产生复位。 喂狗:如果在计数没减到 0 之前,重置计数器的值的话,那么就不会产生复位信号,这个动作我们称为。 作用:检测外界电磁干扰或硬件导致程序跑飞的问题。 二、工作原理其本质还是一个计数器; 根据其工作原理图知:IWDG有一个输入(时钟LSI),为内部专门的 40Khz 低速时钟(LSI)驱动 ,经过分频器进行预分频,分频为工作时钟,然后提供给递减计数器,当递减计数器减为0时产生复位信号。为递减计数器赋值的过程称为喂狗,喂狗的作用就是不产生复位信号。 三、相关寄存器 3.1键寄存器(IWDG_KR)该寄存器共有16位,其作用为控制看门狗的相关操作,由软件进行设置: 主要的操作有三个:1、0XAAAA进行喂狗,只有这样才能将重装载寄存器的值进行喂狗;2、0X5555解除写保护,表示允许访问IWDG_PR和IWDG_RLR寄存器;3、写入入0xCCCC,启动看门狗工作。 3.2预分频寄存器(IWDG_PR)此寄存器只有三位有效,其主要作用就是将来自时钟信号进行分频,从而供给看门狗使用。 3.3重装载寄存器(IWDG_RLR)该寄存器的有效位数为12位,其作用为看门狗计数器的重装载值。每当向IWDG_KR 寄存器写入0xAAAA时,重装载值会被传送到计数器中。随后计数器从这个值开始递减计数。所以说最大的重装载值为2^12,最小的重装载值为1。 3.4状态寄存器(IWDG_SR)该寄存器只有两位,其主要的功能为: RVU: 看门狗计数器重装载值更新;PVU: 看门狗预分频值更新 。 3.5寄存器配置步骤上述寄存器以及相关的位的配置步骤如下: 1、通过IWDG_KR 置为0xCCCC 使能看门狗; 2、通过IWDG_KR 置为0x5555 使能寄存器访问,可以访问PR与RLT寄存器; 3、通过IWDG_PR 的0-7位为预分频器; 4、通过IWDG_RLR 设置喂狗的值; 5、通过IWDG_SR 判断重装载值以及预分频系数是否更新完; 6、刷新计数器的值IWDG_RLR,再将IWDG_KR置为0XAAA进行反复的喂狗。 四、IWDG配置步骤 1、IWDG溢出时间计算寄存器设置分频系数的方法: psc=4 * 2^prer,但最大值只能是 256; 2、IWDG 的配置步骤1、取消PR/RLR寄存器写保护。 2、IWDG设置预分频系数和重装载值,启动IWDG。 3、及时喂狗,写入0XAAAA到IWDG_KR。 3、IWDG的HAL库驱动HAL_IWDG_Init 函数,涉及主要的寄存器IWDG_PR/RL/KP,使能IWDG设置预分频系数和重装载值。 其形参为结构体指针:IWDG_HandleTypeDef *hiwdg;进一步看主要由三个参数进行定义: HAL_IWDG_Refresh 函数,涉及主要的寄存器IWDG_KR,把重装载寄存器的值重载到计数器中,也就是喂狗。 该库函数的参数 结构体指针:IWDG_HandleTypeDef *hiwdg; 五、源码及验证 5.1实验说明可以看到 LED0 不停的闪烁,证明系统在不停的复位,否则 LED0 常亮。这时我们不停的按 KEY_0按键,可以看到 LED0 就常亮了,不会再闪烁。也就是说不按下KEY0按键时,程序不停地在看门狗复位,按下按键的过程也就是喂狗的过程,及时喂狗打断复位,让LED0长亮。 5.2源码main.c #include "./SYSTEM/sys/sys.h" #include "./SYSTEM/usart/usart.h" #include "./SYSTEM/delay/delay.h" #include "./BSP/led/led.h" #include "./BSP/iwdg/IWDG.h" #include "./BSP/key/key.h" int main(void) { HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ delay_init(72); /* 延时初始化 */ led_init(); /* LED初始化 */ key_init(); /* KEY初始化 */ delay_ms(100); /* 延时1s,再初始化看门狗,作用是为了使LED0的灯进行可视化 */ iwdg_init(IWDG_PR_PR_2,625); /* 预分频系数为64,重载值为625,看门狗的时间约为1s */ LED1(0); /* 点亮LED0 */ while(1) { if (key_scan()==1) /* 如果KEY0 按下,则喂狗 */ { iwdg_feed(); /* 喂狗 */ } } }IWDG.c #include "./BSP/iwdg/IWDG.h" IWDG_HandleTypeDef g_iwdg_handle;//定义独立看门狗句柄; /**; * @brief 初始化独立看门狗 * @param prer:预分频系数; * @arg 分频因子 = 4 * 2^prer. 但最大值只能是256! * @param rlr: 自动重装载值,0~0XFFF. * @note 时间计算(大概):Tout=((4 * 2^prer) * rlr) / 40 (ms). * @retval 无 */ void iwdg_init(uint8_t prer,uint16_t rlr) { g_iwdg_handle.Instance=IWDG; g_iwdg_handle.Init.Prescaler=prer; g_iwdg_handle.Init.Reload=rlr; HAL_IWDG_Init(&g_iwdg_handle); } /**; * @brief 喂狗函数 * @param 无 * @retval 无 */ void iwdg_feed(void) { HAL_IWDG_Refresh(&g_iwdg_handle); }key.c #include "./BSP/key/key.h" #include "./SYSTEM/delay/delay.h" /** * @brief 初始化KEY相关IO口, 并使能时钟 * @param 无 * @retval 无 */ void key_init(void) { GPIO_InitTypeDef gpio_init_struct; //定义GPIO结构体 __HAL_RCC_GPIOE_CLK_ENABLE();//使能GPIOB的时钟; gpio_init_struct.Pin=GPIO_PIN_4;//设置IO口的引脚; gpio_init_struct.Pull=GPIO_PULLUP;//设置IO口的工作模式 gpio_init_struct.Mode=GPIO_MODE_INPUT; gpio_init_struct.Speed=GPIO_SPEED_FREQ_HIGH;//设置IO口的输入速度。 HAL_GPIO_Init(GPIOE, &gpio_init_struct); } /** * @brief 判断按键是否按下 * @param 无 * @retval keyval如果是1就是按键按下,如果是0就是按键未按下 */ uint8_t key_scan() { uint8_t keyval=0;//定义一个返回值,用于判断按键是否按下 if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)//判断按键是否按下 { delay_ms(20); while(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==1);//判断按下后是否松开 keyval=1; } return keyval; }led.c #include "./BSP/led/led.h" /**; * @brief 初始化LED函数 * @param 无 * @retval 无 */ void led_init(void) { __HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB的时钟; GPIO_InitTypeDef gpio_init_struct;//定义GPIO结构体 gpio_init_struct.Mode=GPIO_MODE_OUTPUT_PP; //设置IO口的工作模式 gpio_init_struct.Pin=GPIO_PIN_5;//设置IO口的引脚; gpio_init_struct.Pull=GPIO_PULLUP;//设置IO口上下; gpio_init_struct.Speed=GPIO_SPEED_FREQ_HIGH;//设置IO的速度; HAL_GPIO_Init(GPIOB, &gpio_init_struct); LED1(1);//关闭LED灯; }led.h #ifndef __LED_H #define __LED_H #include "./SYSTEM/sys/sys.h" void led_init(void);//初始化LED函数 #define LED1(x) do{ x ? \ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET): \ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); \ }while(0)//进行宏定义,通过LED1(x),设置一个三目运算符,如果是1就关闭LED,如果是0就打开LED. #endif 5.3实验现象iwdg实验 链接:https://pan.baidu.com/s/1Al3ryi_T9vZxanOJnFt2Qg 提取码:1022 总结: 本节的主要内容,我们学习的是STM32单片的IWDG即独立看门狗的相关知识,主要的内容有:IWDG的简介与工作原理,相关的寄存器讲解,配置的步骤以及HAL库的相关函数,最后通过实验实现了IWDG控制LED的相关实验现象。本节的内容不算太难,在学习的同时还能很好复习之前的LED、KEY等模块。 创作不易,还请大家多多点赞支持!!! |
CopyRight 2018-2019 实验室设备网 版权所有 |