接上一篇分享【STM32WB09KE测评】Demo程序编译烧写 - STM32/STM8单片机论坛 - ST MCU意法半导体官方技术支持论坛 - 21ic电子技术开**坛,这次分享看门狗功能测试。
在例程文件中有看门狗例程源码,所以分享一下该例程代码框架。看门狗例程用的是STM32WB09KE\STM32Cube_FW_WB0_V1.0.0\Projects\NUCLEO-WB09KE\Examples\IWDG\IWDG_Reset文件下的例程。
在系统时钟初始化时也会打开LEI的时钟,因为看门狗的时钟源是LSI,对应代码如下- /** Initializes the RCC Oscillators according to the specified parameters
- * in the RCC_OscInitTypeDef structure.
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.LSIState = RCC_LSI_ON;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
在时钟树中的位置如下图
第二步是先判断设备是正常启动还是看门狗自启动,判断代码如下- /*##-1- Check if the system has resumed from IWDG reset ####################*/
- if ((RAM_VR.ResetReason & RCC_FLAG_WDGRST) == RCC_FLAG_WDGRST)
- {
- /* IWDGRST flag set: Turn LD1 on and set IwdgStatus */
- IwdgStatus = 1;
- BSP_LED_On(LD1);
- /* Insert 4s delay */
- HAL_Delay(4000);
- /* Notification done: Turn LD1 off */
- BSP_LED_Off(LD1);
- }
主要是通过检测特定的寄存器的值进行判断,如果是看门狗自启动则打开LED1指示灯,亮4S后会关闭。
第三步是清除看门狗标志,实现代码如下
- /* Clear reset flags in any cases */
- __HAL_RCC_CLEAR_RESET_FLAGS();
- IwdgStatus = 0;
第四步是获取LSI的频率,因为LSI的时钟源是内部时钟,容易受温度等的影响。测量LSI的频率是用TIM17定时器测量LSI一个时钟周期的时间,通过仿真测试发现时钟确实有些偏差。原本的重载值应为1000,但是仿真的结果比1000大一点,仿真结果如下
对应的代码如下
- /*##-2- Get the LSI frequency: TIM17 is used to measure the LSI frequency ###*/
- GetLSIFrequency();
接下来是初始化看门狗了,主要是配置看门狗的预分频器的值和重载值等。这里预分频器的值配置的是32,主要是时钟源是32KHz,配置成32,正好一个周期是1ms。重载值是根据LSI的实际频率进行配置,配置时间是1S,即两次喂狗时间间隔不得大于或等于1S。重载值的计算方式如下
- #define IWDG_RELOAD (uwLsiFreq / 32)
其中uwLsiFreq是LSI的真实始终频率。
除此之外还配置了GPIO中断,中断源是B1按键。中断执行程序是向未被映射的内存区域写数据,这样就会触发安全机制,使程序进入死循环,而不能按时喂狗,最终触发看门狗复位。中断执行的程序如下
- /* Failure is generated by user, turn LD1 off */
- BSP_LED_Off(LD1);
- /* As the following address is invalid (not mapped), a Hardfault exception
- will be generated with an infinite loop and when the IWDG counter falls to 0
- the IWDG reset occurs */
- *(__IO uint32_t *) 0x00040001 = 0xFF;
在main的while(1)中的代码如下
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- /* Toggle LD2 */
- BSP_LED_Toggle(LD2);
- /* Insert 990 ms delay */
- HAL_Delay(990);
- /* Refresh IWDG: reload counter */
- if(HAL_IWDG_Refresh(&hiwdg) != HAL_OK)
- {
- /* Refresh Error */
- Error_Handler();
- }
若没有触发中断的话,程序会一直执行while(1)中的代码,即每990ms翻转一下LED2引脚的输出状态,让其不停地闪烁;也会进行喂狗。
整体实现的效果是绿灯一直在闪烁,若按下B1按键,则会触发看门狗,即蓝灯亮4秒后熄灭,绿灯会继续闪烁。效果如下。
|