门店管理网站建设,简历模板电子版,crm客户管理系统源码,公司网站开发后台代码一、IWDG简介
IWDG有什么作用#xff1f;
二、IWDG工作原理 三、IWDG框图 四、IWDG寄存器
键寄存器#xff08;IWDG_KR#xff09;预分频器寄存器 (IWDG_PR)重装载寄存器(IWDG_RLR) 状态寄存器(IWDG_SR) 寄存器配置操作步骤
五、IWDG溢出时间计算
IWDG溢出时间计算公式…一、IWDG简介
IWDG有什么作用
二、IWDG工作原理 三、IWDG框图 四、IWDG寄存器
键寄存器IWDG_KR预分频器寄存器 (IWDG_PR)重装载寄存器(IWDG_RLR) 状态寄存器(IWDG_SR) 寄存器配置操作步骤
五、IWDG溢出时间计算
IWDG溢出时间计算公式(HAL库)寄存器设置分频系数的方法IWDG溢出时间计算公式(寄存器)IWDG最短最长超时时间
六、IWDG配置步骤 七、编程实战验证不及时喂狗系统将复位重启 八、总结
一、IWDG简介 IWDGIndependent Watchdog独立看门狗的基本概念 IWDG的全称 IWDG全称为Independent Watchdog它是一种用于监控系统运行的硬件设备。 IWDG的本质 IWDG是一个递减的计数器如果在一段时间内没有被重新加载喂狗则会产生系统复位信号。它是为了防止系统由于某些原因例如程序错误或系统死锁导致无响应。 IWDG的时钟 IWDG的时钟通常由独立的RCResistor-Capacitor振荡器提供。这使得IWDG能够在待机Standby和停止Stop模式下运行即使主系统时钟停止IWDG仍然能够正常工作。 复位触发条件 IWDG的计数器递减当计数器的值减至0x000时会产生复位。这种设计保证了即使系统出现问题也会在一定时间内进行复位。 喂狗 喂狗是指在IWDG计数器减至0之前通过重新加载计数器的值来防止复位。通过定期喂狗可以确保系统正常运行否则IWDG会在计数器减至0时触发复位。
IWDG通常是嵌入式系统中的一个重要功能用于提高系统的稳定性和可靠性。在实际应用中程序员需要根据系统的实际需求配置IWDG并在合适的位置定期喂狗以确保系统不会因为某些异常情况而一直停滞。 STM32F10xxx闪存编程手册
IWDG有什么作用 IWDG的作用的关键点 检测异常 IWDG主要用于检测系统中的异常情况包括但不限于外界电磁干扰、硬件异常或软件异常。当系统出现无法处理的异常时可能导致程序失控、死循环等问题此时IWDG可以通过触发复位来使系统重新启动从而恢复正常运行。 电磁干扰 在一些嵌入式系统中特别是一些对抗电磁干扰要求较高的应用场景IWDG可以起到一种保护作用。外界的电磁干扰有可能导致系统产生错误而IWDG则能够在检测到异常时及时复位系统以保障系统的稳定性。 硬件异常 除了电磁干扰IWDG还能够监测到一些硬件异常比如电源波动、时钟故障等。这些硬件异常可能导致系统运行不正常而IWDG可以在检测到这些异常时采取措施。 最后手段 IWDG通常被看作是异常处理的最后手段。当其他的异常处理机制都无法正常工作或者不可靠时IWDG可以作为一个保险机制确保在极端情况下系统可以重新启动。 应用场景 IWDG适用于对系统稳定性要求较高、对时间精度要求较低的场合。在一些嵌入式产品中特别是一些安全关键系统或长时间运行的系统中使用IWDG可以提高系统的可靠性。 依赖性 尽管IWDG是一个有力的异常处理手段但设计时应避免对它的过度依赖。最好的做法是在系统设计和软件编程中尽量避免异常的发生使得IWDG只在极端情况下起到最后的保护作用。
二、IWDG工作原理 IWDG的工作原理 时钟源 (Src CLK) IWDG的工作始于一个时钟源该时钟源通常是一个独立的RC振荡器。这个时钟源提供了IWDG的时基。 预分频器 (PSC) 时钟源进入预分频器预分频器用于将时钟源的频率进行分频。预分频因子决定了IWDG的时钟频率进而影响计数器的递减速度。 IWDG时钟 (IWDG CLK) 经过预分频后的时钟被用作IWDG的时钟这个时钟将用于递减计数器。 递减计数器 (CNT) 递减计数器是IWDG的核心组件。它以IWDG时钟的速率递减当计数器减至零时触发相应的操作通常是产生复位信号。 重装载寄存器 (RELOAD) 在IWDG工作期间可以通过将重装载寄存器的值写入CNT寄存器重置计数器。这就是“喂狗”的概念。如果在计数器递减至零之前及时进行重装载系统就不会因为IWDG的复位而重新启动。 复位 当计数器递减至零时IWDG触发相应的操作通常是系统复位。这样可以确保系统在长时间没有喂狗的情况下仍能重新启动从而防止系统因为外界干扰或软硬件错误而陷入死循环或无法响应的状态。
整个过程通过控制时钟源、预分频、递减计数器和重装载寄存器实现了对系统的监控和复位功能确保系统在异常情况下能够恢复到正常工作状态。
三、IWDG框图 IWDG的框图和各个组成部分的功能描述的一些关键点 低速内部(LSI) RC振荡器 IWDG的时钟源是LSI低速内部RC振荡器。在启用IWDG后LSI时钟会自动开启。需要注意的是LSI的时钟频率可能不够精确因此在计算时需要注意。 预分频器寄存器 (IWDG_PR) 8位预分频器用于对LSI时钟进行预分频从而得到IWDG的时钟。通过调整预分频因子可以调整IWDG的工作频率影响计数器的递减速度。 状态寄存器 (IWDG_SR) 状态寄存器用于监测IWDG的状态其中包括计数器的运行状态和复位状态。 递减计数器 (IWDG_CNT) 12位递减计数器是IWDG的核心部分。它以预分频后的时钟为基准递减当计数器减至零时触发相应的操作。 密钥寄存器 (IWDG_KR) 密钥寄存器用于对IWDG进行操作的授权。写入指定值后才能对IWDG进行启动、重装载等操作。 重载寄存器 (IWDG_RLR) 重载寄存器用于设置IWDG的重装载值即重新加载计数器的值。通过定期对该寄存器进行写入可以避免IWDG触发复位。 看门狗功能供电 IWDG的功能是由 V D D V_{DD} VDD电压域供电的这意味着即使在停止模式和待机模式下IWDG仍然能够正常工作。
整个框图清晰地展示了IWDG的各个组成部分并说明了它们之间的关系和作用。这样的硬件设计使得IWDG能够在异常情况下提供可靠的系统监控和复位功能。
四、IWDG寄存器
键寄存器IWDG_KR
键寄存器可以看作是独立看门狗的控制寄存器 在键寄存器(IWDG_KR)中写入 0xCCCC开始启用独立看门狗此时计数器开始从其复位值 0xFFF 递减计数。当计数器计数到末尾 0x000 时会产生一个复位信号(IWDG_RESET)。无论何时只要键寄存器 IWDG_KR 中被写入 0xAAAAIWDG_RLR 中的值就会被重新加载到计数器中从而避免产生看门狗复位。 IWDG_PR 和 IWDG_RLR 寄存器具有写保护功能。要修改这两个寄存器的值必须先向IWDG_KR 寄存器中写入 0x5555。将其他值写入这个寄存器将会打乱操作顺序寄存器将重新被保护。重装载操作(即写入 0xAAAA)也会启动写保护功能。 若选择了硬件看门狗则不受此命令字限制
预分频器寄存器 (IWDG_PR) 该寄存器用来设置看门狗时钟LSI的分频系数最低为 4最高位 256该寄存器是一个 32 位的寄存器但是我们只用了最低 3 位其他都是保留位。
预分频器寄存器IWDG_PR是独立看门狗IWDG中的一个寄存器用于设置预分频因子从而调整IWDG的时钟频率。IWDG的时钟频率直接影响计数器的递减速度。
预分频器寄存器 (IWDG_PR) 用于设置 IWDG 的预分频因子从而确定 IWDG 的时钟频率。这个预分频因子决定了递减计数器的速度进而影响看门狗的定时周期。IWDG_PR 寄存器是一个 3 位的寄存器可以设置的预分频因子如下
Bit 2:0 PR[2:0]: Prescaler divider000: f(LSI) / 4001: f(LSI) / 8010: f(LSI) / 16011: f(LSI) / 32100: f(LSI) / 64101: f(LSI) / 128110: f(LSI) / 256111: f(LSI) / 256000: IWDG时钟 LSI / 4001: IWDG时钟 LSI / 8010: IWDG时钟 LSI / 16011: IWDG时钟 LSI / 32100: IWDG时钟 LSI / 64101: IWDG时钟 LSI / 128110: IWDG时钟 LSI / 256111: IWDG时钟 LSI / 256
这里的f(LSI)表示低速内部LSIRC振荡器的频率。通过设置PR位可以选择不同的预分频因子从而得到不同的IWDG时钟频率。
例如如果设置PR位为010则预分频因子为16IWDG的时钟频率将是LSI时钟频率的1/16。这会使得计数器的递减速度减缓增加喂狗的时间间隔。
在使用IWDG时你可以根据实际需求选择适当的预分频因子以平衡系统对看门狗的监测精度和系统响应速度的要求。
通过选择适当的预分频因子可以调整 IWDG 的时钟频率以满足特定的定时需求。更小的预分频因子将导致更快的计数器递减速度而更大的预分频因子将导致更慢的计数器递减速度。在实际应用中需要根据具体的系统需求和预期的看门狗定时周期来选择合适的预分频因子。
重装载寄存器(IWDG_RLR) 该寄存器用来保存重装载到计数器中的值。该寄存器也是一个 32 位寄存器只有低 12 位是有效的。
重装载寄存器IWDG_RLR是 IWDG 的一个重要寄存器用于设置 IWDG 的重载值。这个值决定了递减计数器的初始值也就是看门狗的计数周期。当递减计数器递减到零时会触发相应的操作通常是产生复位信号。
IWDG_RLR 是一个 12 位的寄存器可以设置的范围是 0 到 0xFFF4095。这个数值表示递减计数器的初始值。在 IWDG 启动后计数器开始递减当递减计数器减至零时会产生复位。为了防止复位发生需要定期“喂狗”重新加载计数器。
重装载寄存器的使用步骤
初始化 IWDG_RLR设置递减计数器的初始值。这通常在系统初始化的时候进行。
IWDG_RLR 0x0FFF; // 设置重载值决定计数周期启动 IWDG。一旦 IWDG 启动递减计数器开始递减。
IWDG_KR 0xAAAA; // 启动 IWDG定期“喂狗”重新加载计数器。这通常在程序的主循环中或者其他适当的位置进行。
IWDG_KR 0xAAAA; // 喂狗重新加载计数器通过调整重装载寄存器的值可以实现对看门狗定时周期的控制满足系统的监控和复位需求。
状态寄存器(IWDG_SR) 状态寄存器 (IWDG_SR) 是 IWDGIndependent Watchdog独立看门狗的一个寄存器用于监控 IWDG 的运行状态。IWDG_SR 寄存器的位域描述了 IWDG 的状态信息。以下是 IWDG_SR 寄存器的主要位域 Bit 0 - RVU: 重装载值更新 0: 重装载寄存器的值没有被更新。1: 重装载寄存器的值已经被更新。 Bit 1 - PVU: 预分频器值更新 0: 预分频器寄存器的值没有被更新。1: 预分频器寄存器的值已经被更新。 Bit 2 - WVU: 窗口寄存器值更新 0: 窗口寄存器的值没有被更新。1: 窗口寄存器的值已经被更新。 Bit 3 - KEY: 密钥值 0: 密钥寄存器的值没有被更新。1: 密钥寄存器的值已经被更新。
使用状态寄存器的步骤 检查 RVU、PVU、WVU、KEY 位 在对 IWDG 进行任何配置之前可以检查这些位确保相关寄存器的值已经被更新。 配置重载值RLR、预分频器值PR和窗口寄存器值WINR 根据系统需求配置相应的寄存器。 更新密钥寄存器KR 将 IWDG_KR 寄存器写入 0x5555然后写入 0xAAAA以更新相关寄存器的值。 检查状态寄存器位 可以通过检查 RVU、PVU、WVU、KEY 位来确认更新是否成功。
总体而言状态寄存器用于提供关于 IWDG 配置的更新状态信息确保相关寄存器的值在使用前已经被更新。
寄存器配置操作步骤 配置STM32上独立看门狗IWDG的寄存器的操作。下面是对每个步骤的详细解释 使能IWDG 通过在键寄存器IWDG_KR中写入0xCCCC可以使能IWDG。这个操作告诉IWDG开始工作启动递减计数器。 使能寄存器访问 通过在键寄存器IWDG_KR中写入0x5555可以使能对IWDG相关寄存器的访问。这个步骤通常在修改IWDG配置之前进行确保能够对寄存器进行写操作。 配置预分频器 通过将预分频器寄存器IWDG_PR的值设置为0到7之间的数值可以配置IWDG的预分频器。预分频器用于将IWDG的时钟源进行分频以设置递减计数器的计数速度。 写入重载寄存器 通过对重载寄存器IWDG_RLR进行写操作设置递减计数器的初始值。这个值决定了IWDG的计数周期。 等待寄存器更新 在写入寄存器配置后等待寄存器更新。可以通过检查状态寄存器IWDG_SR的值确认相关寄存器的更新状态。通常等待IWDG_SR等于0x0000 0000。 刷新计数器 最后通过在键寄存器IWDG_KR中写入0xAAAA来刷新计数器。这个操作相当于“喂狗”重新加载计数器的值以防止IWDG产生复位信号。
这些步骤确保了IWDG的正确配置和运行以提供对系统的监控和保护。
五、IWDG溢出时间计算 IWDG溢出时间计算公式(HAL库)
在HAL库中IWDGIndependent Watchdog独立看门狗的溢出时间 T o u t T_{out} Tout 可以通过以下公式计算 T o u t p s c × r l r f IWDG T_{out} \frac{psc \times rlr}{f_{\text{IWDG}}} ToutfIWDGpsc×rlr
其中 T o u t T_{out} Tout 是看门狗的溢出时间。 f IWDG f_{\text{IWDG}} fIWDG 是看门狗的时钟源频率。 p s c psc psc 是看门狗的预分频系数。 r l r rlr rlr 是看门狗的重装载值。
这个公式描述了看门狗计数器的计数时间即在重新加载计数器之前的时间。通常 T o u t T_{out} Tout 可以用来估算系统的监视时间确保系统在这个时间内喂狗防止看门狗产生复位信号。
推导IWDG溢出时间的公式
推导IWDG溢出时间的公式涉及时钟源频率、预分频系数和重装载值等参数。以下是一个简化的推导过程 IWDG时钟源频率 f IWDG f_{\text{IWDG}} fIWDG 在HAL库中IWDG的时钟源通常是LSI低速内部振荡器。该频率通常在芯片手册中给出以 H z Hz Hz为单位。假设为 f IWDG f_{\text{IWDG}} fIWDG。 IWDG预分频系数 p s c psc psc 预分频系数 p s c psc psc 用于将时钟源的频率进行分频以降低计数器的计数速度。 p s c psc psc 的值可以设置为0到7之间的整数。 IWDG重装载值 r l r rlr rlr 重装载值 r l r rlr rlr 决定了IWDG计数器的初始值即溢出时间的起点。 r l r rlr rlr 也是可以根据系统需求设置的值。 IWDG计数器的溢出时间 T out T_{\text{out}} Tout IWDG的计数器溢出时间可以通过以下公式计算 T out p s c × r l r f IWDG T_{\text{out}} \frac{psc \times rlr}{f_{\text{IWDG}}} ToutfIWDGpsc×rlr
推导的步骤 计算分频后的时钟频率 通过时钟频率 f IWDG f_{\text{IWDG}} fIWDG 和看门狗预分频系数 p s c psc psc 的除法得到分频后的时钟频率 f IWDG p s c \frac{f_{\text{IWDG}}}{psc} pscfIWDG。这个值表示IWDG实际工作时的时钟频率即一秒钟内IWDG可以进行的计数次数。 计算一次计数需要的时间 取上一步计算的分频后时钟频率的倒数即 1 f IWDG p s c \frac{1}{\frac{f_{\text{IWDG}}}{psc}} pscfIWDG1这个值表示IWDG进行一次计数所需的时间。 计算溢出时间 将上一步得到的一次计数时间乘以看门狗重装载值 r l r rlr rlr即 p s c f IWDG × r l r \frac{psc}{f_{\text{IWDG}}} \times rlr fIWDGpsc×rlr得到的结果就是看门狗的溢出时间。
这个公式的推导基于时钟源的分频、重装载值和时钟频率的关系。确保 T out T_{\text{out}} Tout 不超过IWDG的设定溢出时间以免系统因未及时喂狗而触发复位。
寄存器设置分频系数的方法
在STM32系列的IWDG中预分频系数 p s c psc psc 与寄存器 I W D G _ P R IWDG\_PR IWDG_PR 的设置关系为 p s c 4 × 2 p r e r psc 4 \times 2^{prer} psc4×2prer
其中 p r c r prcr prcr 是 I W D G _ P R IWDG\_PR IWDG_PR 寄存器的设置值。
这个公式表达了预分频系数 p s c psc psc 与 I W D G _ P R IWDG\_PR IWDG_PR 寄存器的值之间的关系。通过调整 I W D G _ P R IWDG\_PR IWDG_PR 的值可以间接地影响 p s c psc psc从而调整IWDG的时钟频率。在设置IWDG时需要根据具体的应用和需求选择合适的 I W D G _ P R IWDG\_PR IWDG_PR 的值以满足对看门狗的计数速度的要求。
IWDG溢出时间计算公式(寄存器)
在使用寄存器配置IWDG时计算溢出时间的公式可以表示为 T o u t ( 4 × 2 p r e r ) × r l r f IWDG T_{out} \frac{(4 \times 2^{prer}) \times rlr}{f_{\text{IWDG}}} ToutfIWDG(4×2prer)×rlr
其中 T o u t T_{out} Tout 是IWDG的溢出时间。 f IWDG f_{\text{IWDG}} fIWDG 是IWDG的时钟源频率通常是LSI的频率。 p r e r prer prer 是 I W D G _ P R IWDG\_PR IWDG_PR 寄存器的设置值决定了预分频系数。 r l r rlr rlr 是IWDG的重装载值决定了计数器的初始值。
这个公式描述了IWDG计数器的溢出时间即在重新加载计数器之前的时间。确保 T o u t T_{out} Tout 不超过IWDG的设定溢出时间以免系统因未及时喂狗而触发复位。
IWDG最短最长超时时间
在STM32系列中IWDG的时钟源通常是LSI低速内部振荡器其频率为40kHz和32kHz。根据这个时钟源频率我们可以计算IWDG的最短和最长超时时间。 最短超时时间 由于IWDG是一个12位的递减计数器最短超时时间为计数器值为1时的时间。因此最短超时时间 $ T_{\text{min}}$ 可以通过以下公式计算 T min 1 LSI频率 T_{\text{min}} \frac{1}{\text{LSI频率}} TminLSI频率1 最长超时时间 最长超时时间取决于IWDG的重装载值 r l r rlr rlr 的设置。假设 r l r rlr rlr 设置为最大值即4095最长超时时间 T max T_{\text{max}} Tmax 可以通过以下公式计算 T max 4095 × 4 × 2 p r e r LSI频率 T_{\text{max}} \frac{4095 \times 4 \times 2^{prer}}{\text{LSI频率}} TmaxLSI频率4095×4×2prer
其中 p r e r prer prer 是 I W D G _ P R IWDG\_PR IWDG_PR 寄存器的设置值决定了预分频系数。确保 T max T_{\text{max}} Tmax 不超过IWDG的设定溢出时间以免系统因未及时喂狗而触发复位。
IWDG最短最长超时时间F1 IWDG最短最长超时时间F4/F7/H7 六、IWDG配置步骤 HAL库相关函数介绍 HAL_IWDG_Init 函数和 HAL_IWDG_Refresh 函数是HAL库中用于初始化和刷新IWDG的两个函数。
HAL_IWDG_Init 函数
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)输入参数 IWDG_HandleTypeDef 结构体包含IWDG的基地址和初始化参数。功能 使能IWDG设置预分频系数和重装载值等。具体操作 使用给定的 IWDG_InitTypeDef 结构体中的参数配置IWDG的预分频系数和重装载值。启用IWDG时钟。使用配置好的参数初始化IWDG。
HAL_IWDG_Refresh 函数
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)输入参数 IWDG_HandleTypeDef 结构体包含IWDG的基地址。功能 将重装载寄存器的值重载到计数器中喂狗。具体操作 通过IWDG的键寄存器 (IWDG_KR) 将重装载值加载到递减计数器。此函数用于定期刷新IWDG以防止计数器溢出导致系统复位。
IWDG_HandleTypeDef 结构体包含IWDG的基地址和初始化参数而 IWDG_InitTypeDef 结构体包含预分频系数和重装载值等参数。这两个函数配合使用能够实现对IWDG的初始化和刷新操作。 stm32f1xx_hal.c
#include stm32f1xx_hal.h#ifdef HAL_IWDG_MODULE_ENABLED
#define HAL_IWDG_DEFAULT_TIMEOUT ((6UL * 256UL * 1000UL) / LSI_VALUE)HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)
{uint32_t tickstart;/* Check the IWDG handle allocation */if (hiwdg NULL){return HAL_ERROR;}/* Check the parameters */assert_param(IS_IWDG_ALL_INSTANCE(hiwdg-Instance));assert_param(IS_IWDG_PRESCALER(hiwdg-Init.Prescaler));assert_param(IS_IWDG_RELOAD(hiwdg-Init.Reload));/* Enable IWDG. LSI is turned on automatically */__HAL_IWDG_START(hiwdg);/* Enable write access to IWDG_PR and IWDG_RLR registers by writing0x5555 in KR */IWDG_ENABLE_WRITE_ACCESS(hiwdg);/* Write to IWDG registers the Prescaler Reload values to work with */hiwdg-Instance-PR hiwdg-Init.Prescaler;hiwdg-Instance-RLR hiwdg-Init.Reload;/* Check pending flag, if previous update not done, return timeout */tickstart HAL_GetTick();/* Wait for register to be updated */while (hiwdg-Instance-SR ! 0x00u){if ((HAL_GetTick() - tickstart) HAL_IWDG_DEFAULT_TIMEOUT){return HAL_TIMEOUT;}}/* Reload IWDG counter with value defined in the reload register */__HAL_IWDG_RELOAD_COUNTER(hiwdg);/* Return function status */return HAL_OK;
}HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
{/* Reload IWDG counter with value defined in the reload register */__HAL_IWDG_RELOAD_COUNTER(hiwdg);/* Return function status */return HAL_OK;
}#endif /* HAL_IWDG_MODULE_ENABLED */
stm32f1xx_hal.h
#ifndef __STM32F1xx_HAL_DEF
#define __STM32F1xx_HAL_DEF#ifdef __cplusplus
extern C {
#endif/* Includes ------------------------------------------------------------------*/
#include stm32f1xx.h
#include Legacy/stm32_hal_legacy.h
#include stddef.h/* Exported types ------------------------------------------------------------*//*** brief HAL Status structures definition*/
typedef enum
{HAL_OK 0x00U,HAL_ERROR 0x01U,HAL_BUSY 0x02U,HAL_TIMEOUT 0x03U
} HAL_StatusTypeDef;/*** brief HAL Lock structures definition*/
typedef enum
{HAL_UNLOCKED 0x00U,HAL_LOCKED 0x01U
} HAL_LockTypeDef;/* Exported macro ------------------------------------------------------------*/
#define HAL_MAX_DELAY 0xFFFFFFFFU#define HAL_IS_BIT_SET(REG, BIT) (((REG) (BIT)) ! 0U)
#define HAL_IS_BIT_CLR(REG, BIT) (((REG) (BIT)) 0U)#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__) \do{ \(__HANDLE__)-__PPP_DMA_FIELD__ (__DMA_HANDLE__); \(__DMA_HANDLE__).Parent (__HANDLE__); \} while(0U)#define UNUSED(X) (void)X /* To avoid gcc/g warnings */#define __HAL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)-State 0U)#if (USE_RTOS 1U)
/* Reserved for future use */
#error USE_RTOS should be 0 in the current HAL release
#else
#define __HAL_LOCK(__HANDLE__) \do{ \if((__HANDLE__)-Lock HAL_LOCKED) \{ \return HAL_BUSY; \} \else \{ \(__HANDLE__)-Lock HAL_LOCKED; \} \}while (0U)#define __HAL_UNLOCK(__HANDLE__) \do{ \(__HANDLE__)-Lock HAL_UNLOCKED; \}while (0U)
#endif /* USE_RTOS */#if defined (__ARMCC_VERSION) (__ARMCC_VERSION 6010050) /* ARM Compiler V6 */
#ifndef __weak
#define __weak __attribute__((weak))
#endif
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#elif defined ( __GNUC__ ) !defined (__CC_ARM) /* GNU Compiler */
#ifndef __weak
#define __weak __attribute__((weak))
#endif /* __weak */
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif /* __packed */
#endif /* __GNUC__ *//* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive #pragma data_alignment4 must be used instead */
#if defined (__ARMCC_VERSION) (__ARMCC_VERSION 6010050) /* ARM Compiler V6 */
#ifndef __ALIGN_BEGIN
#define __ALIGN_BEGIN
#endif
#ifndef __ALIGN_END
#define __ALIGN_END __attribute__ ((aligned (4)))
#endif
#elif defined ( __GNUC__ ) !defined (__CC_ARM) /* GNU Compiler */
#ifndef __ALIGN_END
#define __ALIGN_END __attribute__ ((aligned (4)))
#endif /* __ALIGN_END */
#ifndef __ALIGN_BEGIN
#define __ALIGN_BEGIN
#endif /* __ALIGN_BEGIN */
#else
#ifndef __ALIGN_END
#define __ALIGN_END
#endif /* __ALIGN_END */
#ifndef __ALIGN_BEGIN
#if defined (__CC_ARM) /* ARM Compiler V5*/
#define __ALIGN_BEGIN __align(4)
#elif defined (__ICCARM__) /* IAR Compiler */
#define __ALIGN_BEGIN
#endif /* __CC_ARM */
#endif /* __ALIGN_BEGIN */
#endif /* __GNUC__ *//*** brief __RAM_FUNC definition*/
#if defined ( __CC_ARM ) || (defined (__ARMCC_VERSION) (__ARMCC_VERSION 6010050))#define __RAM_FUNC#elif defined ( __ICCARM__ )
/* ICCARM Compiler---------------RAM functions are defined using a specific toolchain keyword __ramfunc.
*/
#define __RAM_FUNC __ramfunc#elif defined ( __GNUC__ )
/* GNU Compiler------------RAM functions are defined using a specific toolchain attribute__attribute__((section(.RamFunc))).
*/
#define __RAM_FUNC __attribute__((section(.RamFunc)))#endif/*** brief __NOINLINE definition*/
#if defined ( __CC_ARM ) || (defined (__ARMCC_VERSION) (__ARMCC_VERSION 6010050)) || defined ( __GNUC__ )
/* ARM V4/V5 and V6 GNU Compiler-------------------------------
*/
#define __NOINLINE __attribute__ ( (noinline) )#elif defined ( __ICCARM__ )
/* ICCARM Compiler---------------
*/
#define __NOINLINE _Pragma(optimize no_inline)#endif#ifdef __cplusplus
}
#endif#endif /* ___STM32F1xx_HAL_DEF */七、编程实战验证不及时喂狗系统将复位重启 wdg.c
#include ./BSP/WDG/wdg.hIWDG_HandleTypeDef g_iwdg_handle; // 定义IWDG的句柄/* IWDG初始化函数 */
void iwdg_init(uint8_t prer, uint16_t rlr)
{g_iwdg_handle.Instance IWDG; // 设置IWDG句柄的寄存器基地址为IWDGg_iwdg_handle.Init.Prescaler prer; // 设置IWDG的预分频系数g_iwdg_handle.Init.Reload rlr; // 设置IWDG的重装载值HAL_IWDG_Init(g_iwdg_handle); // 使用HAL库初始化IWDG
}/* 喂狗函数 */
void iwdg_feed(void)
{HAL_IWDG_Refresh(g_iwdg_handle); // 使用HAL库刷新IWDG防止看门狗复位系统
}wdg.h
#ifndef __WDG_H
#define __WDG_H#include ./SYSTEM/sys/sys.hvoid iwdg_init(uint8_t prer, uint16_t rlr);
void iwdg_feed(void);#endifmain.c
#include ./SYSTEM/sys/sys.h
#include ./SYSTEM/usart/usart.h
#include ./SYSTEM/delay/delay.h
#include ./BSP/LED/led.h
#include ./BSP/WDG/wdg.hint main(void)
{HAL_Init(); // 初始化HAL库sys_stm32_clock_init(RCC_PLL_MUL9); // 设置时钟为72MHzdelay_init(72); // 延时初始化usart_init(115200); // 串口初始化为115200printf(您还没喂狗请及时喂狗\r\n); // 打印提示信息iwdg_init(IWDG_PRESCALER_32, 1250); // 预分频系数为32重装载值为1250溢出时间约为1swhile (1){delay_ms(1000); // 延时1秒iwdg_feed(); // 喂狗刷新看门狗计数器printf(已经喂狗\r\n); // 打印喂狗提示信息}
}IWDG的重装载值Reload Value的计算方式与溢出时间直接相关。溢出时间Timeout的计算公式如下 Tout PSC × RLR fIWDG \text{Tout} \frac{\text{PSC} \times \text{RLR}}{\text{fIWDG}} ToutfIWDGPSC×RLR
其中 Tout \text{Tout} Tout 是看门狗溢出时间。 PSC \text{PSC} PSC 是预分频系数。 RLR \text{RLR} RLR 是重装载值。 fIWDG \text{fIWDG} fIWDG 是看门狗的时钟源频率。
在你的代码中预分频系数 PSC \text{PSC} PSC被设置为32这是一个固定的值。时钟源频率 fIWDG \text{fIWDG} fIWDG为40kHz。
如果要计算重装载值 RLR \text{RLR} RLR可以根据预期的溢出时间来确定。在你的情况下你希望溢出时间约为1秒。因此可以通过重排上述公式解出 RLR \text{RLR} RLR RLR Tout × fIWDG PSC \text{RLR} \frac{\text{Tout} \times \text{fIWDG}}{\text{PSC}} RLRPSCTout×fIWDG
将数值代入得到 RLR 1 × 40000 32 1250 \text{RLR} \frac{1 \times 40000}{32} 1250 RLR321×400001250
所以重装载值 RLR \text{RLR} RLR为1250。 八、总结