This repository has been archived on 2020-06-14. You can view files and clone it, but cannot push or open issues or pull requests.
johan9107 ca351f536b Drivers PWM and motors
Added comment to drivers and a clk prescaler to the pwm signal
2016-09-16 10:43:15 +02:00

247 lines
8.9 KiB
C

/**************************************************************************
* 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;
}