yes

Committer:
braichi13
Date:
Sun May 08 14:39:57 2022 +0000
Revision:
0:c60399891edd
Yes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
braichi13 0:c60399891edd 1 //This should (hopefully) work on all STM targets which use TIM timers for PWM
braichi13 0:c60399891edd 2
braichi13 0:c60399891edd 3 #ifdef TARGET_STM
braichi13 0:c60399891edd 4
braichi13 0:c60399891edd 5 #include "FastPWM.h"
braichi13 0:c60399891edd 6
braichi13 0:c60399891edd 7 typedef __IO uint32_t* CHANNEL_P_T;
braichi13 0:c60399891edd 8
braichi13 0:c60399891edd 9 typedef struct {
braichi13 0:c60399891edd 10 CHANNEL_P_T channel;
braichi13 0:c60399891edd 11 uint32_t clk_prescaler;
braichi13 0:c60399891edd 12 } fastpwm_struct;
braichi13 0:c60399891edd 13
braichi13 0:c60399891edd 14 #define PWM_CHANNEL ((((fastpwm_struct*)fast_obj)->channel))
braichi13 0:c60399891edd 15 #define PWM_CLK_PRESCALER ((((fastpwm_struct*)fast_obj)->clk_prescaler))
braichi13 0:c60399891edd 16 #define PWM_TIMER ((TIM_TypeDef*)_pwm.pwm)
braichi13 0:c60399891edd 17
braichi13 0:c60399891edd 18 #if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1)
braichi13 0:c60399891edd 19 extern __IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin);
braichi13 0:c60399891edd 20 #endif
braichi13 0:c60399891edd 21
braichi13 0:c60399891edd 22 void FastPWM::initFastPWM( void ) {
braichi13 0:c60399891edd 23 fast_obj = new fastpwm_struct;
braichi13 0:c60399891edd 24 #if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1)
braichi13 0:c60399891edd 25 PWM_CHANNEL = getChannel(PWM_TIMER, _pwm.pin);
braichi13 0:c60399891edd 26 #else
braichi13 0:c60399891edd 27 PWM_CHANNEL = (&PWM_TIMER->CCR1 + _pwm.channel - 1);
braichi13 0:c60399891edd 28 #endif
braichi13 0:c60399891edd 29
braichi13 0:c60399891edd 30 // Depending on the timer and the internal bus it is connected to, each STM timer
braichi13 0:c60399891edd 31 // can have a fixed prescaler from the clock, especially the faster devices.
braichi13 0:c60399891edd 32 // In order not to have to hardcode this in, we use knowledge that mbed lib sets
braichi13 0:c60399891edd 33 // default period to 20ms to reverse engineer the prescaler from this.
braichi13 0:c60399891edd 34 uint32_t current_hz = SystemCoreClock / (PWM_TIMER->PSC + 1) / (PWM_TIMER->ARR+1);
braichi13 0:c60399891edd 35 PWM_CLK_PRESCALER = (current_hz + 1) / 50; //50Hz is magic number it should be, +1 is to handle possible rounding errors in mbed setup
braichi13 0:c60399891edd 36
braichi13 0:c60399891edd 37 //Sanity check in case a target does something different
braichi13 0:c60399891edd 38 if ( (PWM_CLK_PRESCALER == 0 ) || (PWM_CLK_PRESCALER > 16)) {
braichi13 0:c60399891edd 39 PWM_CLK_PRESCALER = 1;
braichi13 0:c60399891edd 40 }
braichi13 0:c60399891edd 41
braichi13 0:c60399891edd 42 //Enable PWM period syncing for glitch free result
braichi13 0:c60399891edd 43 PWM_TIMER->CR1 |= TIM_CR1_ARPE;
braichi13 0:c60399891edd 44
braichi13 0:c60399891edd 45 bits = 16;
braichi13 0:c60399891edd 46 }
braichi13 0:c60399891edd 47
braichi13 0:c60399891edd 48 void FastPWM::pulsewidth_ticks( uint32_t ticks ) {
braichi13 0:c60399891edd 49 *PWM_CHANNEL = ticks;
braichi13 0:c60399891edd 50 }
braichi13 0:c60399891edd 51
braichi13 0:c60399891edd 52 void FastPWM::period_ticks( uint32_t ticks ) {
braichi13 0:c60399891edd 53 PWM_TIMER->ARR = ticks - 1;
braichi13 0:c60399891edd 54 }
braichi13 0:c60399891edd 55
braichi13 0:c60399891edd 56 uint32_t FastPWM::getPeriod( void ) {
braichi13 0:c60399891edd 57 return PWM_TIMER->ARR + 1;
braichi13 0:c60399891edd 58 }
braichi13 0:c60399891edd 59
braichi13 0:c60399891edd 60 uint32_t FastPWM::setPrescaler(uint32_t reqScale) {
braichi13 0:c60399891edd 61 if (reqScale == 0) {
braichi13 0:c60399891edd 62 //Return prescaler
braichi13 0:c60399891edd 63 return (PWM_TIMER->PSC + 1) * PWM_CLK_PRESCALER;
braichi13 0:c60399891edd 64 }
braichi13 0:c60399891edd 65 if (reqScale > (uint32_t)(PWM_CLK_PRESCALER<<16)) {
braichi13 0:c60399891edd 66 reqScale = PWM_CLK_PRESCALER<<16;
braichi13 0:c60399891edd 67 }
braichi13 0:c60399891edd 68 //Else set prescaler, we have to substract one from reqScale since a 0 in PCVAL is prescaler of 1
braichi13 0:c60399891edd 69 //Take into account PWM_CLK_PRESCALER, we need to make sure reqScale is always rounded up
braichi13 0:c60399891edd 70 PWM_TIMER->PSC = (reqScale + PWM_CLK_PRESCALER - 1)/PWM_CLK_PRESCALER - 1;
braichi13 0:c60399891edd 71
braichi13 0:c60399891edd 72 return setPrescaler(0);
braichi13 0:c60399891edd 73 }
braichi13 0:c60399891edd 74
braichi13 0:c60399891edd 75 #endif