STM32_ExtendedLibs/STM32_General/Src/general_tim.c
Razvalyaev 141ea6bac9 Переструктурирование:
- MyLibs - максимально платформонезависимые библиотеки (кроме разве что RTT)
- RTT
- STM32_General - библиотеки для периферии stm32
2025-10-21 05:03:54 +03:00

723 lines
20 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
**************************************************************************
* @file general_tim.c
* @brief Модуль для инициализации таймеров и работы с ними.
**************************************************************************
Реализация функций для работы с TIM:
- Инициализация таймера и его каналов
- Формирование задержек через таймеры
- Считывание энкодера
*************************************************************************/
#include "general_tim.h"
//-------------------------------------------------------------------
//-------------------------TIM INIT FUNCTIONS------------------------
/**
* @brief Инициализация таймера.
* @param stim Указатель на структуру с настройками таймера.
* @return HAL status.
* @details
* Инициализирует таймер исходя из настроек верхнего уровня:
* - Длительность одного тика @ref TIM_MHzTickBaseTypeDef
* - Частота таймера (в Гц, float)
* - Частота тактирования таймера от шины (в Гц, float)
*
* При невозможности выставления частоты при заданой длительности тика
* длительность тика увеличивается до тех пор, пока частота не будет достигнута.
*
* При выставлении дефайна @ref UPDATE_TIM_PARAMS_AFTER_INITIALIZATION
* новая длительность тика записывается в структуру.
*
* Также остается возможность низкоуровневой настройки по структурам @ref TIM_SettingsTypeDef.
* Для этого надо высокоуровневые настройки приравнять к нулю
*/
HAL_StatusTypeDef TIM_Base_Init(TIM_SettingsTypeDef *stim)
{ // function takes structure for init
// check that htim is defined
if(check_null_ptr_2(stim, stim->htim.Instance))
return HAL_ERROR;
if(stim->sTickBaseUS) // if tickbase isnt disable
{
if(stim->sTimAHBFreqMHz == NULL)
return HAL_ERROR;
stim->htim.Init.Prescaler = (stim->sTimAHBFreqMHz*stim->sTickBaseUS) - 1;
if ((stim->sTimFreqHz != NULL))
stim->htim.Init.Period = ((1000000/stim->sTickBaseUS) / stim->sTimFreqHz) - 1;
else if (stim->htim.Init.Period == NULL)
stim->htim.Init.Period = 0xFFFF;
if(stim->sTickBasePrescaler)
{
stim->htim.Init.Prescaler = (stim->htim.Init.Prescaler + 1)/stim->sTickBasePrescaler - 1;
stim->htim.Init.Period = (stim->htim.Init.Period + 1)*stim->sTickBasePrescaler - 1;
}
else
stim->sTickBasePrescaler = 1;
}
// fix overflow of presc and period if need
for(int i = 0; (stim->htim.Init.Prescaler > 0xFFFF) || (stim->htim.Init.Period > 0xFFFF); i++)
{
if (i>10) // if it isnt fixed after 10 itteration - return HAL_ERRPOR
{
return HAL_ERROR;
}
// if timbase is too big (prescaller too big for choosen base from MHZ)
if(stim->htim.Init.Prescaler > 0xFFFF)
{
// переносим часть пресскалера в период
stim->htim.Init.Prescaler = ((stim->htim.Init.Prescaler + 1)/2) - 1;
stim->htim.Init.Period = ((stim->htim.Init.Period + 1)*2) - 1;
// обновляем TickBase, если есть куда обновлять
if(stim->sTickBaseUS > 1)
stim->sTickBaseUS /= 2;
// обновляем sTickBasePrescaler, если sTickBaseUS - уже в минимуме
else if (stim->sTickBaseUS == 1)
stim->sTickBasePrescaler *= 2;
else // if TickBase = 0 - return error
return HAL_ERROR;
}
// if freq is too low (period too big for choosen base)
if(stim->htim.Init.Period > 0xFFFF)
{
// переносим часть периода в прескалер
stim->htim.Init.Period = ((stim->htim.Init.Period + 1)/2) - 1;
stim->htim.Init.Prescaler = ((stim->htim.Init.Prescaler + 1)*2) - 1;
// обновляем TickBase
stim->sTickBaseUS *= 2;
}
}
//-------------TIM BASE INIT----------------
// tim base init
TIM_Base_MspInit(&stim->htim, stim->sTimMode);
if (HAL_TIM_Base_Init(&stim->htim) != HAL_OK)
{
MyLibs_Error_Handler();
return HAL_ERROR;
}
//-------------CLOCK SRC INIT---------------
// fill sClockSourceConfig if its NULL
if (stim->sClockSourceConfig.ClockSource == NULL)
stim->sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
// clock source init
if (HAL_TIM_ConfigClockSource(&stim->htim, &stim->sClockSourceConfig) != HAL_OK)
{
MyLibs_Error_Handler();
return HAL_ERROR;
}
//--------------SLAVE INIT------------------
// if slave mode enables - config it
if (stim->sSlaveConfig.SlaveMode)
{
// slave mode init
if (HAL_TIM_SlaveConfigSynchro(&stim->htim, &stim->sSlaveConfig) != HAL_OK)
{
MyLibs_Error_Handler();
return HAL_ERROR;
}
}
//--------------MASTER INIT-----------------
// master mode init
if (HAL_TIMEx_MasterConfigSynchronization(&stim->htim, &stim->sMasterConfig) != HAL_OK)
{
MyLibs_Error_Handler();
return HAL_ERROR;
}
//--------------BDTR INIT-----------------
if (HAL_TIMEx_ConfigBreakDeadTime(&stim->htim, &stim->sBreakDeadTimeConfig) != HAL_OK)
{
MyLibs_Error_Handler();
return HAL_ERROR;
}
//----------------IT CLEAR-------------------
__HAL_TIM_CLEAR_IT(&stim->htim, TIM_IT_UPDATE);
// обновляем TickBase
#ifdef UPDATE_TIM_PARAMS_AFTER_INITIALIZATION
stim->sTickBaseUS = (stim->htim.Instance->PSC+1)*stim->sTickBasePrescaler/(stim->sTimAHBFreqMHz);
if(stim->sTickBaseUS == 0) // if prescaler is too high
{ // recalc what is prescaler irl
stim->sTickBaseUS = 1;
stim->sTickBasePrescaler = stim->sTimAHBFreqMHz/(stim->htim.Instance->PSC+1);
}
#endif
stim->htim.Instance->CNT = 0;
return HAL_OK;
}
/**
* @brief Инициализация режима энкодер у таймера.
* @param henc Указатель на хендл энкодера.
* @param htim Указатель на хендл таймера.
* @return HAL status.
* @note Предварительно надо инициализировать таймер @ref TIM_Base_Init.
*/
HAL_StatusTypeDef TIM_Encoder_Init(TIM_EncoderTypeDef *henc, TIM_HandleTypeDef *htim)
{
if(check_null_ptr_3(henc, htim, htim->Instance))
return HAL_ERROR;
if(check_null_ptr_3(henc->GPIOx, henc->GPIO_PIN_TI1, henc->GPIO_PIN_TI2))
return HAL_ERROR;
GPIO_InitTypeDef GPIO_InitStruct = {0};
HAL_StatusTypeDef RES = HAL_ERROR;
henc->htim = htim;
// setup channel for pwm
RES = HAL_TIM_Encoder_Init(henc->htim, &henc->sConfig);
if (RES != HAL_OK)
{
MyLibs_Error_Handler();
return RES;
}
// choose port for enable clock
RES = GPIO_Clock_Enable(henc->GPIOx);
if(RES != HAL_OK)
{
MyLibs_Error_Handler();
return RES;
}
GPIO_InitStruct.Pin = henc->GPIO_PIN_TI1|henc->GPIO_PIN_TI2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_TIM_Alternate_Mapping(henc->htim->Instance);
if(GPIO_InitStruct.Alternate)
HAL_GPIO_Init(henc->GPIOx, &GPIO_InitStruct);
if(henc->GPIO_PIN_SW)
{
/*Configure switch pin */
GPIO_InitStruct.Pin = henc->GPIO_PIN_SW;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(henc->GPIOx, &GPIO_InitStruct);
GPIO_Switch_Init(&henc->Sw, henc->GPIOx, henc->GPIO_PIN_SW, 0);
}
return HAL_OK;
}
/**
* @brief Инициализация выхода ШИМ таймера.
* @param htim Указатель на хендл таймера.
* @param sConfigOC Указатель на настрйоки канала таймера.
* @param TIM_CHANNEL Канал таймера для настройки.
* @param GPIOx Порт для вывода ШИМ.
* @param GPIO_PIN Пин для вывода ШИМ.
* @return HAL status.
* @note Предварительно надо инициализировать таймер @ref TIM_Base_Init.
*/
HAL_StatusTypeDef TIM_Output_PWM_Init(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef *sConfigOC, uint32_t TIM_CHANNEL, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN)
{
if(check_null_ptr_3(htim, htim->Instance, sConfigOC))
return HAL_ERROR;
if(check_null_ptr_2(GPIOx, GPIO_PIN))
return HAL_ERROR;
GPIO_InitTypeDef GPIO_InitStruct = {0};
HAL_StatusTypeDef RES = HAL_ERROR;
// setup channel for pwm
RES = HAL_TIM_PWM_ConfigChannel(htim, sConfigOC, TIM_CHANNEL);
if (RES != HAL_OK)
{
MyLibs_Error_Handler();
return RES;
}
// choose port for enable clock
RES = GPIO_Clock_Enable(GPIOx);
if(RES != HAL_OK)
{
MyLibs_Error_Handler();
return RES;
}
GPIO_InitStruct.Pin = GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
if(sConfigOC->OCPolarity == TIM_OCNPOLARITY_HIGH)
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
else
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_TIM_Alternate_Mapping(htim->Instance);
if(GPIO_InitStruct.Alternate)
HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
return HAL_OK;
}
/**
* @brief Инициализация OC компаратора таймера.
* @param htim Указатель на хендл таймера.
* @param TIM_CHANNEL Канал таймера для настройки.
* @return HAL status.
* @note Предварительно надо инициализировать таймер @ref TIM_Base_Init.
*/
HAL_StatusTypeDef TIM_OC_Comparator_Init(TIM_HandleTypeDef *htim, uint32_t TIM_CHANNEL)
{
if(check_null_ptr_2(htim, htim->Instance))
return HAL_ERROR;
TIM_OC_InitTypeDef sConfigOC = {0};
HAL_StatusTypeDef RES = HAL_ERROR;
sConfigOC.OCMode = TIM_OCMODE_ACTIVE;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
RES = HAL_TIM_OC_ConfigChannel(htim, &sConfigOC, TIM_CHANNEL);
if (RES != HAL_OK)
{
MyLibs_Error_Handler();
return RES;
}
return RES;
}
//-------------------------------------------------------------------
//-------------------------TIM USER FUNCTIONS------------------------
/**
* @brief Считать энкодер.
* @param henc Указатель на хендл энкодера.
* @return HAL status.
* @details Читает разницу энкодера, которую он накопил после
* предыдущего вызова этой функции.
*/
HAL_StatusTypeDef TIM_Encoder_Read(TIM_EncoderTypeDef *henc)
{
if(check_null_ptr_3(henc, henc->htim, henc->htim->Instance))
return HAL_ERROR;
uint16_t cnt_now = (uint16_t)henc->htim->Instance->CNT;
int16_t diff = (int16_t)(cnt_now - henc->Encoder_Shdw); // переполнение корректно обрабатывается
henc->Encoder_Diff = diff;
henc->Encoder_Shdw = cnt_now;
return HAL_OK;
}
/**
* @brief Считать кнопку энкодера.
* @param henc Указатель на хендл энкодера.
* @return 1 - если кнопка нажата,
* 0 - если отжата,
* -1 - если ошибка
*/
int TIM_Encoder_ReadSwitch(TIM_EncoderTypeDef *henc)
{
if(check_null_ptr_1(henc))
return -1;
return GPIO_Read_Switch(&henc->Sw);
}
/**
* @brief Задержка в тиках таймера (блокирующая).
* @param htim Указатель на хендл таймера.
* @param delay Задержка в тиках таймера.
* @return HAL status.
* @details Формирует задержку с блокировкой программы.
*/
HAL_StatusTypeDef TIM_Delay(TIM_HandleTypeDef *htim, uint16_t delay)
{
if(check_null_ptr_2(htim, htim->Instance))
return HAL_ERROR;
if(delay >= htim->Instance->ARR)
{
return HAL_ERROR;
}
htim->Instance->CNT = 0;
while(1)
{
if(htim->Instance->CNT > delay)
{
return HAL_OK;
}
}
}
/**
* @brief Начать отсчет неблокирующей задержки.
* @param htim Указатель на хендл таймера.
* @return HAL status.
* @details Сбрасывает счетчик для начала отсчета неблокирующей задержки.
* @ref TIM_Delay_NonBlocking для проверки статуса задержки
*/
HAL_StatusTypeDef TIM_Delay_Start(TIM_HandleTypeDef *htim)
{
if(check_null_ptr_2(htim, htim->Instance))
return HAL_ERROR;
htim->Instance->CNT = 0;
return HAL_OK;
}
/**
* @brief Задержка в тиках таймера (неблокирующая).
* @param htim Указатель на хендл таймера.
* @param delay Задержка в тиках таймера.
* @return HAL status.
* @details Формирует задержку с блокировкой программы.
* Перед ожиданием задержки надо запутстить таймер @ref TIM_Delay_Start
* @note Таймер не должен использоваться на время этой задержки
*/
HAL_StatusTypeDef TIM_Delay_NonBlocking(TIM_HandleTypeDef *htim, uint16_t delay)
{
if(check_null_ptr_2(htim, htim->Instance))
return HAL_ERROR;
if(delay >= htim->Instance->ARR)
{
return HAL_ERROR;
}
if(htim->Instance->CNT <= delay)
{
return HAL_BUSY;
}
else
{
return HAL_OK;
}
}
/**
* @brief Инициализация CLK и NVIC таймеров.
* @param htim Указатель на хендл таймера.
* @note Чтобы не генерировать функцию с иницилизацией неиспользуемых таймеров,
дефайнами @ref TIM_INIT в @ref general_tim.h определяются используемые таймеры.
*/
void TIM_Base_MspInit(TIM_HandleTypeDef* htim, TIM_ITModeTypeDef it_mode)
{
if(check_null_ptr_2(htim, htim->Instance))
return;
it_mode = it_mode&TIM_IT_CONF;
#ifdef USE_TIM1
if(htim->Instance==TIM1)
{
/* TIM2 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* TIM2 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
}
}
#endif
#ifdef USE_TIM2
if(htim->Instance==TIM2)
{
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
}
}
#endif
#ifdef USE_TIM3
if(htim->Instance==TIM3)
{
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* TIM3 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
}
}
#endif
#ifdef USE_TIM4
if(htim->Instance==TIM4)
{
/* TIM4 clock enable */
__HAL_RCC_TIM4_CLK_ENABLE();
/* TIM4 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM4_IRQn);
}
}
#endif
#ifdef USE_TIM5
if(htim->Instance==TIM5)
{
/* TIM5 clock enable */
__HAL_RCC_TIM5_CLK_ENABLE();
/* TIM5 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM5_IRQn);
}
}
#endif
#ifdef USE_TIM6
if(htim->Instance==TIM6)
{
/* TIM6 clock enable */
__HAL_RCC_TIM6_CLK_ENABLE();
/* TIM6 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
}
}
#endif
#ifdef USE_TIM7
if(htim->Instance==TIM7)
{
/* TIM7 clock enable */
__HAL_RCC_TIM7_CLK_ENABLE();
/* TIM7 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM7_IRQn);
}
}
#endif
#ifdef USE_TIM8
if(htim->Instance==TIM8)
{
/* TIM8 clock enable */
__HAL_RCC_TIM8_CLK_ENABLE();
/* TIM8 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
}
}
#endif
#ifdef USE_TIM9
if(htim->Instance==TIM9)
{
/* TIM9 clock enable */
__HAL_RCC_TIM9_CLK_ENABLE();
/* TIM9 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM1_BRK_TIM9_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
}
}
#endif
#ifdef USE_TIM10
if(htim->Instance==TIM10)
{
/* TIM10 clock enable */
__HAL_RCC_TIM10_CLK_ENABLE();
/* TIM10 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
}
}
#endif
#ifdef USE_TIM11
if(htim->Instance==TIM11)
{
/* TIM11 clock enable */
__HAL_RCC_TIM11_CLK_ENABLE();
/* TIM11 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM1_TRG_COM_TIM11_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_TRG_COM_TIM11_IRQn);
}
}
#endif
#ifdef USE_TIM12
if(htim->Instance==TIM12)
{
/* TIM12 clock enable */
__HAL_RCC_TIM12_CLK_ENABLE();
/* TIM12 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM8_BRK_TIM12_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn);
}
}
#endif
#ifdef USE_TIM13
if(htim->Instance==TIM13)
{
/* TIM13 clock enable */
__HAL_RCC_TIM13_CLK_ENABLE();
/* TIM13 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
}
}
#endif
#ifdef USE_TIM14
if(htim->Instance==TIM14)
{
/* TIM14 clock enable */
__HAL_RCC_TIM14_CLK_ENABLE();
/* TIM14 interrupt Init */
if(it_mode)
{
HAL_NVIC_SetPriority(TIM8_TRG_COM_TIM14_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM8_TRG_COM_TIM14_IRQn);
}
}
#endif
}
/**
* @brief Деинициализация CLK и NVIC таймеров.
* @param htim Указатель на хендл таймера.
* @note Чтобы не генерировать функцию с деиницилизацией неиспользуемых таймеров,
дефайнами @ref TIM_INIT в @ref general_tim.h определяются используемые таймеры.
*/
void TIM_Base_MspDeInit(TIM_HandleTypeDef* htim)
{
if(check_null_ptr_2(htim, htim->Instance))
return;
#ifdef USE_TIM1
if(htim->Instance==TIM1)
{
__HAL_RCC_TIM1_FORCE_RESET();
__HAL_RCC_TIM1_RELEASE_RESET();
}
#endif
#ifdef USE_TIM2
if(htim->Instance==TIM2)
{
__HAL_RCC_TIM2_FORCE_RESET();
__HAL_RCC_TIM2_RELEASE_RESET();
}
#endif
#ifdef USE_TIM3
if(htim->Instance==TIM3)
{
__HAL_RCC_TIM3_FORCE_RESET();
__HAL_RCC_TIM3_RELEASE_RESET();
}
#endif
#ifdef USE_TIM4
if(htim->Instance==TIM4)
{
__HAL_RCC_TIM4_FORCE_RESET();
__HAL_RCC_TIM4_RELEASE_RESET();
}
#endif
#ifdef USE_TIM5
if(htim->Instance==TIM5)
{
__HAL_RCC_TIM5_FORCE_RESET();
__HAL_RCC_TIM5_RELEASE_RESET();
}
#endif
#ifdef USE_TIM6
if(htim->Instance==TIM6)
{
__HAL_RCC_TIM6_FORCE_RESET();
__HAL_RCC_TIM6_RELEASE_RESET();
}
#endif
#ifdef USE_TIM7
if(htim->Instance==TIM7)
{
__HAL_RCC_TIM7_FORCE_RESET();
__HAL_RCC_TIM7_RELEASE_RESET();
}
#endif
#ifdef USE_TIM8
if(htim->Instance==TIM8)
{
__HAL_RCC_TIM8_FORCE_RESET();
__HAL_RCC_TIM8_RELEASE_RESET();
}
#endif
#ifdef USE_TIM9
if(htim->Instance==TIM9)
{
__HAL_RCC_TIM9_FORCE_RESET();
__HAL_RCC_TIM9_RELEASE_RESET();
}
#endif
#ifdef USE_TIM10
if(htim->Instance==TIM10)
{
__HAL_RCC_TIM10_FORCE_RESET();
__HAL_RCC_TIM10_RELEASE_RESET();
}
#endif
#ifdef USE_TIM11
if(htim->Instance==TIM11)
{
__HAL_RCC_TIM11_FORCE_RESET();
__HAL_RCC_TIM11_RELEASE_RESET();
}
#endif
#ifdef USE_TIM12
if(htim->Instance==TIM12)
{
__HAL_RCC_TIM12_FORCE_RESET();
__HAL_RCC_TIM12_RELEASE_RESET();
}
#endif
#ifdef USE_TIM13
if(htim->Instance==TIM13)
{
__HAL_RCC_TIM13_FORCE_RESET();
__HAL_RCC_TIM13_RELEASE_RESET();
}
#endif
#ifdef USE_TIM14
if(htim->Instance==TIM14)
{
__HAL_RCC_TIM14_FORCE_RESET();
__HAL_RCC_TIM14_RELEASE_RESET();
}
#endif
}
//-------------------------TIM INIT FUNCTIONS------------------------
//-------------------------------------------------------------------