/******************************* (C) LiteMesh ********************************** * @module systick * @file systick.c * @version 1.0.0 * @date 29.05.2015 * $brief Functions to work with System Timer. * Module is based on code teplofizik, 2013 ******************************************************************************* * @history Version Author Comment * 29.05.2015 1.0.0 Telenkov D.A. First release. ******************************************************************************* */ #include "stm32f4xx.h" #include "systick.h" #include #include extern void Time_Update(void); typedef struct { TTimerHandler Handler; uint16_t Countdown; uint16_t Reload; bool Run; // Запущено bool Fired; // Сработало } THandlers; volatile uint32_t TimingDelay; volatile uint8_t StopDelayFlag = 0; static THandlers Handlers[TIMER_HANDLERS]; static uint32_t TimerFrequency; static int TimerCount; /** * @brief Обработчик прерывания системного таймера * @retval нет */ void SysTick_Handler(void) { int i; Time_Update(); TimingDelay_Decrement(); for(i = 0; i < TIMER_HANDLERS; i++) { if(Handlers[i].Run) { if(--Handlers[i].Countdown == 0) { Handlers[i].Countdown = Handlers[i].Reload; /* Запишем, что сработало */ Handlers[i].Fired = true; } } } } /** * @brief Запуск таймера с заданной частотой * @retval нет */ void timer_Init(uint32_t Frequency) { if(!Frequency) return; /* Сбросим параметры */ TimerCount = 0; TimerFrequency = Frequency; memset(&Handlers[0], 0, sizeof(Handlers)); /* Настройка частоты */ SysTick_Config(clock_GetSYS() / Frequency); } /** * @brief Добавить функцию в список вызова. * Handler будет вызываться с заданной частотой * @retval нет */ void timer_AddFunction(uint16_t Frequency, TTimerHandler Handler) { int i; for(i = 0; i < TIMER_HANDLERS; i++) { /* Найдем пустой слот */ if(!Handlers[i].Handler) { /* Обработчик, частота опроса */ Handlers[i].Run = true; Handlers[i].Fired = false; Handlers[i].Handler = Handler; Handlers[i].Reload = Frequency; Handlers[i].Countdown = Handlers[i].Reload; TimerCount++; return; } } } /** * @brief Изменить частоту таймера * @retval нет */ void timer_ChangeFrequency(TTimerHandler Handler, uint16_t Frequency) { int i; for(i = 0; i < TIMER_HANDLERS; i++) { if(Handlers[i].Handler == Handler) { Handlers[i].Reload = Frequency; Handlers[i].Countdown = Handlers[i].Reload; break; } } } /** * @brief Возобночить работу задачи * @retval нет */ void timer_Resume(TTimerHandler Handler) { int i; for(i = 0; i < TIMER_HANDLERS; i++) { if(Handlers[i].Handler == Handler) { Handlers[i].Run = true; break; } } } /** * @brief Перезапуск задачи * @retval нет */ void timer_Restart(TTimerHandler Handler) { int i; for(i = 0; i < TIMER_HANDLERS; i++) { if(Handlers[i].Handler == Handler) { Handlers[i].Run = true; Handlers[i].Countdown = Handlers[i].Reload; break; } } } /** * @brief Перезапуск задачи. Задача будет вызвана сразу. * @retval нет */ void timer_RestartAtOnce(TTimerHandler Handler) { int i; for(i = 0; i < TIMER_HANDLERS; i++) { if(Handlers[i].Handler == Handler) { Handlers[i].Run = true; Handlers[i].Countdown = 1; break; } } } /** * @brief Остановить задачу * @retval нет */ void timer_Stop(TTimerHandler Handler) { int i; for(i = 0; i < TIMER_HANDLERS; i++) { if(Handlers[i].Handler == Handler) { Handlers[i].Run = false; Handlers[i].Fired = false; break; } } } /** * @brief Получить значение счетчика * @retval значение счетчика или 0 если не найдено */ uint16_t timer_GetCountdown(TTimerHandler Handler) { int i; for(i = 0; i < TIMER_HANDLERS; i++) { if(Handlers[i].Handler == Handler) { return Handlers[i].Countdown; } } return 0; } /** * @brief Функция перебора и вызова актуальных задач. * Должна вызываться в главном цикле * @retval нет */ void timer_Main(void) { int i; for(i = 0; i < TIMER_HANDLERS; i++) { /* Если сработало - вызовем */ if(Handlers[i].Fired) { Handlers[i].Fired = false; Handlers[i].Handler(); } } } /** * @brief * @retval Частота тактирования ядра */ uint32_t clock_GetSYS(void) { return SystemCoreClock; } /** * @brief Задержка в миллисекундах * @retval нет */ void Delay_ms(uint32_t nTime) { TimingDelay = nTime; while(TimingDelay); } /** * @brief Вспомогательная функция для реализации Delay_ms * @retval нет */ void TimingDelay_Decrement(void) { if (TimingDelay) TimingDelay--; } //******************************** (C) POTEK ***********************************