diplom/научка/code/pwm_motor_control/GENERAL/tim_general.c
2025-05-09 21:26:59 +03:00

542 lines
14 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.

/**********************************TIM**************************************
Данный файл содержит базовые функции для инициализации таймеров.
//-------------------Функции-------------------//
@func users
- TIM_Base_Init Инициализация TIM
- TIM_Output_PWM_Init Инициализация PWM с выводом на GPIO
@func tim initialize
- TIM_Base_MspInit Аналог HAL_MspInit для таймера
- TIM_Base_MspDeInit Аналог HAL_MspDeInit для таймера
***************************************************************************/
#include "tim_general.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->sTickBaseMHz) // if tickbase isnt disable
{
if((stim->sTimAHBFreqMHz == NULL))
return HAL_ERROR;
stim->htim.Init.Prescaler = (stim->sTimAHBFreqMHz*stim->sTickBaseMHz) - 1;
if ((stim->sTimFreqHz != NULL))
stim->htim.Init.Period = ((1000000/stim->sTickBaseMHz) / stim->sTimFreqHz) - 1;
else if (stim->htim.Init.Period == NULL)
stim->htim.Init.Period = 0xFFFF;
}
// // if freq is too high (period too small for choosen base) OR base is too high (period too small for choosen base)
// if((stim->htim.Init.Period == NULL) || (stim->htim.Init.Prescaler == NULL))
// {
// return HAL_ERROR;
// }
// fix overflow of presc and period if need
for(int i = 0; (stim->htim.Init.Prescaler > 0xFFFF) || (stim->htim.Init.Period > 0xFFFFFFFF); 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
stim->sTickBaseMHz /= 2;
}
// 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->sTickBaseMHz *= 2;
}
}
//-------------TIM BASE INIT----------------
// tim base init
TIM_Base_MspInit(&stim->htim, stim->sTimMode);
if (HAL_TIM_Base_Init(&stim->htim) != HAL_OK)
{
ERROR_HANDLER_NAME();
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)
{
ERROR_HANDLER_NAME();
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)
{
ERROR_HANDLER_NAME();
return HAL_ERROR;
}
}
//--------------MASTER INIT-----------------
// master mode init
if (HAL_TIMEx_MasterConfigSynchronization(&stim->htim, &stim->sMasterConfig) != HAL_OK)
{
ERROR_HANDLER_NAME();
return HAL_ERROR;
}
//--------------BDTR INIT-----------------
if (HAL_TIMEx_ConfigBreakDeadTime(&stim->htim, &stim->sBreakDeadTimeConfig) != HAL_OK)
{
ERROR_HANDLER_NAME();
return HAL_ERROR;
}
//----------------IT CLEAR-------------------
__HAL_TIM_CLEAR_IT(&stim->htim, TIM_IT_UPDATE);
// обновляем TickBase
stim->sTickBaseMHz = (stim->htim.Instance->PSC+1)/stim->sTimAHBFreqMHz;
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 *henc1, TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
HAL_StatusTypeDef RES = HAL_ERROR;
henc1->htim = htim;
// setup channel for pwm
RES = HAL_TIM_Encoder_Init(henc1->htim, &henc1->sConfig);
if (RES != HAL_OK)
{
ERROR_HANDLER_NAME();
return RES;
}
// choose port for enable clock
RES = GPIO_Clock_Enable(henc1->GPIOx);
if(RES != HAL_OK)
{
ERROR_HANDLER_NAME();
return RES;
}
GPIO_InitStruct.Pin = henc1->GPIO_PIN_TI1|henc1->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(henc1->htim->Instance);
if(GPIO_InitStruct.Alternate)
HAL_GPIO_Init(henc1->GPIOx, &GPIO_InitStruct);
if(henc1->GPIO_PIN_SW)
{
/*Configure switch pin */
GPIO_InitStruct.Pin = henc1->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)
{
ERROR_HANDLER_NAME();
return RES;
}
// choose port for enable clock
RES = GPIO_Clock_Enable(GPIOx);
if(RES != HAL_OK)
{
ERROR_HANDLER_NAME();
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 TIMs clock and interrupt.
* @param htim - указатель на хендл таймера.
* @note Чтобы не генерировать функцию с иницилизацией неиспользуемых таймеров,
дефайнами в tim_general.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 Чтобы не генерировать функцию с деиницилизацией неиспользуемых таймеров,
дефайнами в tim_general.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------------------------
//-------------------------------------------------------------------