/*============================================================================== * Инициализация таймеров с использованием бибилотеки PLIB035 *------------------------------------------------------------------------------ * ЦНИИ СЭТ, Разваляев Алексей *============================================================================== * ЦНИИ СЭТ *============================================================================== */ //-- Includes ------------------------------------------------------------------ #include "periph_config.h" TMR_HandleTypeDef htmr0; TMR_HandleTypeDef htmr1; TMR_HandleTypeDef htmr2; TMR_HandleTypeDef htmr3; //-- Defines ------------------------------------------------------------------- //-- Peripheral init functions ------------------------------------------------- void tmr_init_first(void) { #if (USE_TMR0==1) RCU_APBClkCmd(RCU_APBClk_TMR0, ENABLE); RCU_APBRstCmd(RCU_APBRst_TMR0, ENABLE); htmr0.TMR = TMR0; tmr_init(&htmr0, &tmr0_config); if(htmr0.Config->IT == ENABLE) { NVIC_EnableIRQ(TMR0_IRQn); } #endif #if (USE_TMR1==1) RCU_APBClkCmd(RCU_APBClk_TMR1, ENABLE); RCU_APBRstCmd(RCU_APBRst_TMR1, ENABLE); htmr1.TMR = TMR1; tmr_init(&htmr1, &tmr1_config); if(htmr1.Config->IT == ENABLE) { NVIC_EnableIRQ(TMR1_IRQn); } #endif #if (USE_TMR2==1) RCU_APBClkCmd(RCU_APBClk_TMR2, ENABLE); RCU_APBRstCmd(RCU_APBRst_TMR2, ENABLE); htmr2.TMR = TMR2; tmr_init(&htmr2, &tmr2_config); if(htmr2.Config->IT == ENABLE) { NVIC_EnableIRQ(TMR2_IRQn); } #endif #if (USE_TMR3==1) RCU_APBClkCmd(RCU_APBClk_TMR3, ENABLE); RCU_APBRstCmd(RCU_APBRst_TMR3, ENABLE); htmr3.TMR = TMR3; tmr_init(&htmr3, &tmr3_config); if(htmr3.Config->IT == ENABLE) { NVIC_EnableIRQ(TMR3_IRQn); } #endif } /** * @brief Инициализация таймера * @param htmr указатель на хендл таймера * @param NewConfig указатель на новую конфигурацию UART, иначе используется та, что в структуре * @retval OperationStatus OK - если всё хорошо, ERROR - если ошибка */ OperationStatus tmr_init(TMR_HandleTypeDef *htmr, TMR_Init_TypeDef *NewConfig) { if(htmr->TMR == NULL) { return ERROR; } if(NewConfig != NULL) { htmr->Config = NewConfig; } if(htmr->Config == NULL) { return ERROR; } TMR_Init(htmr->TMR, htmr->Config); return OK; } /** * @brief Установка коллбека таймера * @param htmr указатель на хендл таймера * @param cb_type Тип коллбека * @param Callback Функция коллбека * @retval void */ OperationStatus tmr_set_callback(TMR_HandleTypeDef* htmr, int cb_type, void (*Callback)(void)) { if((htmr->TMR == NULL) || (htmr->Config == NULL)) { return ERROR; } htmr->Config->Callback = Callback; return OK; } /** * @brief Запуск таймера * @param htmr указатель на хендл таймера * @retval OperationStatus OK - если всё хорошо, ERROR - если ошибка */ OperationStatus tmr_start(TMR_HandleTypeDef *htmr) { if(htmr->TMR == NULL) { return ERROR; } TMR_Cmd(htmr->TMR, ENABLE); return OK; } /** * @brief Остановка таймера * @param htmr указатель на хендл таймера * @retval OperationStatus OK - если всё хорошо, ERROR - если ошибка */ OperationStatus tmr_stop(TMR_HandleTypeDef *htmr) { if(htmr->TMR == NULL) { return ERROR; } TMR_Cmd(htmr->TMR, DISABLE); return OK; } /** * @brief Задержка в тиках таймера (блокирующая). * @param htmr Указатель на хендл таймера. * @param delay Задержка в тиках таймера. * @return OperationStatus. * @details Формирует задержку с блокировкой программы. */ OperationStatus tmr_delay(TMR_HandleTypeDef *htmr, uint32_t delay) { if(!htmr || !htmr->TMR) return ERROR; uint32_t presc = htmr->Config->Prescaler+1; uint64_t delay_load = delay*presc; if(delay_load > 0xFFFFFFFF) { delay_load = 0xFFFFFFFF; } if(delay_load >= htmr->TMR->LOAD) { return ERROR; } uint32_t starttick = htmr->TMR->VALUE; while(1) { if((starttick - htmr->TMR->VALUE) >= delay_load) { return OK; } } } /** * @brief Начать отсчет неблокирующей задержки. * @param htmr Указатель на хендл таймера. * @param var Указатель на переменную куда положить значение тиков. * @return OperationStatus. * @details Запоминает счетчик для начала отсчета неблокирующей задержки. * @ref tmr_delay_done для проверки статуса задержки */ OperationStatus tmr_delay_start(TMR_HandleTypeDef *htmr, uint32_t *var) { if(!htmr || !htmr->TMR) return ERROR; *var = htmr->TMR->VALUE; return OK; } /** * @brief Задержка в тиках таймера (неблокирующая). * @param htmr Указатель на хендл таймера. * @param delay Задержка в тиках таймера. * @param var Указатель на переменную где хранится тики в момент начала задержки. * @return 1 - задержка прошла. 0 - задержка в процессе. * @details Формирует задержку с блокировкой программы. * Перед ожиданием задержки надо инициализировать задержку @ref tmr_delay_start */ int tmr_delay_done(TMR_HandleTypeDef *htmr, uint32_t delay, uint32_t *var) { if(!htmr || !htmr->TMR) return 0; uint32_t presc = htmr->Config->Prescaler+1; uint64_t delay_load = delay*presc; if(delay_load > 0xFFFFFFFF) { delay_load = 0xFFFFFFFF; } if(delay_load >= htmr->TMR->LOAD) { return 0; } if((*var - htmr->TMR->VALUE) >= delay_load) { return 1; // Задержка прошла } else { return 0; } } /** * @brief Обработчик прерывания таймера * @param htmr указатель на хендл таймера * @retval void */ void tmr_handler(TMR_HandleTypeDef* htmr) { if((htmr->TMR == NULL) || (htmr->Config == NULL)) { return; } /* Проверка флага прерывания таймера */ if (TMR_ITStatus(htmr->TMR) == SET) { /* Если есть коллбек вызываем его */ if(htmr->Config->Callback) htmr->Config->Callback(); /* Очистка флага прерывания */ TMR_ITStatusClear(htmr->TMR); } } /* Расширение библиотеки plib */ /** * @brief Инициализирует модуль TMRx согласно параметрам структуры InitStruct. * @param TMRx Выбор таймера, где x=A|B * @param InitStruct Указатель на структуру типа @ref TMR_Init_TypeDef, * которая содержит конфигурационную информацию * @retval void */ void TMR_Init(TMR_TypeDef* TMRx, TMR_Init_TypeDef* InitStruct) { uint32_t tim_clk = InitStruct->ClkFreq*__MHZ; uint32_t presc = InitStruct->Prescaler+1; if(InitStruct->PeriodUs) { TMR_PeriodConfig(TMRx, tim_clk, InitStruct->PeriodUs); } else if(InitStruct->FreqHz) { TMR_FreqConfig(TMRx, tim_clk, InitStruct->FreqHz); } else { uint64_t load = (uint64_t)InitStruct->Load*presc; if(load > 0xFFFFFFFF) load = 0xFFFFFFFF; TMR_SetLoad(TMRx, load); } TMR_ITCmd(TMRx, InitStruct->IT); TMR_DMAReqCmd(TMRx, InitStruct->DMAReq); TMR_ADCSOCCmd(TMRx, InitStruct->ADCSOC); TMR_ExtInputConfig(TMRx, InitStruct->ExtInput); }