STM32_ExtendedLibs/MyLibsGeneral/Src/__general_tim.c
Razvalyaev f61aa1ff0f init commit
сделаны базовые хедеры:
- mylibs_config
- mylibs_defs
- mylibs_include
- trace
- trackers
- bit_access

также сделан модуль general_gpio.c/.h

Но надо проверить переструктуризированные модули

Остальные модули  __general_XXX в целом готовы и как-то работают (на МЗКТЭ) но не структуризированы
2025-10-18 18:27:37 +03:00

658 lines
18 KiB
C
Raw 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 Модуль для инициализации таймеров.
**************************************************************************
@verbatim
//-------------------Функции-------------------//
Functions: user init
- TIM_Base_Init Инициализация TIM
- TIM_Encoder_Init Инициализация режима энкодера
- TIM_Output_PWM_Init Инициализация PWM с выводом на GPIO
- TIM_OC_Comparator_Init Инициализация TIM как компаратора
Functions: user
- TIM_Delay Задержка с помощью TIM
Functions: tim initialize
- TIM_Base_MspInit Аналог HAL_MspInit для таймера
- TIM_Base_MspDeInit Аналог HAL_MspDeInit для таймера
@endverbatim
*************************************************************************/
#include "general_tim.h"
#include "general_gpio.h"
//-------------------------------------------------------------------
//-------------------------TIM INIT FUNCTIONS------------------------
/**
* @brief Initialize TIM with TIM_SettingsTypeDef structure.
* @param stim - указатель на структуру с настройками таймера.
* @return HAL status.
* @note Данная структура содержит хендл таймера и структуры для его настройки.
*/
HAL_StatusTypeDef TIM_Base_Init(TIM_SettingsTypeDef *stim)
{ // function takes structure for init
// check that htim is defined
if (stim->htim.Instance == NULL)
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 Initialize TIM Encoder functional.
* @param htim - указатель на хендл таймера.
* @param sConfigOC - указатель на настрйоки канала таймера.
* @param GPIOx - порт для приема енкодера.
* @param GPIO_PIN1 - первый пин для енкодера.
* @param GPIO_PIN2 - второй пин для енкодера.
* @param GPIO_PIN_SW - пин для кнопки енкодера.
* @return HAL status.
*/
HAL_StatusTypeDef TIM_Encoder_Init(TIM_EncoderTypeDef *henc, TIM_HandleTypeDef *htim)
{
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 = 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(GPIOA, &GPIO_InitStruct);
}
return HAL_OK;
}
/**
* @brief Initialize PWM Channel and GPIO for output.
* @param htim - указатель на хендл таймера.
* @param sConfigOC - указатель на настрйоки канала таймера.
* @param TIM_CHANNEL - канал таймера для настройки.
* @param GPIOx - порт для вывода ШИМ.
* @param GPIO_PIN - пин для вывода ШИМ.
* @return HAL status.
*/
HAL_StatusTypeDef TIM_Output_PWM_Init(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef *sConfigOC, uint32_t TIM_CHANNEL, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN)
{
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 = TIM_Alternate_Mapping(htim->Instance);
if(GPIO_InitStruct.Alternate)
HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
return HAL_OK;
}
/**
* @brief Initialize OC Comparator.
* @param htim - указатель на хендл таймера.
* @param TIM_CHANNEL - канал таймера для настройки.
* @return HAL status.
*/
HAL_StatusTypeDef TIM_OC_Comparator_Init(TIM_HandleTypeDef *htim, uint32_t TIM_CHANNEL)
{
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 Delay via TIM.
* @param htim - указатель на хендл таймера.
* @param delay - задержка в тиках таймера.
* @return HAL status.
* @note Таймер должен быть уже запущен.
*/
HAL_StatusTypeDef TIM_Delay(TIM_HandleTypeDef *htim, uint16_t delay)
{
if(delay >= htim->Instance->ARR)
{
return HAL_ERROR;
}
htim->Instance->CNT = 0;
while(1)
{
if(htim->Instance->CNT > delay)
{
return HAL_OK;
}
}
}
/**
* @brief Start delay via TIM.
* @param htim - указатель на хендл таймера.
* @return HAL status.
* @note Таймер должен быть уже запущен.
*/
HAL_StatusTypeDef TIM_Delay_Start(TIM_HandleTypeDef *htim)
{
htim->Instance->CNT = 0;
return HAL_OK;
}
/**
* @brief Wait Delay via TIM without blocking app.
* @param htim - указатель на хендл таймера.
* @param delay - задержка в тиках таймера.
* @return HAL status.
* @note Перед ожиданием задержки надо запутстить таймер её @ref TIM_Delay_Start
* @note Таймер не должен использоваться на время этой задержки
*/
HAL_StatusTypeDef TIM_Delay_NonBlocking(TIM_HandleTypeDef *htim, uint16_t delay)
{
if(delay >= htim->Instance->ARR)
{
return HAL_ERROR;
}
if(htim->Instance->CNT <= delay)
{
return HAL_BUSY;
}
else
{
return HAL_OK;
}
}
/**
* @brief Initialize TIMs clock and interrupt.
* @param htim - указатель на хендл таймера.
* @note Чтобы не генерировать функцию с иницилизацией неиспользуемых таймеров,
дефайнами в general_tim.h определяются используемые таймеры.
*/
void TIM_Base_MspInit(TIM_HandleTypeDef* htim, TIM_ITModeTypeDef it_mode)
{
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 DeInitialize TIMs clock and interrupt.
* @param htim - указатель на хендл таймера.
* @note Чтобы не генерировать функцию с деиницилизацией неиспользуемых таймеров,
дефайнами в general_tim.h определяются используемые таймеры.
*/
void TIM_Base_MspDeInit(TIM_HandleTypeDef* htim)
{
#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------------------------
//-------------------------------------------------------------------