17. STM32. Програмування STM32F103. Watchdog
Сторожові таймери (Watchdog) існують для того, щоб у разі зависання програми мікроконтролера його (мікроконтролер) можна було перезавантажити. STM32 мають два watchdog. Їх звати IWDG і WWDG. IWDG - незалежний ("I" - Independent), доступний повсякчас. WWDG - більш обмежений ("W" - Window). Робота watchdog проста - якщо Ви його завели у своєму господарстві (налаштували і запустили), тоді треба його періодично годувати (скидати лічильник). Якщо лічильник не обновляти певний час, watchdog вважає, що з мікроконтролером щось не так і перезавантажує його. Це головна ідея watchdog. Тепер розглянемо їх детальніше і розберемо, у чому різниця між IWDG і WWDG.
IWDG - Independent Watchdog
Independent - незалежний Watchdog. IWDG тактується від окремого, вбудованого у мікроконтролера, генератора низької частоти. Дивись: 4. STM32. Програмування STM32F103. Тактування.Ініціалізація IWDG виконується наступним чином:
- Вмикається LSI (40 kHz) (генератор низької частоти, яким тактується IWDG)
- Вмикається доступ до регістрів IWDG
- Налаштовується дільник вхідної частоти
- Встановлюється лічильник (від 0 до 0x0FFF)
- Вмикається IWDG
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_iwdg.h"
#include "misc.h"
int main(void)
{
int i;
/* Initialize Leds mounted on STM32 board */
GPIO_InitTypeDef GPIO_InitStructure;
/* Initialize LED which connected to PC13, Enable the Clock*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Configure the GPIO_LED pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Disable LED */
GPIO_SetBits(GPIOC, GPIO_Pin_13);
/* delay */
for(i=0;i<0x100000;i++);
/* Enable the LSI OSC */
RCC_LSICmd(ENABLE);
/* Wait till LSI is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{}
/* Enable Watchdog*/
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_4); // 4, 8, 16 ... 256
IWDG_SetReload(0x0FFF);//This parameter must be a number between 0 and 0x0FFF.
IWDG_ReloadCounter();
IWDG_Enable();
/* Enable LED */
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
while (1)
{
//IWDG_ReloadCounter();
}
}
Оскільки IWDG тактується від власного генератора, він спрацює навіть у тому випадку, якщо від мікроконтролера відвалиться джерело тактування, наприклад кварц. Якщо при старті контролера програма перевіряє наявність джерела тактування, контролер зможе згенерувати відповідне повідомлення чи перейти на інше джерело тактування, а не просто повиснути.
WWDG - Window Watchdog
На відмінність від IWDG, WWDG тактується частотою, якою тактується мікроконтролер. Вірніше сказати, частота тактування WWDG дорівнює частоті PCLK1 (частота на виході APB1), поділена на постійний дільник 4096. Таким чином можна сказати, що робота WWDG синхронізована з роботою програми мікроконтролера.До чого тут Window? Для WWDG можна налаштувати "вікно" (проміжок часу), у яке треба обновляти лічильник watchdog. Не раніше і не пізніше. Тобто, якщо WWDG обновити раніше або пізніше, ніж очікувалось, буде виконано перезавантаження мікроконтролера. Ця властивість використовується не тільки для контролю зависання програми, а ще для контролю несанкціонованих переходів. Наприклад, якщо з будь-яких причин була пропущена важлива процедура. Саме занадто малий час між подіями і може стати сигналом того, що критична процедура не була виконана.
У WWDG є особливість - лічильник працює у діапазоні від 127 до 64. Тобто, він рахує вниз від зазначеного числа до 64. Для того, щоб налаштувати вікно, нам треба щоб WindowValue було менше за початкове значення лічильника. Наприклад, ми встановили WindowValue = 90, а лічильник 120. WWDG починає зменшувати лічильник від 120 до 64. І, якщо ми перезапишемо лічильник раніше, ніж він дорахує до 90, відбудеться перезавантаження мікроконтролера, бо ми не попали у вікно.
Якщо WindowValue рівна або більша за лічильник, тоді WWDG працює як звичайний watchdog.
Ініціалізація WWDG виконується наступним чином:
- Вмикається тактування WWDG
- Налаштовується дільник вхідної частоти
- Встановлюється вікно (від 64 до 127)
- Встановлюється лічильник (від 64 до 127) і вмикається WWDG
- Вмикається і налаштовується переривання, якщо потрібно
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_wwdg.h"
int main(void)
{
int i;
/* Initialize Leds mounted on STM32 board */
GPIO_InitTypeDef GPIO_InitStructure;
/* Initialize LED which connected to PC13, Enable the Clock*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Configure the GPIO_LED pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Disable LED */
GPIO_SetBits(GPIOC, GPIO_Pin_13);
/* delay */
for(i=0;i<0x100000;i++);
/* Enable Watchdog*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
WWDG_DeInit();
WWDG_SetPrescaler(WWDG_Prescaler_8);
WWDG_SetWindowValue(0x7F);
WWDG_Enable(0x5F);
/* Enable LED */
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
while (1)
{
//WWDG_SetCounter(0x5F);
}
}
Для WWDG можна налаштувати обробку переривання. Наприклад, нам потрібно зберегти якісь дані перед перезавантаженням. Або виконати якісь процедури і вирішити чи дійсно треба перезавантажити мікроконтролер чи дозволити йому працювати далі. Якщо скинути прапор WWDG функцією WWDG_ClearFlag() перезавантаження не відбудеться.
Приклад:
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_wwdg.h"
#include "misc.h"
void WWDG_IRQHandler(void) {
int i;
WWDG_ClearFlag(); //This function reset flag WWDG->SR and cancel the resetting
WWDG_SetCounter(100);
/* Toggle LED which connected to PC13*/
GPIOC->ODR ^= GPIO_Pin_13;
}
int main(void)
{
/* Initialize Leds mounted on STM32 board */
GPIO_InitTypeDef GPIO_InitStructure;
/* Initialize LED which connected to PC13, Enable the Clock*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Configure the GPIO_LED pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Disable LED */
GPIO_SetBits(GPIOC, GPIO_Pin_13);
/* Enable Watchdog*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
WWDG_DeInit();
WWDG_SetPrescaler(WWDG_Prescaler_8); //1, 2, 4, 8
WWDG_SetWindowValue(127); // 64...127
WWDG_Enable(100);
WWDG_EnableIT();
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; /*WWDG interrupt*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);/* NVIC initialization*/
while (1)
{
}
}
Пам`ятка
WWDG тактується частотою: (PCLK1/4096)/WWDG_PrescalerІнтервал до перезавантаження розраховується як: T = 1000 / PCLK1 * 4096 * WWDG_Prescaler * (Counter - 63) мс Наприклад: T = 1000 / 8000000 * 4096 * 1 * (120-63) = 29.184 мс
Інтервал, після якого можна обновляти лічильник WWDG, розраховується як: t = 1000 / PCLK1 * 4096 * WWDG_Prescaler * (Counter - WindowValue) мс Наприклад: t = 1000 / 8000000 * 4096 * 1 * (120-80) = 20.48 мс
Бажаю успіхів!
Дивись також:
- 1. STM32. Програмування STM32F103. Тестова плата. Прошивка через UART та через ST-Link
- 2. STM32. Програмування. IDE для STM32
- 3. STM32. Програмування STM32F103. GPIO
- 4. STM32. Програмування STM32F103. Тактування
- 5. STM32. Програмування STM32F103. USART
- 6. STM32. Програмування STM32F103. NVIC
- 7. STM32. Програмування STM32F103. ADC
- 8. STM32. Програмування STM32F103. DMA
- 9. STM32. Програмування STM32F103. TIMER
- 10. STM32. Програмування STM32F103. TIMER. Захоплення сигналу
- 11. STM32. Програмування STM32F103. TIMER. Encoder
- 12. STM32. Програмування STM32F103. TIMER. PWM
- 13. STM32. Програмування STM32F103. EXTI
- 14. STM32. Програмування STM32F103. RTC
- 15. STM32. Програмування STM32F103. BKP
- 16. STM32. Програмування STM32F103. Flash
- 17. STM32. Програмування STM32F103. Watchdog
- 18. STM32. Програмування STM32F103. Remap
- 19. STM32. Програмування STM32F103. I2C Master
- 20. STM32. Програмування STM32F103. I2C Slave
- 21. STM32. Програмування STM32F103. USB
- 22. STM32. Програмування STM32F103. PWR
- 23. STM32. Програмування STM32F103. Option bytes
- 24. STM32. Програмування STM32F103. Bootloader
- STM32. Скачати приклади
- System Workbench for STM32 Інсталяція на Ubuntu
- Keil uVision5 – IDE для STM32
- IAR Workbench – IDE для STM32
- Керування безколекторним двигуном постійного струму (BLDC) за допомогою STM32
- Керування PMSM за допомогою STM32
Недавні записи
- DShot receiver on STM32
- CRSF to PWM
- U-FOC PC Monitor для Chrome browser
- Фільтрація Back-EMF. Безсенсорні BLDC мотори
- Text to speech. Українська мова
- LCD Display ST7567S (IIC)
- Розпізнавання мови (Speech recognition)
- Selenium
- Комп'ютерний зір (Computer Vision)
- Деякі думки про точність вимірювань в електроприводі
Tags
git wifi encoder solar atmega ssd1331 sensors nvic piezo rfid smd python usb rtc motor timer bmp280 mpu-9250 barometer ethernet html books sms flask ssd1306 adc battery max1674 lcd soldering avr bldc stm32 mongodb 3d-printer remap eeprom dc-dc displays java-script nodemcu programmator gps watchdog gpio raspberry-pi websocket flash rs-232 css hih-4000 foc brushless esp8266 uart meteo bme280 mpu-6050 examples i2c servo capture bluetooth led web options bkp pwm usart exti st-link tim docker ngnix dma pmsm dht11 eb-500 mpx4115a
Архіви