/** * @brief This function will set the PWM to the required value * @param port : the gpio port to use * @param pin : the gpio pin to use * @param clock_freq : frequency of the tim clock * @param period : period of the tim counter * @param value : the value to push on the PWM output * @param do_init : if set to 1 the initialization of the PWM is done * @retval None */ void pwm_start(PinName pin, uint32_t clock_freq, uint32_t period, uint32_t value, uint8_t do_init) { TIM_HandleTypeDef timHandle = {}; TIM_OC_InitTypeDef timConfig = {}; uint32_t timChannel; /* Compute the prescaler value to have TIM counter clock equal to clock_freq Hz */ timHandle.Instance = pinmap_peripheral(pin, PinMap_PWM); if (timHandle.Instance == NP) return; timHandle.Init.Prescaler = (uint32_t)(getTimerClkFreq(timHandle.Instance) / clock_freq) - 1; timHandle.Init.Period = period -1; timHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; timHandle.Init.CounterMode = TIM_COUNTERMODE_UP; #if !defined(STM32L0xx) && !defined(STM32L1xx) timHandle.Init.RepetitionCounter = 0; #endif timHandle.State= HAL_TIM_STATE_RESET; // TBC: is timHandle.State field should be saved ? if (do_init == 1) { g_current_pin = pin; if (HAL_TIM_PWM_Init(&timHandle) != HAL_OK) { return; } } timChannel = get_pwm_channel(pin); if (!IS_TIM_CHANNELS(timChannel)) return; //HAL_TIM_PWM_Stop(&timHandle, timChannel); /*##-2- Configure the PWM channels #########################################*/ /* Common configuration for all channels */ timConfig.OCMode = TIM_OCMODE_PWM1; timConfig.OCPolarity = TIM_OCPOLARITY_HIGH; timConfig.OCFastMode = TIM_OCFAST_DISABLE; #if !defined(STM32L0xx) && !defined(STM32L1xx) timConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH; timConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET; timConfig.OCIdleState = TIM_OCIDLESTATE_RESET; #endif timConfig.Pulse = value; if (HAL_TIM_PWM_ConfigChannel(&timHandle, &timConfig, timChannel) != HAL_OK) { /*##-2- Configure the PWM channels #########################################*/ return; } #if !defined(STM32L0xx) && !defined(STM32L1xx) if(STM_PIN_INVERTED(pinmap_function(pin, PinMap_PWM))) { HAL_TIMEx_PWMN_Start(&timHandle, timChannel); } else #endif { HAL_TIM_PWM_Start(&timHandle, timChannel); } }
/** * @brief This function will disable the PWM * @param port : the gpio port to use * @param pin : the gpio pin to use * @retval None */ void pwm_stop(PinName pin) { TIM_HandleTypeDef timHandle; uint32_t timChannel; timHandle.Instance = pinmap_peripheral(pin, PinMap_PWM); if (timHandle.Instance == NP) return; timChannel = get_pwm_channel(pin); if (!IS_TIM_CHANNELS(timChannel)) return; #if !defined(STM32L0xx) && !defined(STM32L1xx) if (STM_PIN_INVERTED(pinmap_function(pin, PinMap_PWM))) { HAL_TIMEx_PWMN_Stop(&timHandle, timChannel); } else #endif { HAL_TIM_PWM_Stop(&timHandle, timChannel); } HAL_TIM_PWM_DeInit(&timHandle); }
/* * Set the period and pulse width for a PWM pin. * * Parameters * dev: Pointer to PWM device structure * pwm: PWM channel to set * period_cycles: Period (in timer count) * pulse_cycles: Pulse width (in timer count). * * return 0, or negative errno code */ static int pwm_stm32_pin_set(struct device *dev, u32_t pwm, u32_t period_cycles, u32_t pulse_cycles) { struct pwm_stm32_data *data = DEV_DATA(dev); TIM_HandleTypeDef *TimerHandle = &data->hpwm; TIM_OC_InitTypeDef sConfig; u32_t channel; bool counter_32b; if (period_cycles == 0 || pulse_cycles > period_cycles) { return -EINVAL; } /* configure channel */ channel = (pwm - 1)*CHANNEL_LENGTH; if (!IS_TIM_INSTANCE(PWM_STRUCT(dev)) || !IS_TIM_CHANNELS(channel)) { return -ENOTSUP; } #ifdef CONFIG_SOC_SERIES_STM32F1X /* FIXME: IS_TIM_32B_COUNTER_INSTANCE not available on * SMT32F1 Cube HAL since all timer counters are 16 bits */ counter_32b = 0; #else counter_32b = IS_TIM_32B_COUNTER_INSTANCE(PWM_STRUCT(dev)); #endif /* * The timer counts from 0 up to the value in the ARR register (16-bit). * Thus period_cycles cannot be greater than UINT16_MAX + 1. */ if (!counter_32b && (period_cycles > 0x10000)) { /* 16 bits counter does not support requested period * You might want to adapt PWM output clock to adjust * cycle durations to fit requested period into 16 bits * counter */ return -ENOTSUP; } /* Configure Timer IP */ TimerHandle->Instance = PWM_STRUCT(dev); TimerHandle->Init.Prescaler = data->pwm_prescaler; TimerHandle->Init.ClockDivision = 0; TimerHandle->Init.CounterMode = TIM_COUNTERMODE_UP; TimerHandle->Init.RepetitionCounter = 0; /* Set period value */ TimerHandle->Init.Period = period_cycles - 1; HAL_TIM_PWM_Init(TimerHandle); /* Configure PWM channel */ sConfig.OCMode = TIM_OCMODE_PWM1; sConfig.OCPolarity = TIM_OCPOLARITY_HIGH; sConfig.OCFastMode = TIM_OCFAST_DISABLE; sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET; sConfig.OCIdleState = TIM_OCIDLESTATE_RESET; /* Set the pulse value */ sConfig.Pulse = pulse_cycles; HAL_TIM_PWM_ConfigChannel(TimerHandle, &sConfig, channel); return HAL_TIM_PWM_Start(TimerHandle, channel); }