stm32F4系列MCU,視窗看門狗 WWDG中的bug。
1. 如果使能預喂狗中斷,那麼必須滿足如下兩點
(1)在開啟wwdg中斷之前,需要先將 SR 寄存器中的EWI標誌位清零,否則會看門狗會不斷複位
(2)在wwdg_irq裡加上一小段延時,否則看門狗會不斷複位
2. 如果系統裡還有其他中斷,比如按鍵,在按鍵中斷中設定一個變數,這個變數在wwdg_isr中讀取,來決定是否停止喂狗
這樣按下按鍵以後,系統直接就飛了。
這裡給出一個測試代碼。 如下所示。
/** ****************************************************************************** * @file USART/USART_Printf/main.c * @author MCD Application Team * @version V1.0.1 * @date 13-April-2012 * @brief Main program body ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2> * * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** *//* Includes ------------------------------------------------------------------*/#include "stm32f4xx.h"#include "stm324xg_eval.h"#include <stdio.h>/** @addtogroup STM32F4xx_StdPeriph_Examples * @{ *//** @addtogroup USART_Printf * @{ */ /* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*//* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*/USART_InitTypeDef USART_InitStructure;/* Private function prototypes -----------------------------------------------*/#ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif /* __GNUC__ */ /* Private functions ---------------------------------------------------------*/void delay(int t);void wwdg_nvic_config(void);void key_init(void);/** * @brief Main program * @param None * @retval None */int main(void){ int i = 0; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f4xx.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f4xx.c file */ /* USARTx configured as follow: - BaudRate = 115200 baud - Word Length = 8 Bits - One Stop Bit - No parity - Hardware flow control disabled (RTS and CTS signals) - Receive and transmit enabled */ USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; STM_EVAL_COMInit(COM1, &USART_InitStructure); /* Output a message on Hyperterminal using printf function */ printf("\n\rUSART Printf Example\n\r"); /* key configuration */ key_init(); /* WWDG configuration */ /* Enable WWDG clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); /* WWDG clock counter = (PCLK1 (42MHz)/4096)/8 = 1281 Hz (~780 us) */ WWDG_SetPrescaler(WWDG_Prescaler_8); /* Set Window value to 80; WWDG counter should be refreshed only when the counter is below 80 (and greater than 64) otherwise a reset will be generated */ WWDG_SetWindowValue(120); /* Enable WWDG and set counter value to 127, WWDG timeout = ~780 us * 64 = 49.92 ms In this case the refresh window is: ~780 * (127-80) = 36.6ms < refresh window < ~780 * 64 = 49.9ms */ WWDG_Enable(127); wwdg_nvic_config(); WWDG->SR = 0; WWDG_EnableIT(); while (1) { printf("%d\r\n", i++); delay(1000); }}void delay(int t){ int i,j; for(i=0; i<t; i++) for(j=0; j<10000;j++) ;}/** * @brief Retargets the C library printf function to the USART. * @param None * @retval None */PUTCHAR_PROTOTYPE{ /* Place your implementation of fputc here */ /* e.g. write a character to the USART */ USART_SendData(EVAL_COM1, (uint8_t) ch); /* Loop until the end of transmission */ while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET) {} return ch;}#ifdef USE_FULL_ASSERT/** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */void assert_failed(uint8_t* file, uint32_t line){ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ while (1) { }}#endif/** * @} */ static int wwdg_clear_flag = 0;void WWDG_IRQHandler(void){ WWDG->SR = 0; if (wwdg_clear_flag == 0) //wwdg_clear_flag 在按鍵中斷中被設定為1 { /* Update WWDG counter */ WWDG->CR = 127 & 0x7F; delay(1); }}void wwdg_nvic_config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}static void key_gpio_init(void){ GPIO_InitTypeDef GPIO_InitStructure; /* 使能時鐘 */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | \ RCC_AHB1Periph_GPIOF | \ RCC_AHB1Periph_GPIOD, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; /* 初始化中斷按鍵 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOA, &GPIO_InitStructure); /* 初始化輪詢按鍵 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; GPIO_Init(GPIOF, &GPIO_InitStructure); /* 初始化LED引腳 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_Init(GPIOD, &GPIO_InitStructure);}static void key_exti_config(void){ EXTI_InitTypeDef EXTI_InitStructure; /* 串連PA0到外部中斷線0 */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); /* 配置外部中斷線0 */ EXTI_InitStructure.EXTI_Line = EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);}static void key_nvic_config(void){ NVIC_InitTypeDef NVIC_InitStructure; /* 使能外部中斷0 */ NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}void key_init(void){ key_gpio_init(); key_exti_config(); key_nvic_config();}void EXTI0_IRQHandler(void){ extern int stop_feed_dog; /* 清除中斷標誌 */ printf("key isr\r\n"); wwdg_clear_flag = 1; EXTI_ClearITPendingBit(EXTI_Line0);}/** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/