FreeRTOS xTimerCreate |
![]() |
Добавил(а) microsin |
Создает новый программный таймер и возвратит дескриптор (handle), по которому к этому таймеру можно будет обращаться. TimerHandle_t xTimerCreate (const char * const pcTimerName, const TickType_t xTimerPeriod, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction); Чтобы эта функция была доступна: 1. Обе опции configUSE_TIMERS и configSUPPORT_DYNAMIC_ALLOCATION должны быть установлены в 1 файле FreeRTOSConfig.h (configSUPPORT_DYNAMIC_ALLOCATION можно также оставить без определения, в таком случае его значение по умолчанию будет 1). 2. К сборке должен быть подключен модуль FreeRTOS/Source/timers.c. xTimerCreate и xTimerCreateStatic. Каждый программный таймер требует небольшое количество RAM, в котором хранится состояние таймера. Если таймер создается вызовом xTimerCreate(), то эта RAM автоматически выделяется из кучи FreeRTOS. Если программый таймер создан функцией xTimerCreateStatic(), то RAM для этой цели предоставляется программистом в дополнительном последнем параметре функции. RAM в таком случае выделяется статически, во время компиляции. Для дополнительной информации по различиям выделения памяти динамически (из кучи) и статически (в момент компиляции) см. документацию [2]. Таймеры после создания находятся в неактивном состоянии. Функции xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() и xTimerChangePeriodFromISR() могут использоваться для перевода таймера в активное состояние. Параметры xTimerCreate: pcTimerName Удобочитаемый текст, который в целях отладки указывается для описания таймера. Ни для каких других целей этот параметр не нужен. Ядро RTOS обращается к таймеру только по его дескриптору, и никогда по имени. xTimerPeriod Период таймера в тиках RTOS. Может использоваться макрос pdMS_TO_TICKS(), чтобы преобразовать длительность в миллисекунды в количество тиков. Например, если таймер должен сработать через 100 тиков, то просто установите xTimerPeriod в начение 100. Или если таймер должен сработать через 500 мс, то установите xTimerPeriod в значение pdMS_TO_TICKS(500). Макрос pdMS_TO_TICKS() может использоваться только если configTICK_RATE_HZ меньше или равен 1000. Период таймера в тиках должен быть больше 0. uxAutoReload Если этот параметр установлен в pdTRUE, то таймер будет сам срабатывать периодически с интервалом xTimerPeriod. Если uxAutoReload установлен в pdFALSE, то таймер после запуска сработает однократно, и останется в неактивном состоянии. pvTimerID Идентификатор, который назначается созданному таймеру. Обычно этот идентификатор может использоваться в общей callback-функции таймера, чтобы идентифицировать, какой из таймеров сработал, или этот идентификатор может использоваться в функциях vTimerSetTimerID() и pvTimerGetTimerID() для сохранения значения между вызовами callback-функции таймера. pxCallbackFunction Это функция, которая будет вызвана при срабатывании таймера. У callback-функций должен быть прототип, определенный типом TimerCallbackFunction_t: void vCallbackFunction (TimerHandle_t xTimer); Возвращаемое значение: если таймер был успешно создан, то будет возвращен дескриптор (handle) для нового созданного таймера. Если таймер не может быть создан из-за недостатка памяти в куче FreeRTOS, чтобы выделить структуры для таймера, то будет возвращено значение NULL. Пример использования: #define NUM_TIMERS 5
/* Массив для хранения дескрипторов созданных таймеров. */
TimerHandle_t xTimers [NUM_TIMERS];
/* Определение callback-функции, которая будет использоваться несколькими
экземплярами таймеров. Эта функция только подсчитывает количество
срабатываний таймера, и остановит таймер, как только он сработает
10 раз. Счетчик срабатываний сохраняется как ID таймера. */
void vTimerCallback (TimerHandle_t xTimer) { const uint32_t ulMaxExpiryCountBeforeStopping = 10; uint32_t ulCount; /* Опциональная проверка, что параметр pxTimer не NULL. */
configASSERT(xTimer);
/* Количество раз, которое сработал таймер, сохраняется в ID таймера.
Получим этот счетчик. */ ulCount = (uint32_t)pvTimerGetTimerID(xTimer); /* Инкремент счетчика, затем его проверка, достиг ли он значения
ulMaxExpiryCountBeforeStopping. */ ulCount++; /* Если таймер сработал 10 раз, остановим его. */ if(ulCount >= ulMaxExpiryCountBeforeStopping) { /* Не используйте время блокировки, если вызываете API-функцию таймера из callback-функции таймера, так как это может
вызвать самоблокировку (deadlock)! */ xTimerStop( xTimer, 0 ); } else { /* Сохранение увеличенного счетчика обратно в поле ID таймера, чтобы его можно было прочитать при следующем срабатывании
таймера. */ vTimerSetTimerID( xTimer, ( void * ) ulCount ); } } void main (void) { long x; /* При старте создается несколько таймеров. Запуск таймеров
перед запуском планировщика RTOS будет означать, что таймеры
начнут работать сразу после запуска планировщика. */ for(x = 0; x < NUM_TIMERS; x++) { xTimers[x] = xTimerCreate( "Timer", // это просто произвольный текст, который // ядро RTOS не использует (100 * x) + 100, // Время периода таймера в тиках, // которое должно быть > 0. pdTRUE, // Таймеры перезапустят себя автоматически, // когда истечет период. (void *)0, // ID таймера, используемый в качестве // счетчика срабатываний, инициализируется // нулем. vTimerCallback // Функция, запускаемая при // срабатывании таймера. ); if(xTimers[x] == NULL) { /* Таймер не был создан. */ } else { /* Запуск таймера. Время блокировки не указано, и даже если бы оно было, то оно будет проигнорировано, потому что планировщик RTOS
еще не запущен. */ if(xTimerStart(xTimers[x], 0) != pdPASS) { /* Таймер не был установлен в состояние Active. */ } } } /* ...
Создайте здесь задачи приложения (tasks).
... */
/* Запуск планировщика RTOS запустит таймеры, которые уже были установлены
в активное состояние. */
vTaskStartScheduler();
/* До этого места выполнение кода никогда не дойдет. */ for( ;; ); } [Ссылки] 1. xTimerCreate site:freertos.org. |