Pinscape fork (KL25Z)
Dependents: Pinscape_Controller_V2_arnoz Pinscape_Controller_V2
Fork of FastPWM by
FastPWM_STM_TIM.cpp
00001 //This should (hopefully) work on all STM targets which use TIM timers for PWM 00002 00003 #ifdef TARGET_STM 00004 00005 #include "FastPWM.h" 00006 00007 typedef __IO uint32_t* CHANNEL_P_T; 00008 00009 typedef struct { 00010 CHANNEL_P_T channel; 00011 uint32_t clk_prescaler; 00012 } fastpwm_struct; 00013 00014 #define PWM_CHANNEL ((((fastpwm_struct*)fast_obj)->channel)) 00015 #define PWM_CLK_PRESCALER ((((fastpwm_struct*)fast_obj)->clk_prescaler)) 00016 #define PWM_TIMER ((TIM_TypeDef*)_pwm.pwm) 00017 00018 #if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1) 00019 extern __IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin); 00020 #endif 00021 00022 void FastPWM::initFastPWM( void ) { 00023 fast_obj = new fastpwm_struct; 00024 #if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1) 00025 PWM_CHANNEL = getChannel(PWM_TIMER, _pwm.pin); 00026 #else 00027 PWM_CHANNEL = (&PWM_TIMER->CCR1 + _pwm.channel - 1); 00028 #endif 00029 00030 // Depending on the timer and the internal bus it is connected to, each STM timer 00031 // can have a fixed prescaler from the clock, especially the faster devices. 00032 // In order not to have to hardcode this in, we use knowledge that mbed lib sets 00033 // default period to 20ms to reverse engineer the prescaler from this. 00034 uint32_t current_hz = SystemCoreClock / (PWM_TIMER->PSC + 1) / (PWM_TIMER->ARR+1); 00035 PWM_CLK_PRESCALER = (current_hz + 1) / 50; //50Hz is magic number it should be, +1 is to handle possible rounding errors in mbed setup 00036 00037 //Sanity check in case a target does something different 00038 if ( (PWM_CLK_PRESCALER == 0 ) || (PWM_CLK_PRESCALER > 16)) { 00039 PWM_CLK_PRESCALER = 1; 00040 } 00041 00042 //Enable PWM period syncing for glitch free result 00043 PWM_TIMER->CR1 |= TIM_CR1_ARPE; 00044 00045 bits = 16; 00046 } 00047 00048 void FastPWM::pulsewidth_ticks( uint32_t ticks ) { 00049 *PWM_CHANNEL = ticks; 00050 } 00051 00052 void FastPWM::period_ticks( uint32_t ticks ) { 00053 PWM_TIMER->ARR = ticks - 1; 00054 } 00055 00056 uint32_t FastPWM::getPeriod( void ) { 00057 return PWM_TIMER->ARR + 1; 00058 } 00059 00060 uint32_t FastPWM::setPrescaler(uint32_t reqScale) { 00061 if (reqScale == 0) { 00062 //Return prescaler 00063 return (PWM_TIMER->PSC + 1) * PWM_CLK_PRESCALER; 00064 } 00065 if (reqScale > (uint32_t)(PWM_CLK_PRESCALER<<16)) { 00066 reqScale = PWM_CLK_PRESCALER<<16; 00067 } 00068 //Else set prescaler, we have to substract one from reqScale since a 0 in PCVAL is prescaler of 1 00069 //Take into account PWM_CLK_PRESCALER, we need to make sure reqScale is always rounded up 00070 PWM_TIMER->PSC = (reqScale + PWM_CLK_PRESCALER - 1)/PWM_CLK_PRESCALER - 1; 00071 00072 return setPrescaler(0); 00073 } 00074 00075 #endif
Generated on Thu Jul 14 2022 06:53:45 by 1.7.2