Программирование ARM ESP32 General Purpose Timer Fri, December 06 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


ESP32 General Purpose Timer Печать
Добавил(а) microsin   

Чип ESP32 содержит 2 группы аппаратных таймеров. У каждой группы есть два 64-битного таймера общего назначения. У каждого таймера есть 16-битный прескалер и 64-битные счетчики, которые могут считать вверх и вниз, с возможностью автозагрузки значения в счетчик.

В следующих секциях этого документа (перевод документации [1]) описываются типовые шаги, необходимые для конфигурирования и работы таймера:

• Инициализация таймера - какие параметры должны быть установлены для того, чтобы таймер заработал, а также варианты функциональности, предоставляемые в зависимости от конфигурации таймера.
• Управление таймером - как читать значение таймера, приостанавливать или запускать, и изменять его поведение.
• События (Alarms) - показано, как устанавливать и использовать alarm-ы.
• Прерывания - как использовать callback-и прерывания.

[Инициализация таймера]

В двух группах таймеров ESP32, по 2 таймера в каждой, предоставляется для общего использования 4 индивидуальных таймера. Группа таймеров ESP32 идентифицируется с использованием типа timer_group_t. Отдельный таймер в группе идентифицируется значением типа timer_idx_t.

Сначала таймер должен быть инициализирован вызовом функции timer_init() с передачей ей структуры timer_config_t, параметры в которой определяют, как должен работать таймер. В частности, могут быть установлены параметры:

Clock Source: выбирается источник тактирования, который вместе с параметром Divider определяет разрешающую способность таймера. По умолчанию источником тактов установлен APB_CLK (обычно 80 МГц).
Divider: устанавливает деление тактовой частоты для таймера, определяет как быстро происходят "тики" таймера.
Mode: устанавливает, должен ли счетчик инкрементироваться или декрементироваться. Это определяется значением поля counter_dir, которое может быть установлено в одно из двух значений из timer_count_dir_t.
Counter Enable: если счетчик разрешен, то он начнет инкрементироваться / декрементироваться сразу после вызова timer_init(). Вы можете поменять это поведение установкой поля counter_en, которое может быть одним из значений timer_start_t.
Alarm Enable: можно установить с помощью поля alarm_en.
Auto Reload: устанавливает, должен ли счетчик автоматически загружать начальное значение при событии alarm, либо продолжать инкремент или декремент.

Чтобы получить текущие значения настройки таймера, используйте функцию timer_get_config().

[Управление таймером]

Как только таймер был разрешен, его счетчик начинает изменяться с заданной тактовой частотой. Для разрешения таймера вызовите timer_init() с counter_en, установленным в true, либо вызовите timer_start(). Вы можете указать начальное значение счетчика таймера вызовом timer_set_counter_value(). Для проверки текущего значения счетчика таймера вызовите timer_get_counter_value() или timer_get_counter_time_sec().

Для приостановки таймера в любой момент вызовите timer_pause(). Для возобновления работы таймера вызовите timer_start(). Для переконфигурирования таймера можно вызвать timer_init(). Также можно использовать выделенные функции для изменения отдельных настроек:

Таблица 1. Описание функций для изменения отдельных параметров таймера.

Настройка Функция Описание
Divider timer_set_divider() Меняет частоту тиков таймера. Чтобы избежать непредсказуемых результатов, таймер должен быть приостановлен перед изменением делителя. Если таймер работает, то timer_set_divider() приостанавливает его, меняет настройку делителя, и затем снова запускает таймер.
Mode timer_set_counter_mode() Устанавливает направление счета таймера - инкремент или декремент.
Auto Reload timer_set_auto_reload() Если установлено, то начальное значение таймера должно быть перезагружено при событии alarm.

[События (Alarms)]

Для установки alarm вызовите timer_set_alarm_value(), и затем разрешите alarm вызовом timer_set_alarm(). Работу alarm можно также разрешить на стадии инициализации таймера, когда вызывается функция timer_init().

После того, как alarm разрешена, и таймер достигает значения alarm, могут быть предприняты два действия в зависимости от конфигурации:

• Сработает прерывание, если оно было ранее разрешено. См. далее раздел "Прерывания", где описано, как они конфигурируются.
• Когда разрешена автозагрузка счетчика (auto_reload), счетчик таймера будет автоматически перезагружаться для начала счета от ранее сконфигурированного значения. Это значение должно быть установлено заранее вызовом timer_set_counter_value().

Замечания: если установлено значение alarm, и таймер уже достиг этого значения, то alarm сработает немедленно. Когда alarm сработала, она автоматически запрещается, и должна быть заново разрешена, чтобы она снова могла сработать.

Чтобы проверить указанное значение alarm, вызовите timer_get_alarm_value().

[Прерывания]

