/************************************************************************** * NAME: Johan Gärtner * * PURPOSE: Initialize driver for the PWM signal to certain outputs * * INFORMATION: * * GLOBAL VARIABLES: * * Variable Type Description * * -------- ---- ----------- * * **************************************************************************/ #include "stm32f4xx.h" #include "drivers/pwm.h" typedef enum { false, true } bool; bool pwmOk = true; /* Struct for a certain pwm profile */ typedef struct { GPIO_TypeDef * GPIO; //GPIOA/B/C uint16_t pin; //GPIO_PIN_0/1/2/3/.. TIM_TypeDef * tim; //TIM1/2/3/.. uint32_t Alternate; //GPIO_AF1_TIM1/GPIO_AF2_TIM2/.. uint32_t Channel; //TIM_CHANNEL_1/TIM_CHANNEL_1/.. }pwmProfile; /************************************************************************** * BRIEF: Error handler which stops the program if an error occurs * * INFORMATION: * **************************************************************************/ static void Error_Handler(void); /************************************************************************** * BRIEF: get_Pwm_Profile() Gets a variable of the struct "pwmProfile" * * INFORMATION: * Example - get_Pwm_Profile(GPIOA, GPIO_PIN_0, TIM_CHANNEL_3, TIM3); * **************************************************************************/ pwmProfile get_Pwm_Profile(GPIO_TypeDef * GPIO, uint16_t pin, uint32_t Channel, TIM_TypeDef * tim); /************************************************************************** * BRIEF: pwmInit initializes a pwm signal to a certain pin output * * INFORMATION: * Example - pwmInit(GPIOB, GPIO_PIN_0, TIM3, TIM_CHANNEL_3, 2000, 100); * GPIO = selects GPIO output on processor * pin = selects pin output on processor * tim = Timer configuration * Channel = Selects a channel for a certain timer, each timer as 4 channels * period = Period of PWM signal * pulse = the "duty cycle" of the pwm signal * **************************************************************************/ void pwmInit(GPIO_TypeDef * GPIO, uint16_t pin, TIM_TypeDef * tim, uint32_t Channel, uint16_t period, uint16_t pulse) { pwmProfile profile; profile = get_Pwm_Profile(GPIO, pin, Channel, tim); /* Get a current profile for a pwm to a certain pin */ HAL_Init(); /* Enables clock for a certain GPIO and timer */ if (GPIO == GPIOA) __HAL_RCC_GPIOA_CLK_ENABLE(); if (GPIO == GPIOB) __HAL_RCC_GPIOB_CLK_ENABLE(); if (GPIO == GPIOC) __HAL_RCC_GPIOC_CLK_ENABLE(); if (tim == TIM1) __HAL_RCC_TIM1_CLK_ENABLE(); if (tim == TIM2) __HAL_RCC_TIM2_CLK_ENABLE(); if (tim == TIM3) __HAL_RCC_TIM3_CLK_ENABLE(); if (tim == TIM4) __HAL_RCC_TIM4_CLK_ENABLE(); if (tim == TIM5) __HAL_RCC_TIM5_CLK_ENABLE(); if (tim == TIM8) __HAL_RCC_TIM8_CLK_ENABLE(); if (tim == TIM9) __HAL_RCC_TIM9_CLK_ENABLE(); if (tim == TIM12) __HAL_RCC_TIM12_CLK_ENABLE(); /* ------------------------------------------ */ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = profile.pin; /* Sets the pwm pin */ GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Alternate = profile.Alternate; /* Enables the Alternate function for a pin to the correct pwm function */ GPIO_InitStructure.Pull = GPIO_NOPULL; HAL_GPIO_Init(profile.GPIO, &GPIO_InitStructure); /* Sets the pwm GPIO */ TIM_HandleTypeDef TimHandle; uint32_t uwPrescalerValue =2; TimHandle.Instance = profile.tim; /* Sets timer */ TimHandle.Init.Period = period; /* Sets period of pwm */ TimHandle.Init.Prescaler = uwPrescalerValue; TimHandle.Init.ClockDivision = 0; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; TIM_OC_InitTypeDef PWMConfig; //PWMConfig.Pulse = 840; PWMConfig.Pulse = 840; PWMConfig.OCMode = TIM_OCMODE_PWM1; PWMConfig.OCPolarity = TIM_OCPOLARITY_HIGH; PWMConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH; PWMConfig.OCIdleState = TIM_OCIDLESTATE_SET; PWMConfig.OCNIdleState= TIM_OCNIDLESTATE_RESET; PWMConfig.OCFastMode = TIM_OCFAST_DISABLE; TIM_BreakDeadTimeConfigTypeDef DeadConfig; DeadConfig.AutomaticOutput=TIM_AUTOMATICOUTPUT_ENABLE; DeadConfig.BreakPolarity=0; DeadConfig.BreakState=0; DeadConfig.DeadTime=100; DeadConfig.LockLevel=0; DeadConfig.OffStateIDLEMode=1; DeadConfig.OffStateRunMode=1; if(HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) Error_Handler(); /* Init pwm */ if(HAL_TIM_PWM_ConfigChannel(&TimHandle,&PWMConfig,profile.Channel) != HAL_OK) Error_Handler(); /* pwm configure channel and select channel */ if(HAL_TIMEx_ConfigBreakDeadTime(&TimHandle,&DeadConfig) != HAL_OK) Error_Handler(); /* ConfigBreakDeadTime and sets channel */ if(HAL_TIM_PWM_Start(&TimHandle, profile.Channel) != HAL_OK) Error_Handler(); /* Starts pwm and sets channel */ if(HAL_TIMEx_PWMN_Start(&TimHandle,profile.Channel) != HAL_OK) Error_Handler(); /* Starts pwm and sets channel */ /* Sets a pulse for a certain channel for a certain timer (CCRx = channel x) */ switch(profile.Channel) { case TIM_CHANNEL_1: profile.tim->CCR1 = pulse; break; case TIM_CHANNEL_2: profile.tim->CCR2 = pulse; break; case TIM_CHANNEL_3: profile.tim->CCR3 = pulse; break; case TIM_CHANNEL_4: profile.tim->CCR4 = pulse; break; default: break; } } /************************************************************************** * BRIEF: setPwmPulse changes a certain pulse for an initialized pwm signal * INFORMATION: It's only possible to change the pwm output for a certain timer * on a certain channel, not a pin output. This function will only run is a pwm is active. * The pwm is activated and deactivated at startPwm/stopPwm * Example - setPwmPulse(TIM_CHANNEL_4, TIM3, 500); **************************************************************************/ void setPwmPulse(uint32_t Channel, TIM_TypeDef * tim, uint16_t newPulse) { if(pwmOk) { TIM_HandleTypeDef TimHandle; TimHandle.Instance = tim; HAL_TIM_PWM_Start(&TimHandle, Channel); switch(Channel) { case TIM_CHANNEL_1: tim->CCR1 = newPulse; break; case TIM_CHANNEL_2: tim->CCR2 = newPulse; break; case TIM_CHANNEL_3: tim->CCR3 = newPulse; break; case TIM_CHANNEL_4: tim->CCR4 = newPulse; break; default: break; } } } /************************************************************************** * BRIEF: startPwm Activates a pwm signal for a certain timer on a certain channel * INFORMATION: * Example - startPwm(TIM_CHANNEL_4, TIM3); **************************************************************************/ void startPwm(uint32_t Channel, TIM_TypeDef * tim) { pwmOk = true; TIM_HandleTypeDef TimHandle; TimHandle.Instance = tim; HAL_TIM_PWM_Start(&TimHandle, Channel); } /************************************************************************** * BRIEF: stopPwm Deactivates a pwm signal for a certain timer on a certain channel * INFORMATION: * Example - stopPwm(TIM_CHANNEL_4, TIM3); **************************************************************************/ void stopPwm(uint32_t Channel, TIM_TypeDef * tim) { pwmOk = false; TIM_HandleTypeDef TimHandle; TimHandle.Instance = tim; HAL_TIM_PWM_Stop(&TimHandle, Channel); } /************************************************************************** * BRIEF: Error handler which stops the program if an error occurs * * INFORMATION: * **************************************************************************/ static void Error_Handler(void) { while(1) { } } /************************************************************************** * BRIEF: get_Pwm_Profile() Gets a variable of the struct "pwmProfile" * * INFORMATION: * Example - get_Pwm_Profile(GPIOA, GPIO_PIN_0, TIM_CHANNEL_3, TIM3); * **************************************************************************/ pwmProfile get_Pwm_Profile(GPIO_TypeDef * GPIO, uint16_t pin, uint32_t Channel, TIM_TypeDef * tim) { pwmProfile profile; /* Sets a Alternate function for a certain timer */ if(tim == TIM1) profile.Alternate = GPIO_AF1_TIM1; else if(tim == TIM2) profile.Alternate = GPIO_AF1_TIM2; else if(tim == TIM3) profile.Alternate = GPIO_AF2_TIM3; else if(tim == TIM4) profile.Alternate = GPIO_AF2_TIM4; else if(tim == TIM5) profile.Alternate = GPIO_AF2_TIM5; else if(tim == TIM8) profile.Alternate = GPIO_AF3_TIM8; else if(tim == TIM9) profile.Alternate = GPIO_AF3_TIM9; else if(tim == TIM12) profile.Alternate = GPIO_AF9_TIM12; profile.Channel = Channel; profile.GPIO = GPIO; profile.pin = pin; profile.tim = tim; return profile; }