Viewing function source code

20 Jan 2012

Hello all I was searching the forum for instructions on how to access function source code. Say for example I'm interested in the functions located here: http://mbed.org/handbook/PwmOut

I'd like to look at the code for the function PwmOut or period_us. How can I do this?

Thank you Scott

21 Jan 2012

Source code of the official mbed libraries is not open (besides the headers).

07 Feb 2012

It is unfortunate that the source code of the official mbed libraries is not open. I need to use the PWM to make pulses narrower than 1 microsecond. Would it be possible to get a look at the PwmOut code specifically for this purpose, or could someone modify the library to have calls to set the pulse width in terms of timer counts?

08 Feb 2012

Philip,

I had a similar need to drive peripherals with a clock signal in the 4-8Mhz range and wanted to use a PWMout channel to do so however, the mbed API is limited to 1Mhz maximum. In my investigations I found some useful information regarding manipulating the hardware registers directly to alter the pre-scaler blocks that 'divide-by' to reduce the 96Mhz system clock down to a lower frequency to drive the PWM hardware.

Refer to forum called "5 MHz clock signal" /forum/mbed/topic/733/?page=1#comment-3597

and also a good blog link for LPC1768 PWM is: http://msys-mv.blogspot.com/2011/01/using-pwm-on-lpc17xx.html

I put together a simple snippet of code to collect my thoughts for self tutorial for my future reference:

#include "mbed.h"

PwmOut oscillator(p21);                // using hardware channel PWM_6

int main() {
    
    /* Here we maniplulate the LPC1768 hardware registers directly. Due to the 96Mhz system
    clock and the design of the PWMout library function to achieve waveform periods on exact
    settings on exact frequency stops in S, ms & us, it is limited to 1Mhz output maximum. We
    use PWMout to do the legwork of setup, pin assignment & starting the PWM, then we access 
    the hardware registers directly to achieve a PWM output greater than the 1Mhz library limitation.
    
    Refer to forum called "5 MHz clock signal" and also a good blog link for LPC1768 PWM is:
    http://msys-mv.blogspot.com/2011/01/using-pwm-on-lpc17xx.html
    */
    

    LPC_SC->PCLKSEL0 &= ~(3<<12);   //manipulate LPC1768 peripheral master PCLK_PWM1 clock pre-scaler register and
    LPC_SC->PCLKSEL0 |= (1<<12);    //set to divide by /1 (ie: system clock 96Mhz) rather than default /4
                                    //should now output 4-times the 1Mhz inherent maximum rate of PWMout, or 4Mhz
                                    //refer to LPC17xx manual, table 40 and 42, pg 56 and 57
                                    
    LPC_PWM1->MR0 = 23;             //Match Register 0 is shared period counter for all PWM outputs
                                    //system clock 96Mhz divided by 24 less one (because counts from zero)
                                    //96Mhz / 24 = exactly 4Mhz period
                                    
    LPC_PWM1->MR6 =12;              //Pin 21 is PWM output 6, so Match Register 6 determines pulse width
                                    //pulse width would be half of 23 for 50% duty cycle but because register
                                    //only accepts integers we'll use 12                                
                                    
        while (1) {}
}

When you make the adjustments to the clock pre-scaler and match register MR0 (period counter), they will affect all six PWMout channels in the same way being all six share and are dependent on these two hardware registers. The duty cycle or pulse width are each independently adjustable and specific to each PWMout channel by the respective match register:

  • MR1 is for PWM output 1
  • MR2 is for PWM output 2
  • MR3 is for PWM output 3
  • MR4 is for PWM output 4
  • MR5 is for PWM output 5
  • MR6 is for PWM output 6

I hope you find this helpful. It helped me learn how to achieve the output I needed.

Dave

10 Feb 2012

Hi Dave,

Thanks for the inputs. In case it is useful for anyone else, here is the code that I wrote to generate single edge pulses from PWM1.1 output to mbed pin 26 with the pulse width and period controllable at the level of clock cycles.

-Phil

void setPWM(int width, int period){
    //pc.printf("pulse width=%i, period=%i.\r\n", width, period);
    LPC_SC->PCONP |= (1 << 6); // PWM1 power on
    LPC_SC->PCLKSEL0 |= (1 << 12); // Divide CCLK by 1 for PWM1
    LPC_PINCON->PINSEL4  |= 1; // DIP26 = pin P2.0, set to PWM1.1
    LPC_PINCON->PINMODE4 |= 2; // enable neither pull up nor pull down.
    LPC_PWM1->TCR = 0; // reset PWM
    //LPC_PWM1->MCR = 0; // no interrupts (set for no interrupts by default)
    LPC_PWM1->MR0 = period; // set pulse period in clock cycles
    LPC_PWM1->MCR |= 1 << 1; // Reset timer on Match0 
    LPC_PWM1->MR1 = width; // set pulse width in clock cycles
    LPC_PWM1->LER = 3; // make match register writes effective for MR0+MR1
    LPC_PWM1->PCR |= (1 << 9); // enable PWM1 output, single edge mode
    LPC_PWM1->TC = 0; // clear timer counter
    LPC_PWM1->PC = 0; // clear prescale counter
    LPC_PWM1->PR = 0; // clear prescale register
    LPC_PWM1->TCR = 8+1; // enable PWM mode and PWM timer counter
}
27 May 2014

You inputs have been really helpful cheers

27 May 2014

FYI take into account these days the mbed source code is open. For faster/more accurate PWM, consider: http://mbed.org/users/Sissors/code/FastPWM/. The wiki there explains it, but it allows you to have the full accuracy of the device.

08 Oct 2015

Thanks Phil/Dave.

How can I reuse the code for any other pin (say pin25=PWM1.2)? Wht values do I need to change other than MCR1?

Jatin

Philip Kaaret wrote:

Hi Dave,

Thanks for the inputs. In case it is useful for anyone else, here is the code that I wrote to generate single edge pulses from PWM1.1 output to mbed pin 26 with the pulse width and period controllable at the level of clock cycles.

-Phil

void setPWM(int width, int period){
    //pc.printf("pulse width=%i, period=%i.\r\n", width, period);
    LPC_SC->PCONP |= (1 << 6); // PWM1 power on
    LPC_SC->PCLKSEL0 |= (1 << 12); // Divide CCLK by 1 for PWM1
    LPC_PINCON->PINSEL4  |= 1; // DIP26 = pin P2.0, set to PWM1.1
    LPC_PINCON->PINMODE4 |= 2; // enable neither pull up nor pull down.
    LPC_PWM1->TCR = 0; // reset PWM
    //LPC_PWM1->MCR = 0; // no interrupts (set for no interrupts by default)
    LPC_PWM1->MR0 = period; // set pulse period in clock cycles
    LPC_PWM1->MCR |= 1 << 1; // Reset timer on Match0 
    LPC_PWM1->MR1 = width; // set pulse width in clock cycles
    LPC_PWM1->LER = 3; // make match register writes effective for MR0+MR1
    LPC_PWM1->PCR |= (1 << 9); // enable PWM1 output, single edge mode
    LPC_PWM1->TC = 0; // clear timer counter
    LPC_PWM1->PC = 0; // clear prescale counter
    LPC_PWM1->PR = 0; // clear prescale register
    LPC_PWM1->TCR = 8+1; // enable PWM mode and PWM timer counter
}