LPC Open LPC13xx PWM

To use the PWM functions of the PWM Output pins we have to modify the lpcopen library. Then we have to do four steps to configure the PWM:

1) modify the lpcopen library

2) configure the IO pins for pwm function

3) Initialise the PWM

4) set a match value for the PWM timer and with it the duty cycle.

Follow me

Modify the lpcopen library:

For some reason the PIO_SWCLK_PIO0_10 register address is not added in the iocon_13xx.h, maybe because this pin has also the swclk function for the jtag interface. So if you want to use this pin as PWM make sure you do not need the jtag interface for reprogramming the chip. I am programming via the uart so I can change the pin configuration without a worry.

To add the register address to the iocon_13xx.h you have to modify the CHIP_IOCON_PIO enum which defines the address offsets and add

IOCON_SWCLK_PIO0_10 = (0x068 >> 2),

Now we are able to configure the PIO0_10 pin correctly.
Now we have to edit the timer_13xx.h to add the PWM register and read, write function of it.
 We add the PWM Control register (PWMC) to the LPC_TIMER_T struct see below:
/**
* @brief 32-bit Standard timer register block structure
*/
typedef struct { /*!< TIMERn Structure */
    __IO uint32_t IR; /*!< Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */
    __IO uint32_t TCR; /*!< Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */
    __IO uint32_t TC; /*!< Timer Counter. The 32 bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */
    __IO uint32_t PR; /*!< Prescale Register. The Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */
    __IO uint32_t PC; /*!< Prescale Counter. The 32 bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */
    __IO uint32_t MCR; /*!< Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */
    __IO uint32_t MR[4]; /*!< Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */
    __IO uint32_t CCR; /*!< Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */
    __IO uint32_t CR[4]; /*!< Capture Register. CR is loaded with the value of TC when there is an event on the CAPn.0 input. */
    __IO uint32_t EMR; /*!< External Match Register. The EMR controls the external match pins MATn.0-3 (MAT0.0-3 and MAT1.0-3 respectively). */
    __I uint32_t RESERVED0[12];
    __IO uint32_t CTCR; /*!< Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */
    __IO uint32_t PWMC; /*!< PWM Control Register */
 
} LPC_TIMER_T;

Now we add read and write functionality to the library:
Write function:
/**
* @brief	Sets the PWM Control Register
* @param	pTMR : Pointer to timer IP register address
* pwmval : value for the PWMC Register
* @return
* @note	Sets the PWMC Register.
*/
STATIC INLINE void Chip_TIMER_PWMWrite(LPC_TIMER_T *pTMR, uint32_t pwmval)
{
    pTMR->PWMC = pwmval;
}

Read Function:
/**
* @brief	Returns the PWMC Register
* @param	pTMR : Pointer to timer IP register address
* @return	Current PWMC value
* @note	Returns the current PWMC value.
*/
STATIC INLINE uint32_t Chip_TIMER_PWMRead(LPC_TIMER_T *pTMR)
{
    return pTMR->PWMC;
}

Configure the IO pins for PWM function:
To configure the IO pins for PWM function we add them in our pin_mux struct and set them up for PWM function and then call Init_Board_PinMux in the main.c.
/**
* @brief struct for pinmuxing on the bldc_board
*
* This struct contains the pinmuxing settings...
*
*/
 
const PINMUX_GRP_T pinmuxing[] = {
    {(uint32_t)IOCON_PIO0_8,
    (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_RESERVED_BIT_6
    | IOCON_RESERVED_BIT_7)}, /*PIO0_8 used for PWM (CT16B0_MAT0)*/
 
    {(uint32_t)IOCON_PIO0_9,
    (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_RESERVED_BIT_6
    | IOCON_RESERVED_BIT_7)}, /*PIO0_9 used for PWM (CT16B0_MAT0)*/
 
    {(uint32_t)IOCON_SCKCLK_PIO0_10,
    (IOCON_FUNC3 | IOCON_MODE_INACT | IOCON_RESERVED_BIT_6
    | IOCON_RESERVED_BIT_7)}, /*PIO0_10 used for PWM (CT16B0_MAT0)*/
};
 
 
void Init_Board_PinMux(void)
{
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON);
    Chip_IOCON_SetPinMuxing(LPC_IOCON,pinmuxing,
    sizeof(pinmuxing)/sizeof(PINMUX_GRP_T));
}

Initialise the PWM:
Now we have to write our Init_PWM function. This function needs a prescale to optionally scale down the frequency with which the 16 bit timer is running. And a OnResetValue for further configuration of the PWM frequency. In the Init_PWM we set up the LPC_Timer16_0, use the match3 register for an on match reset and set a prescaler. We also set the PWM Control Register to activate the PWM functionality for the three PWM Pins of the timer.
void Init_PWM(uint16_t prescaler, uint16_t OnResetValue)
{
    /* Setup Timer for PWM */
    Chip_TIMER_Init(LPC_TIMER16_0);
    // MR3 reset
    Chip_TIMER_ResetOnMatchEnable(LPC_TIMER16_0, 3);
    // Set the frequency prescaler for the timer
    Chip_TIMER_PrescaleSet(LPC_TIMER16_0, prescaler-1);
    // Set MR3 value for resetting the timer
    Chip_TIMER_SetMatch(LPC_TIMER16_0, 3, OnResetValue);
    // Set PWM Control Register
    Chip_TIMER_PWMWrite(LPC_TIMER16_0,(1<<0 | 1<<1 | 1<<2));
    // Enable Timer16_0
    Chip_TIMER_Enable(LPC_TIMER16_0);
}

Set a match value for the PWM timer and with it the duty cycle:
At this point we have everything we need to create a pwm at one of the defined pins.
To set a specific duty cylce the main could be look like this:
int main() {
    uint16_t pwm = 1800;
    Init_Board_PinMux();
    // no prescaler, a reset value of 3600 is a pwm freq. of 20 kHz
    Init_PWM(1,3600);
 
    // set MATCH2(PIO0_10) to a duty cycle of 50%
    Chip_TIMER_SetMatch(LPC_TIMER16_0,2,pwm_value);
}

Now we have a 20 kHz PWM with 50% Duty Cycle running. For the other pins the we just have to change the match port in the Chip_Timer_SetMatch.
Dieser Beitrag wurde unter ARM lpc1xxx, Mikrocontroller abgelegt und mit , , , , , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Ein Kommentar zu LPC Open LPC13xx PWM

  1. Duncan sagt:

    Hello,

    Thank you for posting the tutorial 🙂

    When I try your sample code I get an error:

    ‚IOCON_PIO0_8‘ undeclared here (not in a function)

    I have checked all my includes and I can see „iocon_13xx.h“ is included, where IOCON_PIO0_8 is defined.

    If you have any suggestions I would be grateful.

    Thanks.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darĂĽber, wie deine Kommentardaten verarbeitet werden.