STM32Cube. Работа с WWDG.

Одна из предыдущих статей была посвящена знакомству с одним из сторожевых таймеров микроконтроллеров STM32 — IWDG, и вот пришло время обсудить и второй тип таймера, а именно WWDG!

Сторожевой таймер

Задачи, которые призван решать WWDG, в целом, аналогичны тем задачам, которые решает сторожевой таймер IWDG, поэтому давайте сразу же сосредоточимся на отличиях. А отличия есть, и не одно )

  • Во-первых, в отличие от IWDG, который тактируется от низкочастотного генератора, WWDG тактируется, как и большинство остальных модулей микроконтроллера, от высокочастотного генератора. Частота тактирования таймера WWDG получается делением частоты PCLK1 (частота шины APB1) на постоянный делитель 4096. Кроме того, в настройках таймера мы можем добавить еще и дополнительный предделитель. Его возможные значения равны 1, 2, 4 и 8.
  • Во-вторых, отличие есть и в самом принципе работы. Если IWDG перезапускал контроллер в том случае, если он досчитает до 0, то WWDG работает иначе.

Собственно, на втором пункте остановимся поподробнее.

Значение периода WWDG мы можем установить равным величине, которая лежит в пределах от 64 до 127. Таким образом, таймер начинает считать вниз от того значения, которое мы в него записали, до 63 и, досчитав до 63, перезапускает контроллер.

Еще одним существенным отличием является то, что при работе с IWDG мы могли «перезагрузить» счетный регистр таймера в любой момент времени. WWDG же мы можем «обновить» только в определенный временной промежуток, который задается параметром Window value. Этот параметр мы также можем установить равным любому числу от 64 до 127.

Сейчас рассмотрим небольшой пример для лучшего понимания процесса.

Пусть значение периода таймера равно 100, а значение окна — 80. Включаем сторожевой таймер и он начинает считать от 100 до 63. Обновить значение WWDG мы сможем только после того, как таймер досчитает до 80. Если мы сделаем это раньше установленного срока, то произойдет перезапуск контроллера. Также контроллер будет перезапущен в том случае, если таймер досчитает до 63. Таким образом, при таких настройках параметров таймера мы можем обновить его счетный регистр в те моменты, когда его значение лежит в интервале от 63 до 80.

Вот как все это выглядит:

Принцип работы сторожевого таймера

И еще одним отличием WWDG от IWDG является то, что у WWDG есть свое собственное прерывание. Оно вызывается непосредственно перед перезапуском контроллера, когда таймер уже досчитал до 63. Нужно это для того, чтобы сохранить какие-нибудь важные данные, которые могут быть утеряны при перезапуске.

Давайте теперь перейдем в STM32Cube и создадим небольшой пример для демонстрации того, что мы сегодня обсудили. Активируем WWDG и внешний кварцевый генератор:

Конфигурация STM32Cube

Настройки тактирования в STM32Cube мы уже обсуждали, поэтому не буду приводить скриншот — у меня на APB1 приходит 24 МГц.

Давайте поставим значение периода таймера 120, предделитель — 1, а значение окна — 80. Давайте заодно активируем прерывание во вкладке NVIC Settings:

Настройка таймера WWDG

Тогда таймер перезапустится по истечению интервала:

T = 1000 / 24000000 * 4096 * 1 * (120-63) = 9.73 мс

То есть если мы запустим таймер, но не будем обновлять значение счетчика, то контроллер перезапустится через 9.73 мс.

Давайте также рассчитаем, по истечению какого интервала времени мы сможем обновлять значение счетного регистра:

t = 1000 / 24000000 * 4096 * 1 * (120-80) = 6.82 мс

  • 1000 / 24000000 — находим период (в мс), соответствующий частоте 24 МГц
  • Поскольку частота WWDG дополнительно делится на 4096, то длительность тика умножаем на 4096
  • 1 — это наш дополнительный предделитель — он равен единице.
  • Таким образом выражение 1000 / 24000000 * 4096 * 1 — это длительность одного «тика» таймера. Теперь остается только умножить ее на нужное количество тиков.

Таким образом, мы должны действовать примерно так:

  • Запускаем WWDG
  • Проверяем, если с момента запуска/обновления регистра прошло 6.82 мс — обновляем значение счетчика

Давайте теперь посмотрим, как это реализовано программно. Инициализация:

/* WWDG init function */
void MX_WWDG_Init(void)
{
 
  hwwdg.Instance = WWDG;
  hwwdg.Init.Prescaler = WWDG_PRESCALER_1;
  hwwdg.Init.Window = 80;
  hwwdg.Init.Counter = 120;
  HAL_WWDG_Init(&hwwdg);
 
}

После вызова этой функции необходимо запустить таймер, поскольку у нас будет использоваться прерывание, делаем это следующим образом:

HAL_WWDG_Start_IT(&hwwdg);

Обновление значения счетчика производится так:

HAL_WWDG_Refresh(&hwwdg, 120);

Ну и сам обработчик прерывания:

/**
* @brief This function handles Window Watchdog interrupt.
*/
void WWDG_IRQHandler(void)
{
  /* USER CODE BEGIN WWDG_IRQn 0 */
 
  /* USER CODE END WWDG_IRQn 0 */
  HAL_WWDG_IRQHandler(&hwwdg);
  /* USER CODE BEGIN WWDG_IRQn 1 */
 
  /* USER CODE END WWDG_IRQn 1 */
}

В общем-то все довольно просто реализовано, гораздо сложнее оказался сам принцип работы сторожевого таймера WWDG.

Думаю на этом можно и закончить сегодняшнюю статью, оставайтесь с нами и следите за обновлениями сайта! 😉

Понравилась статья? Поделись с друзьями!

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *