PWM Triggered Interrupt

04 Apr 2012

Hi guys, I have been trying to write a program using the inbuilt PWM function but am experiencing difficulty's when trying to trigger an interrupt on the rising and falling edge of the PWM wave. I need it to create 2 outputs. One needs to output the PWM and output 2 needs to go high after a 100ms delay when the PWM goes high. When the PWM goes low output 2 also needs to go low.

/media/uploads/taylornator/problem.jpg

I currently have an interrupt trigger when the PWM rises and then it waits 100ms and makes output 2 go high. On PWM fall an interrupt makes output 2 low immediately. This works but I have tie the PWM output (p21) to an input (p22) so the input can trigger the interrupt on the rising and falling edge. How could I make it so the interrupt is triggered internally without the need of the extra input pin?

#include "mbed.h"

InterruptIn delay(p22);
PwmOut spark(p21);
DigitalOut active(LED1);
float p = 2000;

void sample() {
    wait_ms(500);           // wait for stable voltage after spike
    active = 1;
//   wait_ms(p - 100);     // see notes
//   active = 0; 
}


void hold() {
    active = 0;             // stop sample
}

int main() {

    spark.period_ms(p);     // set PWM freq
    delay.rise(sample);     // on rising edge trigger sample
    delay.fall(hold);       // on falling edge trigger hold
    spark = 0.5;            // set PWM duty cycle

    while (1) {}            // rinse and repeat
05 Apr 2012

Use the built in PWM controller for application such as this so you're CPU is not tied up doing all the waits and no interrupt needed.

#include "mbed.h"

int main()
{
    //PWM code on channel 2 and 4 (LED2/4 on MBED)
    
    LPC_SC->PCONP|=(1<<6);                                                        //enable power on PWM1
    LPC_SC->PCLKSEL0|=(3<<12);                                                    //run PWM1 clock at prescaler 8 (96MHz/8 = 12MHz)
    LPC_PINCON->PINSEL3|=(2<<14) | (2<<8);                                        //PWM on channel 2 and 4
    LPC_PINCON->PINMODE3|=(2<<14) | (2<<8);                                       //no pull ups/pull downs on PIN1.20 and 1.23
    LPC_PWM1->MCR|=(0<<14) | (0<<13) | (0<<12) | (0<<8) | (0<<7) | (0<<6) | (1<<1);        //no interrupt, no reset, no stop of TC compare match
    LPC_PWM1->CTCR|=(0<<0);                                                       //timer mode
    LPC_PWM1->PCR|=(1<<12) | (1<<10) | (1<<4) | (1<<2);                           //double edge control on channel 2 and 4
    LPC_PWM1->PR=1199999;                                                         //pre scale PWM to 10 Hz
    LPC_PWM1->MR0=9;                                                              //top value of timer/counter, reset counter on match
    LPC_PWM1->MR1=2;                                                              //ON LED 2 after 2 counts
    LPC_PWM1->MR2=9;                                                              //OFF LED 2 after 9 counts
    LPC_PWM1->MR3=6;                                                              //ON LED 4 after 6 counts
    LPC_PWM1->MR4=9;                                                              //OFF LED 4 after 9 counts
    LPC_PWM1->LER|=(1<<4) | (1<<3) | (1<<2) | (1<<1) | (1<<0);                    //update values
    LPC_PWM1->TCR|=(1<<3) | (1<<0);                                               //enable PWM and timer NOW
    
    
    while(1);
}

DEMO code above uses 10Hz counter frequency and LED outputs

use the LPC1768 double-edge PWM functionality

application details:

counter counts from 0 to 9

on count 2, LED 2 is set ON

on count 6, LED 4 is set ON

  • the delay between the two LEDs is 4 counts (400ms)

on count 9(MR2 and MR4), both LEDs are set OFF

on same count 9(MR0), the counter is reset to zero and the cycle begins again

change the values of MRx registers to suit your frequency and period requirements

you are welcome!!!