Регистрация callback-функции прерывания для определенного таймера делается вызовом timer_isr_callback_add() с передачей ей group ID, timer ID, обработчика callback и данных пользователя. Callback будет вызван в контексте ISR, поэтому в нем нельзя вставлять блокирующие вызовы API-функций и функции смены контекста. Достоинство использования callback-а вместо реализации ISR с нуля в том, что программисту не нужно иметь дело с проверкой статуса прерывания и связанными с этим очистками, эти действия выполняются в коде драйвера ISR по умолчанию, до вызова callback-а.

Для дополнительной информации по использованию прерываний см. проект peripherals/timer_group, который находится в папке examples среди других примеров кода, поставляемых вместе со средой разработки ESP-IDF [2].

[Справочник по API]

Файл заголовка API-функций таймера: driver/include/driver/timer.h. Описание типов: hal/include/hal/timer_types.h.

Функция Описание
timer_get_counter_value Считывает значение счетчика аппаратного таймера.
timer_get_counter_time_sec Считывает значение счетчика аппаратного таймера в заданных единицах времени.
timer_set_counter_value Установит значение счетчика аппаратного таймера.
timer_start Запустит счетчик аппаратного таймера.
timer_pause Приостановит счет аппаратного таймера.
timer_set_counter_mode Установит направление счета аппаратного таймера.
timer_set_auto_reload Разрешит или запретит загрузку значения счетчика, когда происходит событие alarm.
timer_set_divider Установит коэффициент деления тактовой частоты таймера. Частота групп таймеров получается делением частоты тактов шины APB.
timer_set_alarm_value Установит значение alarm таймера.
timer_get_alarm_value Возвратит значение alarm таймера.
timer_set_alarm Разрешает или запрещает генерацию событий alarm таймера.
timer_isr_callback_add Добавит callback-обработчик прерывания для соответствующего таймера(1). Этот callback должен вернуть значение bool, которое определяет, нужно ли уступить контекст (YIELD) по окончанию ISR. Замечание: этот обработчик будет вызван из тела ISR, но в обработчике не надо обрабатывать статус прерывания, и его код должен быть настолько коротким, насколько это возможно. Если нужно реализовать какие-то специальные приложения, или переписать ISR полностью, то можете вызвать timer_isr_register() для регистрации ISR.
timer_isr_callback_remove Удалит callback-обработчик для соответствующего таймера.
timer_isr_register Регистрирует обработчик прерывания таймера (ISR). Этот обработчик будет подключен к тому же ядру CPU, на котором был вызов timer_isr_register(1). Для конфигурирования таймеров внутри ISR используйте прямой доступ к регистрам таймера. Кроме того, необходимо полностью реализовать весь код обработчика ISR таймера, т. е. нужно вызвать timer_spinlock_take() перед кодом обработчика и вызвать timer_spinlock_give() после.
timer_init Инициализирует и конфигурирует таймер.
timer_deinit Деинициализирует таймер.
timer_get_config Считывает параметры конфигурации таймера.
timer_group_intr_enable По маске разрешает прерывание группы таймеров.
timer_group_intr_disable По маске запрещает прерывание группы таймеров.
timer_enable_intr Разрешает прерывание таймера.
timer_disable_intr Запрещает прерывание таймера.
timer_group_intr_clr_in_isr Очищает статус прерывания таймера(2).
timer_group_clr_intr_status_in_isr
timer_group_enable_alarm_in_isr Разрешает прерывание alarm(2).
timer_group_get_counter_value_in_isr Вернет текущее значение счетчика(2).
timer_group_set_alarm_value_in_isr Установит порог alarm(2).
timer_group_set_counter_enable_in_isr Разрешит или запретит счетчик таймера(2).
timer_group_intr_get_in_isr Вернет маскированный статус прерывания(2).
timer_group_get_intr_status_in_isr Вернет статус прерывания(2).
timer_group_clr_intr_sta_in_isr Очистит маскированный статус прерывания(2).
timer_group_get_auto_reload_in_isr Вернет статус разрешения автоматической загрузки(2).
timer_spinlock_take Получает spinlock таймера для входа в защищенный критический регион.
timer_spinlock_give Выдает spinlock таймера для выхода из защищенного критического региона.

Примечания:

(1) Если в параметре intr_alloc_flags установлено ESP_INTR_FLAG_IRAM, то обработчик должен быть декларирован с атрибутом IRAM_ATTR, и может вызывать только функции из IRAM или ROM. Он не может вызывать другие API-функции таймера.
(2) Эта функция используется только в теле ISR.

Подробное описание макросов, перечислений, определений типа и функций см. в документации [1].

[Ссылки]

1. ESP32 General Purpose Timer site:docs.espressif.com.
2. Установка среды разработки ESP-IDF для ESP32.
3. ESP32 High Resolution Timer.
4ESP32: оцифровка звука.

 

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


Защитный код
Обновить

Top of Page