Double edged PWM

17 Mar 2011

Hi,

I'm currently trying to implement two double edged pwm outputs to control a two-quad chopper drive. I can't currently get any outputs from either the pwm or a test pin to show when an interrupt is called. I'm assuming I must have missed something in setting up the pwm. I'm not too worried about the exact timings at the moment as these can be tweaked later. If anybody could shed some light on this I'd be very grateful.

#define SAMPLE_RATE    185000
#define DEAD_TIME      4

#include "mbed.h"
#include "adc.h"

DigitalOut tp(p15);
ADC adc(SAMPLE_RATE, 1);

void _OnPWM() {

    tp=0;
    
    /* disbale interrupt */

    NVIC_DisableIRQ(PWM1_IRQn);

/*    static float old_op,old_err;
    static float opfb,dem,err,new_op;
    static float dcyc;

    /* read analogue inputs */

/*    opfb=((float)adc.read(p20))/((float)0xFFF);
    dem=((float)adc.read(p19))/((float)0xFFF);

    /* pi controller implementation */

/*    err=dem-opfb;
    new_op=old_op+3*err-2.985*old_err;

    /* apply limits to pi controller */

/*    if (new_op>24) {
        new_op=24;
    } else if (new_op<0) {
        new_op=0;
    }

    /* update pwm duty cycle */

/*    dcyc=new_op*0.04;  */
    
    LPC_PWM1->MR1 = 0x7F;
    LPC_PWM1->MR2 = 0x7F;
    LPC_PWM1->MR3 = 0x7F;
    LPC_PWM1->MR4 = 0x7F;
    
    LPC_PWM1->LER |=0x15;

    /* save output and error for next time */

/*    old_op=new_op;
    old_err=err;
    
    /* clear and re-enable interrupt */
    
    LPC_PWM1->IR |= 0x73F;
    NVIC_EnableIRQ(PWM1_IRQn);

    tp=1;

    /* return to main code */

    return;
}

int main (void) {

    /* set up double edged pwm */
    /* interrupt on pwm cycle complete */
    /* set pwm frequency to ~20kHz */

    /* power pwm, set up clock and set up pins */

    LPC_SC->PCONP |= (1 << 6);
    LPC_SC->PCLKSEL0 |= (3 << 12);
    LPC_PINCON->PINSEL4 |= 0x044;
    LPC_PINCON->PINMODE4 |= 0x555;
    LPC_PINCON->PINMODE_OD2 |=0x000;
    
    /* enable pwm counter and pwm */

    LPC_PWM1->TCR |= 0x9;
    
    /* interrupt and reset counter on match 0 */
    
    LPC_PWM1->MCR |= 0x3;
    
    /* pwm 2 & 4 double edged, all others disabled */
    LPC_PWM1->PCR |= 0x1514;

    /* set up timing registers */

    LPC_PWM1->PR |= 0xFF;
    LPC_PWM1->MR0 = 0xFF;
    
    LPC_PWM1->MR1 = 0x7F;
    LPC_PWM1->MR2 = 0x7F;
    LPC_PWM1->MR3 = 0x7F;
    LPC_PWM1->MR4 = 0x7F;
    
    /* load everything */
    
    LPC_PWM1->LER |=0x15;

    LPC_PWM1->CTCR = 0;
    LPC_PWM1->CCR = 0;   
    
    /* set up interrupts */

    NVIC_DisableIRQ(PWM1_IRQn);
    NVIC_SetVector(PWM1_IRQn,(uint32_t)&_OnPWM);
    LPC_PWM1->IR |= 0x73F;

    /* put the adc in burst mode -- sampling is done in background */

    adc.startmode(0,0);
    adc.burst(1);

    /* setup pins 19 and 20 for analogue inputs */

    adc.setup(p20,1);
    adc.setup(p19,1);

    /* enable pwm interrupt */

    NVIC_EnableIRQ(PWM1_IRQn);

    tp=1;   // test pin high

    while (1) {

        /* additional code can be placed here */

    }
}

Cheers