Esp32 arduino timer: Timer — Arduino-ESP32 2.0.2 documentation

Таймер общего назначения — ESP32

[中文]

Введение

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

Функциональный обзор

В следующих разделах этого документа описаны типичные шаги по настройке и работе с таймером:

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

  • Управление таймером — описывает, как считывать значение таймера, приостанавливать или запускать таймер, а также изменять его работу.

  • Сигналы тревоги — показывает, как устанавливать и использовать сигналы тревоги.

  • Прерывания — объясняет, как использовать обратные вызовы прерывания.

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

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

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

  • Источник тактового сигнала : Выберите источник тактового сигнала, который вместе с делителем определяют разрешение рабочего таймера. По умолчанию источником синхронизации является APB_CLK (обычно 80 МГц).

  • Делитель : Устанавливает скорость «тикания» счетчика таймера. Параметр делитель используется как делитель источника тактового сигнала.

  • Режим : Устанавливает, должен ли счетчик увеличиваться или уменьшаться. Его можно определить с помощью counter_dir , выбрав одно из значений из timer_count_dir_t .

  • Включение счетчика : Если счетчик включен, он начнет увеличиваться/уменьшаться сразу после вызова timer_init() . Вы можете изменить поведение с помощью counter_en , выбрав одно из значений из timer_start_t .

  • Включение тревоги : Можно установить с помощью alarm_en .

  • Автоматическая перезагрузка : Устанавливает, должен ли счетчик auto_reload начальное значение счетчика сигнала тревоги таймера или продолжить увеличение или уменьшение.

Чтобы получить текущие значения настроек таймера, используйте функцию 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() . Эта функция описана в разделе Инициализация таймера.

Вы также можете перенастроить таймер, используя специальные функции для изменения индивидуальных настроек:

Настройка

Специальная функция

Описание

Разделитель

timer_set_divider()

Изменить скорость тиканья. Во избежание непредсказуемых результатов таймер следует ставить на паузу при смене делителя. Если таймер работает, timer_set_divider() приостанавливает его, изменяет настройку и снова запускает таймер.

Режим

timer_set_counter_mode()

Установить, должен ли счетчик увеличиваться или уменьшаться

Автоматическая перезагрузка

timer_set_auto_reload()

Установите, следует ли перезагружать начальное значение счетчика при тревоге таймера

Тревоги

Чтобы установить будильник, вызовите функцию timer_set_alarm_value() , а затем включите будильник с помощью timer_set_alarm() . Тревогу также можно включить на этапе инициализации таймера, когда вызывается timer_init() .

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

  • Будет запущено прерывание, если оно было настроено ранее. См. Раздел «Прерывания» о том, как настроить прерывания.

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

Примечание

  • Если установлено значение сигнала тревоги, а таймер уже достиг этого значения, сигнал тревоги срабатывает немедленно.

  • После срабатывания сигнал тревоги автоматически отключается, и его необходимо повторно включить для повторного срабатывания.

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

Прерывания

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

Для получения дополнительной информации об использовании прерываний см. приведенный ниже пример приложения.

Пример приложения

Пример 64-битного аппаратного таймера: периферия/timer_group.

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

Функции

esp_err_t timer_get_counter_value (timer_group_t group_num , timer_idx_t timer_num , uint64_t * timer_val )

Считать значение счетчика аппаратного таймера.

Возврат
Параметры
  • group_num : Группа таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • timer_val : Указатель для приема значения счетчика таймера.

esp_err_t timer_get_counter_time_sec (timer_group_t group_num , timer_idx_t timer_num , double * время )

Чтение значения счетчика аппаратного таймера в единицах заданной шкалы.

Возврат
Параметры
  • group_num : Группа таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • time : Указатель, тип double*, для приема значения счетчика таймера в секундах.

esp_err_t timer_set_counter_value (timer_group_t group_num , timer_idx_t timer_num , uint64_t load_val )

Установить значение счетчика на аппаратный таймер.

Возврат
Параметры
  • group_num : Группа таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • load_val : Значение счетчика для записи в аппаратный таймер.

esp_err_t timer_start (timer_group_t group_num , timer_idx_t timer_num )

Запуск счетчика аппаратного таймера.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

esp_err_t timer_pause (timer_group_t group_num , timer_idx_t timer_num )

Приостановить счетчик аппаратного таймера.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

