Timer16 Использование прерываний: различия между версиями

Материал из MIK32 микроконтроллер
Нет описания правки
Нет описания правки
Строка 427: Строка 427:
На временной диаграмме видны однократные срабатывания прерываний по сравнению (CMP) и перезагрузке (ARR) на выводах GPIO0.0 и GPIO0.2 соответственно:
На временной диаграмме видны однократные срабатывания прерываний по сравнению (CMP) и перезагрузке (ARR) на выводах GPIO0.0 и GPIO0.2 соответственно:


==== Пример с использованием двух таймеров ====
Подобный подход можно применить к прерываниям от двух таймеров. В примере ниже запущены два таймера. В их обработчиках меняется состояние выводов GPIO0.3 и GPIO1.3, это происходит "околосинхронно".


На временной диаграмме видны однократные срабатывания прерываний по сравнению (CMP) и перезагрузке (ARR) на выводах GPIO0.0 и GPIO0.2 соответственно:
Программа работает неправильно при следующих условиях:


На временной диаграмме видны однократные срабатывания прерываний по сравнению (CMP) и перезагрузке (ARR) на выводах GPIO0.0 и GPIO0.2 соответственно:
* Закомментирована строка #define TIMER_CMP_IRQ_WORKAROUND;
* Работа из внешней флеш в режиме Quad SPI или XIP с кэшированием.


{{#spoiler:show=Развернуть код|hide=Свернуть код|
Это выражается в несинхронном переключении выводов.
 
Фрагменты, активные при заданном макросе TIMER_CMP_IRQ_WORKAROUND, отвечают за обход повторной установки флага CMP.
 
Код примера представлен ниже:{{#spoiler:show=Развернуть код|hide=Свернуть код|
<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
#include "mik32_hal.h"
#include "mik32_hal.h"

Версия от 13:19, 5 марта 2025

Особенность установки флагов прерываний

Флаг прерывания по сравнению выставляется, если значение счета таймера совпадает со значением сравнения. Из-за этого возможна ситуация, когда после сброса флага прерывания по сравнению внутри обработчика флаг снова выставляется на следующем такте, если счетчик таймера не успел увеличиться. В таком случае, после выхода из обработчика прерывания происходит повторное срабатывание.

Пример ниже демонстрирует эту ситуацию. В этом примере Timer16 тактируется от встроенного низкочастотного источника тактирования.

Timer16 Многократные срабатывания прерываний.png

На временной диаграмме видны многократные срабатывания прерывания по сравнению (CMP). Однократные прерывания по перезагрузке (ARR) связаны с реализацией Timer16.

Варианты обхода

Повторная установка флага потребует подбора обходного пути в зависимости от задачи. Основная идея - отключение прерывания на время счета, равного значению сравнения. Рассмотрим некоторые из возможных обходных путей работы с прерываниями по сравнению.

Отключение прерывания по сравнению и повторное включение в основном цикле

Один из возможных вариантов обхода: временное отключение прерывания по сравнению на время до смены значения счетчика в другой части программы, например, в основном цикле, как в примере ниже:

Timer16 Однократные срабатывания прерываний.png

На временной диаграмме видны однократные срабатывания прерываний по сравнению (CMP) и перезагрузке (ARR):

Такой вариант можно использовать, если программа работает в режиме pooling'а, регулярно вызывая основной цикл.

Отключение прерывания по сравнению и повторное включение в прерывании по перезагрузке

Возможный вариант обхода: отключение прерывания по сравнению и повторное включение в прерывании по переполнению. Пример представлен ниже:

Timer16 Однократные срабатывания прерываний 2.png

На временной диаграмме видны однократные срабатывания прерываний по сравнению (CMP) и перезагрузке (ARR) на выводах GPIO0.0 и GPIO0.2 соответственно:

Пример с использованием двух таймеров

Подобный подход можно применить к прерываниям от двух таймеров. В примере ниже запущены два таймера. В их обработчиках меняется состояние выводов GPIO0.3 и GPIO1.3, это происходит "околосинхронно".

Программа работает неправильно при следующих условиях:

  • Закомментирована строка #define TIMER_CMP_IRQ_WORKAROUND;
  • Работа из внешней флеш в режиме Quad SPI или XIP с кэшированием.

Это выражается в несинхронном переключении выводов.

Фрагменты, активные при заданном макросе TIMER_CMP_IRQ_WORKAROUND, отвечают за обход повторной установки флага CMP.

Код примера представлен ниже: