Timer as PWM on LPC1769

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Timer as PWM on LPC1769

1,169 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by kabriolin on Tue Sep 24 02:13:54 MST 2013
Hi,

Currently developping a new release of an existing personnal board, i'm looking for reaplacing the current 3 uC by an LPC1769.

So I need 6 PWM at 50Hz, that's OK with the PWM module.
But I need 2 more PWM at 10KHz, I was expecting to use one of the Timer module.
Actually I can only create 2 square waves, change the frequency, but not the dutycycle.

I've use TIMER2, with MAT2.0 and MAT2.1 as channels, and MAT2.2 to reset as I did on LPC1347 on the first release.
But on GPIO0.6 and GPIO0.7, I can only see two beautiful squares, not really PWMs.

Is it any way to use a TIMER as PWM without using interrupts?

This is my Init code:
        /*By default, the PCLKSELx value is zero, thus, the PCLK for
all the peripherals is 1/4 of the SystemFrequency. */
/* Bit 12~13 is for TIMER2 */
pclkdiv = (LPC_SC->PCLKSEL1 >> 12) & 0x03;
switch ( pclkdiv )
{
case 0x00:
default:
pclk = SystemCoreClock/4;
break;
case 0x01:
pclk = SystemCoreClock;
break; 
case 0x02:
pclk = SystemCoreClock/2;
break; 
case 0x03:
pclk = SystemCoreClock/8;
break;
}

LPC_PINCON->PINSEL0 |= (0x1<<12)|(0x1<<13); //P0.6 as MAT2.0
LPC_PINCON->PINSEL0 |= (0x1<<14)|(0x1<<15); //P0.7 as MAT2.1

LPC_TIM2->TCR = 2;//Reset counter

LPC_TIM2->IR = 0x0F;          /* Clear MATx interrupt include DMA request */

        LPC_TIM2->EMR |= (1<<0)|(1<<4)|(1<<5); //MAT2.0, toogle on reset
LPC_TIM2->EMR |= (1<<1)|(1<<6)|(1<<7); //MAT2.1, toogle on reset

LPC_TIM2->PR  = pclk/1000000; /* set prescaler to get 1 M counts/sec */

LPC_TIM2->MR0 = 5000;  /* Set up interval */
LPC_TIM2->MR1 = 3000;  /* Set up interval */

LPC_TIM2->MR2 = 10000; /* Set up interval */

LPC_TIM2->MCR = (0x1<<7);/* Reset on MR2 */

LPC_TIM2->TCR = 1;     //Start Timer
}


Thx
Labels (1)
3 Replies

736 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Dec 06 04:02:31 MST 2013

Quote: kabriolin


Is it any way to disable optimisations only for this code part or file?




See #4 of http://www.lpcware.com/content/forum/lpc1114-32bit-timer-resolution
0 Kudos

736 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by kabriolin on Fri Dec 06 03:01:57 MST 2013
Hi,

I can get it working when compiling with no optimisation, but when i switch to -O1 or -O2, with the exactly same code, i have the two output always ON.

My code is

void Init_Timer(void)
{
uint32_t pclkdiv, pclk;

//TIMER2

LPC_SC->PCONP |= (0x01<<22);

/* By default, the PCLKSELx value is zero, thus, the PCLK for
all the peripherals is 1/4 of the SystemFrequency. */
/* Bit 12~13 is for TIMER2 */
pclkdiv = (LPC_SC->PCLKSEL1 >> 12) & 0x03;
switch ( pclkdiv )
{
case 0x00:
default:
pclk = SystemCoreClock/4;
break;
case 0x01:
pclk = SystemCoreClock;
break; 
case 0x02:
pclk = SystemCoreClock/2;
break; 
case 0x03:
pclk = SystemCoreClock/8;
break;
}

//P4.28 & P4.29 as Timer 2 MATCH output
LPC_PINCON->PINSEL9 |= (0x2<<24)|(0x2<<26);

LPC_TIM2->TCR = 2;  //Reset counter

LPC_TIM2->IR = 0x0F;          /* Clear MATx interrupt include DMA request */

LPC_TIM2->EMR = (1<<4)|(1<<6);

LPC_TIM2->PR  = pclk/10000000; /* set prescaler to get 100K counts/sec */

LPC_TIM2->MR0 = 0; /* Set up interval */
LPC_TIM2->MR1 = 0; /* Set up interval */

LPC_TIM2->MR2 = TIME_INTERVALmS * 0.05F; /* Set up 50us interval */

LPC_TIM2->MCR = 0x1<<6 | 0x1<<7;/* IT 2, Reset on MR2 */

LPC_TIM2->TCR = 1;

NVIC_EnableIRQ(TIMER2_IRQn);
}

void TIMER2_IRQHandler (void)
{
LPC_TIM2->EMR |= (1<<0)|(1<<1);
LPC_TIM2->IR |= 0x1<<2;/* clear interrupt flag */
}



Is it any way to disable optimisations only for this code part or file?

Thx
0 Kudos

736 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Pacman on Wed Sep 25 10:18:56 MST 2013
I needed a non-50/50 duty cycle as well.
What I did, was to make an interrupt, which toggled the compare values.
Thus I got a short ON and a very long OFF cycle.

I do not know if there are any better ways than that, but it's definitely possible to keep an accurate timing (you don't need to toggle the pins manually).

An alternative could be to use two compare registers and then an external XOR gate to combine them into one square-wave. You can get 6-pin (SC70-6), 8-pin (SOT-23) logic gates, or even smaller gate-chips if necessary.