esp_err_t timer_set_counter_mode (timer_group_t group_num , timer_idx_t timer_num , timer_count_dir_t counter_dir )

Установка режима счета для аппаратного таймера.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • counter_dir : Направление счета таймера, прямой или обратный отсчет

esp_err_t timer_set_auto_reload (timer_group_t group_num , timer_idx_t timer_num , timer_autoreload_t reload )

Включение или отключение функции перезагрузки счетчика при возникновении аварийного события.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • перезагрузка : Режим перезагрузки счетчика.

esp_err_t timer_set_divider (timer_group_t group_num , timer_idx_t timer_num , uint32_t делитель )

Установка делителя частоты источника аппаратного таймера. Часы групп таймеров являются делителем часов APB.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • делитель : Значение делителя часов таймера. Диапазон делителя от 2 до 65536.

esp_err_t timer_set_alarm_value (timer_group_t group_num , timer_idx_t timer_num , uint64_t alarm_value )

Установка значения сигнала тревоги таймера.

Возврат
Параметры
  • group_num : Группа таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • alarm_value : 64-битное значение для установки значения аварийного сигнала.

esp_err_t timer_get_alarm_value (timer_group_t group_num , timer_idx_t timer_num , uint64_t * alarm_value )

Получить значение сигнала таймера.

Возврат
Параметры
  • group_num : Группа таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • alarm_value : Указатель 64-битного значения для принятия значения аварийного сигнала.

esp_err_t timer_set_alarm (timer_group_t group_num , timer_idx_t timer_num , timer_alarm_t alarm_en )

Включить или отключить генерацию тревожных событий таймера.

Возврат
Параметры
  • group_num : Группа таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • alarm_en : Включение или отключение функции будильника по таймеру.

