Pinscape fork (KL25Z)

Dependents:   Pinscape_Controller_V2_arnoz Pinscape_Controller_V2

Fork of FastPWM by Erik -

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FastPWM_STM_TIM.cpp Source File

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