/* Описание модуля ltimers.c Этот модуль используется для создания неограниченного количества программных таймеров для программы. Модуль использует аппаратный таймер, который генерирует прерывание каждую 1мс (можно использовать любой другой промежуток времени, просто 1 мс это очень удобно и хватает для многих программных пауз, задержек, таймеров и тд. в программе). В прерывании вызывается ф-я ProcessLTimers(), которая инкрементирует значения всех таймеров. Таймеры создаются в файле ltimers.h. Модуль универсален, прост и может использоваться на любой платформе, компиляторе, любом МК. Для подключения модуля настройте аппаратный таймер на прерывание в 1мс (или любой другой нужный промежуток времени) и добавьте в обработчик прерывания этого таймера ф-ю ProcessLTimers();. Затем добавьте #include "ltimers.h" в тот файл программы, где будут использоваться ф-ии модуля. Собственно, в всего нужны две функции для работы с таймерами: StartLTimer ( LTIMER_LED_BLINK ); // запустить таймер GetLTimer ( LTIMER_LED_BLINK ); // получить текущее значение таймера Пример использования: ... // Предварительно ltimers.h создаем перечисление, в котором создаем имена для // программных таймеров, а также в конце перечисления всегда MAX_LTIMERS #include "ltimers.h" ... int main () { ... // Настройка аппаратного таймера на прерывание раз в 1 мс InitLTimersHardWare(); // Стартовая инициализация (просто обнуление) всех программных таймеров InitLTimers (); // Запускаем таймер StartLTimer ( LTIMER_LED_BLINK ); // Основной цикл программы while (1) { // Проверяем значение таймера if ( GetLTimer ( LTIMER_LED_BLINK ) >= 500 ) { LED_ON; } } } ***Примечание 1. Необходимо учитывать разрядность МК и атомарность при проверке значений таймера. То есть, если произойдет прерывание в момент проверки полубайтов на 8-ми разрядном МК, то, возможно, могут быть трудноуловимые глюки. 2. Обратите внимание, что в ф-ии ProcessLTimers() значения таймеров инкрементируются постоянно и не перестают изменяться. Ф-я StartLTimer только сбрасывает значение таймера в ноль, а потом программа уже ловит тот момент, когда это значение превысило или сравнялось с нужным. И когда мы провели сравнение, то таймер все равно продолжает маслать. Но это не важно. Пусть себе маслает. 3. Псевдоним для типа uint32_t можно заменить на необходимый в зависимости от среды разработки и компилятора. */ #include "ltimers.h" #include "ltimers_config.h" uint32_t LTimers [MAX_LTIMERS] = { 0 }; // ---------------------------------------------------------------------------- // Стартовая инициализация всех программных таймеров программиста. // Ф-я вызывается при старте МК и просто устанавливает все значения таймеров // в ноль. // ---------------------------------------------------------------------------- void InitLTimers (void) { LTimersConfig (); } // ---------------------------------------------------------------------------- // Ф-я получения значения программного счетчика // Используется программистом для проверки значения запущенного таймера // Ф-я принимает имя таймера из перечисления LTimerNum_t в файле ltimers.h // Ф-я возвращает значение таймера, которое увеличивается каждую 1мс // ---------------------------------------------------------------------------- uint32_t GetLTimer ( LTimersNames_t LTimer ) { return LTimers[ LTimer ]; } // ---------------------------------------------------------------------------- // Ф-я запуска программного таймера для использования программистом для // любых программных задержек разрешением 1мс // Ф-я принимает имя таймера из перечисления LTimerNum_t в файле ltimers.h // ---------------------------------------------------------------------------- void StartLTimer ( LTimersNames_t LTimer ) { LTimers[ LTimer ] = 0; } // ---------------------------------------------------------------------------- // Ф-я, инкрементирующая значения программных таймеров. Количество этих // программных таймеров нее ограничено и задается программистом в ltimers.h // в тайпдефе LTimerNum_t. Просто дописываем в перечислении перед MAX_LTIMERS // имя нового таймера. // Вызывается эта ф-я в обреботчике TIM6_IRQHandler каждую 1 мс. // 1 мс это удобный квант времени для разных программных задержек // ---------------------------------------------------------------------------- void ProcessLTimers (void) { for ( uint32_t i = 0; i < MAX_LTIMERS; i++ ) { LTimers[i]++; } }