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
Недавні записи
- Модуль драйверів напівмосту IGBT транзисторів
- Драйвер IGBT транзисторів на A316J
- AS5600. Варіант встановлення на BLDC мотор
- DC-DC для IGBT драйверів ізольований 2 W +15 -8 вольт
- U-FOC - Векторне керування безколекторними моторами
- FOC - своя реалізація векторного керування. Підбиваю підсумки 2022 року
- Конструктор регуляторів моторів. Підбиваю підсумки 2022 року.
- Чому трифазні мотори стали такими популярними?
- FOC & Polar coordinates
- Конструктор регуляторів PMSM, BLDC двигунів
Tags
ngnix avr brushless motor examples dma books lcd usb dht11 piezo led servo web pmsm esp8266 ssd1331 wifi bme280 mpu-9250 capture hih-4000 bldc programmator rs-232 ethernet docker dc-dc sms bkp stm32 css git uart meteo bmp280 3d-printer displays mpx4115a eeprom max1674 soldering atmega timer gps tim flash nvic html java-script pwm solar rfid nodemcu st-link options watchdog adc gpio battery bluetooth raspberry-pi python websocket usart foc mongodb flask mpu-6050 barometer exti smd ssd1306 i2c sensors remap rtc encoder eb-500
Архіви