ESP_ERR_T TIMER_ISR_CALLBACK_ADD (TIMER_GROUP_T GROUP_NUM , TIMER_IDX_T TIMER_NUM , TIMER_ISR_T ISR_HANDLER , VOID * 9027 AGR_T ISR_HANDLER , VOID * AGR_T ISR_HANDLER , VOID * AGR_T ISR_HANDLE

Добавить обратный вызов дескриптора ISR для соответствующего таймера.

Обратный вызов должен возвращать логическое значение, чтобы определить, нужно ли выполнять YIELD в конце ISR.

Примечание

Этот обработчик ISR будет вызываться из ISR. Этот обработчик ISR не должен обрабатывать статус прерывания и должен быть коротким. Если вы хотите реализовать некоторые конкретные приложения или написать весь ISR, вы можете вызвать timer_isr_register(…) для регистрации ISR.

Параметры
  • group_num : Номер группы таймеров

  • timer_num : Индекс таймера группы таймеров

  • isr_handler : Функция обработчика прерываний, это функция обратного вызова.

  • arg : Параметр для функции обработчика

  • intr_alloc_flags : Флаги, используемые для выделения прерывания. Одно или несколько (ORred) значений ESP_INTR_FLAG_*. См. esp_intr_alloc. h для получения дополнительной информации.

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

Возврат
esp_err_t timer_isr_callback_remove (timer_group_t group_num , timer_idx_t timer_num )

Удалить обратный вызов дескриптора ISR для соответствующего таймера.

Возврат
Параметры
esp_err_t timer_isr_register (timer_group_t group_num , timer_idx_t timer_num , void (* fn )(void *), void * arg , int intr_alloc_flags , timer_isr_handle_t * handle , )

Регистр Обработчик прерывания таймера, обработчик является ISR. Обработчик будет прикреплен к тому же ядру ЦП, на котором выполняется эта функция.

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

Примечание

Если использовать эту функцию для регистрации ISR, вам необходимо записать весь ISR. В обработчике прерывания вам нужно вызвать timer_spinlock_take(..) перед обработкой и вызвать timer_spinlock_give(…) после обработки.

Параметры
  • group_num : Номер группы таймеров

  • timer_num : Индекс таймера группы таймеров

  • fn : Функция обработчика прерываний.

  • arg : Параметр для функции обработчика

  • intr_alloc_flags : Флаги, используемые для выделения прерывания. Одно или несколько (ORred) значений ESP_INTR_FLAG_*. См. esp_intr_alloc.h для получения дополнительной информации.

  • дескриптор : Указатель на дескриптор возврата. Если не NULL, здесь будет возвращен дескриптор прерывания.

Возврат
esp_err_t timer_init (timer_group_t group_num , timer_idx_t timer_num , const timer_config_t * config )

Инициализирует и настраивает таймер.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • config : Указатель на параметры инициализации таймера.

esp_err_t timer_deinit (timer_group_t group_num , timer_idx_t timer_num )

Деинициализирует таймер.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

esp_err_t timer_get_config (timer_group_t group_num , timer_idx_t timer_num , timer_config_t * config )

Получить значение настройки таймера.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера, 0 для hw_timer[0] и 1 для hw_timer[1]

  • config : Указатель структуры для приема параметров таймера.

esp_err_t timer_group_intr_enable (timer_group_t group_num , timer_intr_t intr_mask )

Разрешение группового прерывания таймера по маске включения.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • intr_mask : Маска разрешения прерывания таймера.

    • TIMER_INTR_T0: прерывание t0

    • TIMER_INTR_T1: прерывание t1

    • TIMER_INTR_WDT: прерывание сторожевого таймера

esp_err_t timer_group_intr_disable (timer_group_t group_num , timer_intr_t intr_mask )

Отключить групповое прерывание таймера по маске отключения.

Возврат
Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • intr_mask : Маска отключения прерывания таймера.

    • TIMER_INTR_T0: прерывание t0

    • TIMER_INTR_T1: прерывание t1

    • TIMER_INTR_WDT: прерывание сторожевого таймера

esp_err_t timer_enable_intr (timer_group_t group_num , timer_idx_t timer_num )

Разрешить прерывание по таймеру.

Возврат
Параметры
esp_err_t timer_disable_intr (timer_group_t group_num , timer_idx_t timer_num )

Отключить прерывание таймера.

Возврат
Параметры
void timer_group_intr_clr_in_isr (timer_group_t group_num , timer_idx_t timer_num )

Очистить состояние прерывания таймера, только что использованное в ISR.

Параметры
недействительным timer_group_clr_intr_status_in_isr (timer_group_t group_num , timer_idx_t timer_num )

Очистить состояние прерывания таймера, только что использованное в ISR.

Параметры
void timer_group_enable_alarm_in_isr (timer_group_t group_num , timer_idx_t timer_num )

Разрешить прерывание по тревоге, только что использованное в ISR.

Параметры
uint64_t timer_group_get_counter_value_in_isr (timer_group_t group_num , timer_idx_t timer_num )

Получить текущее значение счетчика, только что использованное в ISR.

Возврат
  • Значение счетчика

Параметры
недействительным timer_group_set_alarm_value_in_isr (timer_group_t group_num , timer_idx_t timer_num , uint64_t alarm_val )

Установите порог срабатывания сигнализации для таймера, только что использованного в ISR.

Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера.

  • alarm_val : Порог срабатывания сигнализации.

void timer_group_set_counter_enable_in_isr (timer_group_t group_num , timer_idx_t timer_num , timer_start_t counter_en )

Включить/отключить счетчик, только что использованный в ISR.

Параметры
  • group_num : Номер группы таймеров, 0 для TIMERG0 или 1 для TIMERG1

  • timer_num : Индекс таймера.

  • counter_en : Включить/выключить.

timer_intr_t timer_group_intr_get_in_isr (timer_group_t group_num )

Получить статус замаскированного прерывания, только что использованного в ISR.

Возврат
  • Статус прерывания

Параметры
uint32_t timer_group_get_intr_status_in_isr (timer_group_t group_num )

Получить статус прерывания, только что использованный в ISR.

Возврат
  • Статус прерывания

Параметры
void timer_group_clr_intr_sta_in_isr (timer_group_t group_num , timer_intr_t intr_mask )

Очистить состояние замаскированного прерывания, только что использованного в ISR.

Параметры
bool timer_group_get_auto_reload_in_isr (timer_group_t group_num , timer_idx_t timer_num )

Получить статус включения автоматической перезагрузки, только что использованный в ISR.

Возврат
Параметры
esp_err_t timer_spinlock_take (timer_group_t group_num )

Включите спин-блокировку таймера, чтобы войти в критическую защиту.

Возврат
Параметры
esp_err_t timer_spinlock_give (timer_group_t group_num )

Установите блокировку таймера для выхода из критической защиты.

Возврат
Параметры

Макросы

ТАЙМЕР_BASE_CLK

Частота часов на входе групп таймеров

Определения типов

typedef bool (* timer_isr_t )(void *)

Функция обратного вызова обработчика прерывания. Пользователю необходимо повторно запустить логическое значение в обратном вызове.

Возврат
Примечание

Если вы вызвали функции FreeRTOS в обратном вызове, вам необходимо вернуть значение true или false в зависимости от возвращаемого значения аргумента pxHigherPriorityTaskWoken . Например, xQueueSendFromISR вызывается в обратном вызове, если возвращаемое значение pxHigherPriorityTaskWoken любого вызова FreeRTOS равно pdTRUE, возвращается true; в противном случае вернуть ложь.

определение типа intr_handle_t timer_isr_handle_t

Дескриптор прерывания, используемый для освобождения isr после использования. Псевдонимы для дескриптора int на данный момент.

Заголовочный файл

  • hal/include/hal/timer_types.h

Конструкции

структура timer_config_t

Структура данных с настройками конфигурации таймера.

Публичные участники

timer_alarm_t alarm_en

Включение тревоги по таймеру

timer_start_t counter_en

Включение счетчика

timer_intr_mode_t intr_type

Режим прерывания

timer_count_dir_t counter_dir

Встречное направление

timer_autoreload_t авто_перезагрузка

Автоматическая перезагрузка таймера

uint32_t делитель

Делитель счетчика часов. Диапазон делителя от 2 до 65536.

Списки

перечисление timer_group_t

Выбирает группу таймеров из 2 доступных групп.

Значения:

ТАЙМЕР_ГРУППА_0 = 0

Группа аппаратных таймеров 0

ТАЙМЕР_ГРУППА_1 = 1

Группа аппаратного таймера 1

ТАЙМЕР_ГРУППА_МАКС
перечисление timer_idx_t

Выберите аппаратный таймер из групп таймеров.

Значения:

ТАЙМЕР_0 = 0

Выберите таймер 0 из GROUPx

ТАЙМЕР_1 = 1

Выберите таймер 1 из GROUPx

ТАЙМЕР_МАКС
перечисление timer_count_dir_t

Определяет направление счетчика.

Значения:

TIMER_COUNT_DOWN = 0

Счет по убыванию от cnt.high|cnt.low

TIMER_COUNT_UP = 1

Счет по возрастанию от нуля

TIMER_COUNT_MAX
перечисление timer_start_t

Определяет, включен таймер или приостановлен.

Значения:

ТАЙМЕР_ПАУЗА = 0

Счетчик таймера паузы

ТАЙМЕР_СТАРТ = 1

Счетчик пускового таймера

перечисление timer_intr_t

Типы прерываний таймера.

Значения:

ТАЙМЕР_INTR_T0 = БИТ(0)

прерывание таймера 0

ТАЙМЕР_INTR_T1 = БИТ(1)

прерывание таймера 1

TIMER_INTR_WDT = БИТ(2)

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

ТАЙМЕР_ИНТР_НЕТ = 0
перечисление timer_alarm_t

Определяет, включать ли режим тревоги.

Значения:

ТАЙМЕР_ALARM_DIS = 0

Отключить тревогу таймера

ТАЙМЕР_АВАРИЙНЫЙ СИГНАЛ_EN = 1

Включить тревогу таймера

ТАЙМЕР_ALARM_МАКС
перечисление timer_intr_mode_t

Выберите тип прерывания при работе в режиме тревоги.

Значения:

ТАЙМЕР_INTR_LEVEL = 0

Режим прерывания: режим уровня

ТАЙМЕР_ИНТР_МАКС
перечисление timer_autoreload_t

Выберите, должен ли сигнал тревоги загружаться программно или автоматически перезагружаться аппаратно.

Значения:

ТАЙМЕР_АВТОЗАГРУЗКА_DIS = 0

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

ТАЙМЕР_АВТОЗАГРУЗКА_EN = 1

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

ТАЙМЕР_АВТОЗАГРУЗКА_МАКС

Функции, связанные со временем, и прерывания таймера

Таймеры являются одной из общих аппаратных функций всех микроконтроллеров. Таймеры и прерывания по таймеру очень полезны в приложениях микроконтроллеров. Прерывания по таймеру часто используются, когда требуется точное время без доли ошибки. Все порты MicroPython имеют один или несколько таймеров. Некоторые из этих таймеров могут быть зарезервированы для определенных функций, таких как работа в сети или Wi-Fi, а остальные таймеры могут использоваться в пользовательском приложении. В этой статье будут рассмотрены таймеры и реализация прерываний по таймеру в MicroPython. Затем мы рассмотрим таймеры, доступные в ESP8266 и ESP32. Наконец, мы будем использовать вышеупомянутые концепции для разработки тикера ESP8266.

Функции MicroPython, связанные со временем
MicroPython предоставляет модуль time для временных задержек, интервалов и обслуживания даты и времени. Этот модуль является повторной реализацией одноименного модуля CPython. Функции MicroPython, связанные со временем, совместимы со встроенными портами, которые используют эпоху 2000-01-01 00:00:00 UTC вместо системной эпохи POSIX 1970-01-01 00:00:00 UTC. Важно отметить, что настройка и обслуживание календарного времени зависит от ОС или RTOS, установленных на поддерживаемом порту, например, в Raspberry Pico. Встроенный RTC может управлять этим в случае портов микроконтроллера. Связанные со временем функции MicroPython запрашивают у ОС/RTOS или RTC сохранение или установку даты и времени. Установку времени можно выполнить вручную через сетевой протокол или резервную батарею.

Модуль time обеспечивает следующие функции времени, даты и задержки.

time.sleep(seconds) : Этот метод блокировки обеспечивает задержку в секундах. Некоторые порты позволяют указывать время задержки в виде числа с плавающей запятой. После вызова метода контроллер останавливает выполнение пользовательской программы на заданное количество секунд.

time.sleep_ms(ms) : Это еще один метод блокировки, обеспечивающий задержку в миллисекундах. По сравнению с time.sleep() этот метод более точен. В качестве аргумента этому методу может быть передано положительное число или ноль. Если он используется для прерывания по таймеру, задержка может продолжаться до тех пор, пока не завершится выполнение процедуры обслуживания прерывания. Если в качестве аргумента передается 0, задержка будет равна времени, затраченному на выполнение процедуры обслуживания прерывания.

time.sleep_us(us) : Это еще один метод блокировки, обеспечивающий задержку в микросекундах. В качестве аргумента может быть передано положительное число или ноль. Если используется для прерывания по таймеру, задержка может увеличиваться до завершения выполнения процедуры обслуживания прерывания. Если в качестве аргумента передается 0, задержка будет равна времени, затраченному на выполнение процедуры обслуживания прерывания.

time.ticks_ms() : Этот метод возвращает количество миллисекунд, прошедших после произвольной ссылки. Это чем-то похоже на функцию millis() в Arduino. Хотя функция millis() в Arduino возвращает временной интервал в миллисекундах с момента загрузки платы Arduino, time. ticks_ms() предполагает произвольный момент времени для справки. Значение переноса, используемое в качестве максимального диапазона, всегда находится в степени 2, поэтому оно остается одинаковым во всей реализации MicroPython независимо от порта. Он называется TICKS_PERIOD, что на единицу больше, чем TICKS_MAX. Следовательно, вызов этой функции всегда возвращает неотрицательное значение в диапазоне от 0 до TICKS_MAX включительно, что указывает на миллисекунды в указанном диапазоне, прошедшие далее в произвольный момент времени. Важно отметить, что, в отличие от Arduino, стандартные математические операторы или реляционные операторы либо напрямую, либо в качестве аргументов для ticks_diff() или ticks_add() методы для значений, возвращаемых этим методом, или отметка, как упомянутые выше методы, не разрешены. Такие операции могут привести к синтаксической ошибке (в зависимости от IDE) или ошибочным результатам.

time.ticks_us() : Этот метод аналогичен time. ticks_ms() , за исключением того, что он возвращает время в микросекундах из произвольного момента времени.

time.ticks_cpu() : этот метод аналогичен time.ticks_ms() и time.ticks_us() , за исключением того, что он возвращает такты ЦП, пройденные с произвольного момента времени. Он обеспечивает максимально возможное разрешение. Вместо тактов в некоторых портах может быть возвращена другая единица с самым высоким разрешением, обеспечиваемая встроенным таймером. Следует отметить, что этот метод доступен не для всех портов MicroPython. Поэтому перед использованием этого метода в скрипте MicroPython необходимо проверить документацию по конкретному порту.

time.ticks_add(ticks, delta) : Этот метод вычисляет крайние сроки для событий и задач микроконтроллера. В зависимости от времени он возвращает крайний срок в миллисекундах, микросекундах или цикле ЦП .ticks_ms() , time.ticks_us() или time.ticks_cpu() используется в качестве параметра тиков соответственно. Аргумент дельта может быть целым или числовым аргументом. Он равен количеству тиков, где тики могут быть миллисекундами, микросекундами или циклами ЦП, установленными в качестве крайнего срока. Например, следующий оператор возвращает крайний срок 200 миллисекунд.
крайний срок = ticks_add(time.ticks_ms(), 200)

Следующий оператор возвращает крайний срок 100 микросекунд.
крайний срок = ticks_add(time.ticks_us(), 100)

Следующий оператор возвращает крайний срок в 20 циклов ЦП.
крайний срок = ticks_add(time.ticks_cpu(), 20)

time.ticks_diff(ticks1, ticks2) : этот метод возвращает разницу между двумя тиками. Разница в тиках может быть в миллисекундах, микросекундах или циклах ЦП в зависимости от того, что возвращает 9Функции 0275 time.ticks_ms() , time.ticks_us() или time.ticks_cpu() используются в качестве тиков соответственно. Возвращаемое значение — ticks1-ticks2, которое может варьироваться от -TICKS_PERIOD/2 до TICKS_PERIOD/2 — 1. Функция time.ticks_diff() полезна при опросе времени ожидания, планировании встроенной задачи или расчете крайнего срока.

time.time() : Этот метод возвращает количество секунд с начала эпохи при условии, что RTC данного порта установлен и поддерживается. Эпоха совместима со встроенными функциями, а возвращаемое время — это количество секунд, прошедших с 01 января 2000 г. в 00:00:00 UTC. Эпоха может быть ссылкой для конкретного порта, например, временем с момента включения питания или сброса в некоторых портах.

time.time_ns() : Этот метод возвращает количество микросекунд с начала эпохи. Это очень полезно для определения абсолютного времени. Значение, возвращаемое этим методом, является целым числом.

time.mktime() : Этот метод возвращает количество секунд, прошедших между эпохой (т. е. 01.01.2000 00:00:00 UTC) и местным временем, переданным в качестве аргумента. Метод принимает полный 8-кортеж как местное время, где кортеж имеет следующий формат — (год, месяц, день, час, минута, секунда, день недели, день года), где значения кортежа должны быть в следующем диапазоне.

года нашей эры

Год год
месяц 1~12
мдень 1~31
час 0~23
минута 0~59
второй 0~59
рабочий день 0~6 для Пн~Вс
годдень 1~366

 

time.gmtime([secs]) : Этот метод возвращает дату-время в формате UTC, начиная с секунд, указанных в качестве аргумента. Возвращаемое время представляет собой кортеж в формате (год, месяц, mday, час, минута, секунда, день недели, день года).

time.localtime([secs]) : Этот метод возвращает дату-время по местному времени, поскольку в качестве аргумента указаны секунды. Возвращаемое время представляет собой кортеж в формате (год, месяц, mday, час, минута, секунда, день недели, день года). Местное время может быть установлено в соответствии с ОС/RTOS или RTC.

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

Ниже приведен допустимый пример расчета времени, затрачиваемого на выполнение части скрипта MicroPython.
время импорта
начало = time.ticks_us()
… # Операторы MicroPython для проверки времени
print(time.ticks_diff(time.ticks_us(), start))

Ниже приведен допустимый пример нахождения TICKS_MAX заданного порта.
print(ticks_add(0, -1))

Ниже приведен правильный пример установки крайнего срока для встроенной задачи.
крайний срок = ticks_add(time.ticks_ms(), 200)
в то время как ticks_diff(крайний срок, time. ticks_ms()) > 0:
do_a_little_of_something()

Ниже приведен допустимый пример опроса события с тайм-аутом.
start = time.ticks_us()
while pin.value() == 0:

if time.ticks_diff(time.ticks_us(), start) > 500:
поднять TimeoutError

допустимый пример планирования встроенных задач с использованием тикающих функций.
сейчас = time.ticks_ms()
schedule_time = task.scheduled_time()
if ticks_diff(scheduled_time, now) == 0:
print(«пора выполнять задачу!»)
task.run()

Проблема с функциями, связанными со временем
Функции тикания довольно точны. Функции тиканья полезны при расчете временных интервалов, установке тайм-аутов для событий и даже при планировании задач. Несмотря на то, что эти функции не блокируют, они не часто используются для обеспечения задержек или планирования задач. Основной причиной этого является зависимость модуля времени от ОС/RTOS или RTC. Во-вторых, эти методы могут быть прерваны другими более приоритетными событиями микроконтроллера.

С другой стороны, связанные с задержкой функции модуля time, такие как time.sleep(), time.sleep_ms() и time.sleep_us(), имеют две заслуживающие внимания проблемы. Во-первых, эти методы носят блокирующий характер и останавливают скрипт при вызове. Во-вторых, эти методы не обеспечивают точной задержки. Например, задержка в несколько секунд от метода time.sleep() может привести к ошибке в несколько миллисекунд. Эти ошибки могут достигать 1 или 2 процентов.

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

Что такое таймер?
Каждый микроконтроллер имеет некоторые встроенные аппаратные функции. Таймер/счетчик является одним из важных встроенных периферийных устройств, присутствующих почти в каждом микроконтроллере. Таймер/счетчик используется для измерения временных событий или работы в качестве счетчика. Таймер связан с системными часами микроконтроллера, что позволяет ему отслеживать время с высокой точностью. В микроконтроллере может быть несколько таймеров. Каждый таймер настраивается, отслеживается и управляется набором внутренних регистров.

Что такое прерывание по таймеру?
Одной из важных функций таймеров является синхронизация событий. Это делается с помощью прерываний по таймеру. Событие — это не что иное, как выполнение определенного блока кода в микроконтроллере. Этот кодовый блок включен в функцию
подпрограммы обслуживания прерываний (ISR) . ISR выполняется, когда возникает прерывание.

Обычно микроконтроллер выполняет инструкции последовательно. Когда возникает прерывание, микроконтроллер пропускает текущее выполнение кода и сначала выполняет ISR. После завершения ISR возобновляется нормальное выполнение кода.

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

Класс таймера MicroPython
MicroPython предоставляет класс таймера для обработки таймеров и прерываний от поддерживаемых портов. Класс таймера является частью машинного модуля. Он импортируется в сценарий MicroPython с помощью следующего оператора.
из таймера импорта машины

В случае, если порт WiPy, необходимо использовать следующий оператор.
из машинного импорта TimerWiPy

Важно отметить, что если при выполнении процедуры обслуживания прерывания возникают ошибки, MicroPython не создает отчет об ошибке, если для него не создан специальный буфер. Следовательно, буфер должен быть создан для отладки, когда прерывания таймера или другие прерывания используются в скрипте MicroPython. Буфер можно создать с помощью следующих операторов.
import micropython
micropython. alloc_emergency_exception_buf(100)

Важно отметить, что здесь буфер хранит только последнюю трассировку стека исключений. Если во время блокировки кучи генерируется второе исключение, трассировка стека второго исключения заменяет исходную трассировку.

После импорта класса таймера необходимо создать объект таймера. Это делается путем вызова метода конструктора. Метод конструктора имеет следующий прототип.
class machine.Timer(id, /, …)

Метод конструктора принимает идентификатор таймера в качестве аргумента. Это может быть положительное число 0, 1, 2 и т. д. для аппаратного таймера или -1 для виртуального таймера, если порт поддерживает это. Другие параметры конфигурации также могут быть установлены в вызове метода конструктора. В противном случае объект таймера можно явно настроить с помощью метода timer.init() . Метод timer.init() имеет следующий прототип.
Timer.init(*, mode=Timer.PERIODIC, period=- 1, callback=None)

Можно установить режим timer. ONE_SHOT или Timer.PERIODIC. Если установлено значение timer.ONE_SHOT, таймер запускается только один раз, пока не пройдет указанный период в миллисекундах. Если задано значение timer.PERIODIC, таймер запускается периодически с интервалом в миллисекундах, который передается в качестве аргумента период . Аргумент период — это период времени в миллисекундах, используемый в качестве тайм-аута для однократного или периодического выполнения функции обратного вызова, в зависимости от установленного режима. 9Обратный вызов 0275 — это вызываемый объект, выполняемый по истечении периода времени. Процедура обслуживания прерывания вызывается для выполнения желаемых встроенных задач при инициировании прерывания таймера. Вызываемый объект может быть функцией или даже методом, принадлежащим объекту класса.

Класс таймера позволяет остановить таймер и отключить периферийное устройство таймера. Это делается вызовом метода timer.deinit(). Вызов этого метода немедленно останавливает таймер, если он запущен, деинициализирует объект таймера и отключает периферийное устройство таймера. Он имеет следующий прототип.
Timer.deinit()

Если отключенный таймер необходимо снова включить, в пользовательской программе необходимо снова создать объект таймера с тем же идентификатором.

Обработчики прерываний MicroPython
Функция обратного вызова, указанная в качестве аргумента при инициализации или создании объекта таймера, представляет собой процедуру обслуживания прерывания, которая запускается, когда возникает прерывание таймера. Интересно, что MicroPython не поддерживает программирование таймеров на уровне регистров. Вместо этого он использует прерывания таймера, чтобы обеспечить время ожидания в миллисекундах. Методы доступны через машину. Таймеры обычно применимы ко всем поддерживаемым портам.

Функция обратного вызова или процедура обработки прерывания для объектов таймера требуют определенных мер предосторожности при программировании, чтобы избежать сбоев во время выполнения. Мы уже обсуждали одно из таких предостережений: определение буферного объекта для хранения последней ошибки исключения. Обсудим еще несколько рекомендаций по написанию обработчиков прерываний на MicroPython.

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

Большинство платформ микроконтроллеров не позволяют программам обработки прерываний возвращать значения. Однако MicroPython позволяет прерывать процедуры обслуживания и возвращать одно или несколько значений. ISR может вернуть одно значение, обновив глобальную переменную. Если необходимо вернуть несколько значений, подпрограмма должна обновить предварительно выделенный массив байтов. Предварительно выделенный объект массива необходимо обновить, если подпрограмма возвращает несколько целочисленных значений. Однако такое совместное использование переменных и объектов между ISR и основным циклом может вызвать состояние гонки, когда и основной цикл программы, и гонка ISR изменяют значение переменной. Поэтому обновление значения этих переменных в основном цикле программы требует особой осторожности. Перед обновлением общей переменной/массива байтов/массива в основном цикле программы прерывания должны быть отключены вызовом Метод pyb.disable_irq() . После обновления общей переменной/байтового массива/массива в основной программе прерывания можно повторно включить, вызвав метод pyb.enable_irq() .

Таймеры в ESP8266
В ESP8266 есть два таймера — timer0 и timer1. Timer0 используется для сетевых функций. Timer1 доступен для использования в ESP8266, но MicroPython предоставляет доступ к таймерам ESP8266. Вместо этого ESP8266 предоставляет API для виртуального таймера. Этот виртуальный таймер на основе RTOS имеет идентификатор -1. Ниже приведен допустимый пример прерывания таймера в ESP8266.
из машинного импорта Таймер
tim = Таймер(-1)
tim.init(период=500, режим=Timer.ONE_SHOT, обратный вызов=лямбда t:print(1))
tim.init( период=200, режим=Timer.PERIODIC, callback=lambda t:print(2))

Таймеры в ESP32
ESP32 имеет четыре аппаратных таймера с идентификаторами от 0 до 3. Все таймеры доступны для пользователя. Ниже приведен правильный пример прерываний таймера в ESP32.
из машинного импорта Таймер
tim0 = Таймер(0)
tim0.init(период=2000, режим=Timer.ONE_SHOT, обратный вызов=лямбда t:print(0))
tim1 = Таймер(1)
tim1.init(период=1000, режим=Таймер .PERIODIC, callback=lambda t:print(1))

Использование таймера ESP8266 для тикера светодиодов
Теперь давайте воспользуемся таймерами MicroPython для переключения состояния светодиода.

Необходимые компоненты

  1. ESP8266/ESP32 x1
  2. 5 мм светодиод x1
  3. Резистор 330 Ом x1
  4. Макет
  5. Соединительные провода/перемычки

Соединения цепи
Подключите анод светодиода к GPIO14 ESP8266 или ESP32. Подключите резистор 330 Ом к катоду светодиода и заземлите другой конец резистора.

Переключение светодиода на ESP8266 с помощью прерывания таймера MicroPython

Скрипт MicroPython

Как это работает низкий уровень сигнала с выв. Сценарий MicroPython реализует прерывание таймера каждую 1 секунду, когда состояние светодиода переключается, а количество миганий обновляется на консоли.

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

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

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