Forums

PWM with olimex lpc2106-mt pcb - how to?

Started by killtheclock July 20, 2004
Hi all,

I have an olimex lpc2106-mt pcb and try to program a PWM without
success. The Docu is not especially detailed (I think). I tried a lot
of register settings(for hours). All I get is a single 88.64 ms pulse
on PWM4 at reset that does not change with the match register or pre-
scaler value.

This code is one example that illustrates my understanding of that
thing:
//testing PWM4
PINSEL0 |= 0x20000; // select pin 0.08 PWM4 function
PWM_PR = 0x0000; // max prescale counter value
PWM_MCR = 0x0002; // reset when PWMMR0 matches
PWM_PCR = 0x1000; // PWM4 enable, single edge
PWM_MR0 = 0x0f00; // match register trigger value
PWM_TCR = 0x0009; // set the TC counter and enable the PWMs

I would expect a 1.92 kHz frequency from that...
Obviously I do something completly wrong.

Any help is really apreciated

Cheers, Kurt.



An Engineer's Guide to the LPC2100 Series

--- In , "killtheclock" <kurt.westphal@g...>
wrote:

> I have an olimex lpc2106-mt pcb and try to program a PWM without
> success. The Docu is not especially detailed (I think). I tried a
lot
> of register settings(for hours). All I get is a single 88.64 ms
pulse
> on PWM4 at reset that does not change with the match register or
pre-
> scaler value.
>
> This code is one example that illustrates my understanding of that
> thing:
> //testing PWM4
> PINSEL0 |= 0x20000; // select pin 0.08 PWM4 function
> PWM_PR = 0x0000; // max prescale counter value
> PWM_MCR = 0x0002; // reset when PWMMR0 matches
> PWM_PCR = 0x1000; // PWM4 enable, single edge
> PWM_MR0 = 0x0f00; // match register trigger value
> PWM_TCR = 0x0009; // set the TC counter and enable the PWMs
>
> I would expect a 1.92 kHz frequency from that...
> Obviously I do something completly wrong.

You also need to set PWM_MR4, and then PWM_LER before the PWM_MRx
values take effect.

Karl Olsen



I still can't get it running. Karl showed me the way to understand
the docu - at least I felt like understanding it...
Current code status:

//testing PWM4
PINSEL0 |= 0x20000; // select pin 0.08 PWM4 function

PWM_PR = 0x0000; // max prescale counter value
PWM_MCR = 0x0002; // reset TC when PWMMR0 matches
PWM_PCR = 0x7E00; // enable all PWM just to get the right one
PWM_TCR = 0x000A; // reset TC counter (not yet needed?!)

PWM_MR0 = 0x0400; // match register 0 trigger value
PWM_LER |= BIT0;

PWM_MR4 = 0x0150; // match register 4 trigger value
PWM_LER |= BIT4;

PWM_TCR = 0x0009; // set the TC counter and enable the PWMs

But still getting the single 88.64 ms pulse.
Any idea?

Cheers, Kurt. --- In , "Karl Olsen" <kro@p...> wrote:
> --- In , "killtheclock" <kurt.westphal@g...>
> wrote:
>
> > I have an olimex lpc2106-mt pcb and try to program a PWM without
> > success. The Docu is not especially detailed (I think). I tried a
> lot
> > of register settings(for hours). All I get is a single 88.64 ms
> pulse
> > on PWM4 at reset that does not change with the match register or
> pre-
> > scaler value.
> >
> > This code is one example that illustrates my understanding of
that
> > thing:
> > //testing PWM4
> > PINSEL0 |= 0x20000; // select pin 0.08 PWM4 function
> > PWM_PR = 0x0000; // max prescale counter value
> > PWM_MCR = 0x0002; // reset when PWMMR0 matches
> > PWM_PCR = 0x1000; // PWM4 enable, single edge
> > PWM_MR0 = 0x0f00; // match register trigger value
> > PWM_TCR = 0x0009; // set the TC counter and enable the PWMs
> >
> > I would expect a 1.92 kHz frequency from that...
> > Obviously I do something completly wrong.
>
> You also need to set PWM_MR4, and then PWM_LER before the PWM_MRx
> values take effect.
>
> Karl Olsen





> I still can't get it running. Karl showed me the way to understand
> the docu - at least I felt like understanding it...
> Current code status:
>
> //testing PWM4
> PINSEL0 |= 0x20000; // select pin 0.08 PWM4 function
>
> PWM_PR = 0x0000; // max prescale counter value
> PWM_MCR = 0x0002; // reset TC when PWMMR0 matches
> PWM_PCR = 0x7E00; // enable all PWM just to get the right one
> PWM_TCR = 0x000A; // reset TC counter (not yet needed?!)
>
> PWM_MR0 = 0x0400; // match register 0 trigger value
> PWM_LER |= BIT0;
>
> PWM_MR4 = 0x0150; // match register 4 trigger value
> PWM_LER |= BIT4;
>
> PWM_TCR = 0x0009; // set the TC counter and enable the PWMs
>
> But still getting the single 88.64 ms pulse.
> Any idea?
>
> Cheers, Kurt.

Hi Kurt,

I think the main problem is that you have to wait until you get the Match _before_
the PWM cycle is actually written. This would explain why you only get a single pulse.

Follow this procedure I use :

/* Setting the PWM cycle */
/*******************/
PWMTCR = 0x0B; // Hold TC in reset while altering Cycle
PWMMR0 = CYCLE; // Write the new PWM period
PWMMCR = 0x01; // Allow the INT flag for MR0
PWMTCR = 0x09; // Restart PWM
PWMIR |= 0x01; // Reset MR0 Int flag
PWMLER = 0x01; // Enable PWM0 latch
while ( ! (PWMIR & 0x01)); // Wait for match -> new cycle complete
PWMMCR = 0; // Disable MR0 Int flagging

/* Setting , for example, PWM5 */
/***********************/
PWMMR5 = DUTY; // write duty cycle
PWMLER = 0x20; // enable PWM5 Latch

Obviously CYCLE is the total PWM cycle and PERIOD makes the
PWM's dutycycle as = DUTY / CYCLE

So if you eg. set CYCLE to 1000 and DUTY to 150 you would get a 15% dutycycle
with a frequency of PCLK / 1000 (cycle), providing Prescaler is set to ONE (=0).

There might be better ways of doing this, but this way ensures you wait long enough
for the PWM period cycle to update, but no longer than necessary......

B rgds and good luck,
Kris



Now I got it:
It is really simple. The only problem was that I inited P0.8 to be
used as TxD UART 1, PINSEL P0.8 bits set to 01. Then in the main
program I set the bits to 10.
PINSEL0 |= 0x20000;
That resulted in both bits set for P0.8, wich is undefined and does
not work.

This code does work:

//setup PWM4
PINSEL0 &= ~BIT16; // deselect pin 0.08 GPIO function
PINSEL0 |= BIT17; // select pin 0.08 PWM4 function
PWM_PCR = BIT12; //PWM4 enable, single edge
PWM_PR = 0x0000; // max prescale counter value
PWM_MR0 = 0x400; // MR0 must be set prior to enabling
// the PWM
PWM_MCR = 0x02; // enable reset on MR0
PWM_TCR = 0x09; // PWM enable and counter start
PWM_MR4 = 0x0200; // match register 4 trigger value
PWM_LER |= 0x10; // latch MR4

Kris, there is no need to poll the interrupt flag when you init MR0
before enabling PWM mode.
The docu says (UM_LPC2106_2105_2104_1.pdf, p.152, table 117):

"Note that the PWM Match register that determines the PWM rate (PWM
Match 0) must be set up prior to the PWM being enabled. Otherwise a
Match event will not occur to cause shadow register contents to
become effective."

Thank you Kris and Karl,
regards,
Kurt.

--- In , "microbit" <microbit@c...> wrote:
> > I still can't get it running. Karl showed me the way to
understand
> > the docu - at least I felt like understanding it...
> > Current code status:
> >
> > //testing PWM4
> > PINSEL0 |= 0x20000; // select pin 0.08 PWM4 function
> >
> > PWM_PR = 0x0000; // max prescale counter value
> > PWM_MCR = 0x0002; // reset TC when PWMMR0 matches
> > PWM_PCR = 0x7E00; // enable all PWM just to get the
right one
> > PWM_TCR = 0x000A; // reset TC counter (not yet needed?!)
> >
> > PWM_MR0 = 0x0400; // match register 0 trigger value
> > PWM_LER |= BIT0;
> >
> > PWM_MR4 = 0x0150; // match register 4 trigger value
> > PWM_LER |= BIT4;
> >
> > PWM_TCR = 0x0009; // set the TC counter and enable the
PWMs
> >
> > But still getting the single 88.64 ms pulse.
> > Any idea?
> >
> > Cheers, Kurt.
>
> Hi Kurt,
>
> I think the main problem is that you have to wait until you get the
Match _before_
> the PWM cycle is actually written. This would explain why you only
get a single pulse.
>
> Follow this procedure I use :
>
> /* Setting the PWM cycle */
> /*******************/
> PWMTCR = 0x0B; // Hold TC in reset while altering
Cycle
> PWMMR0 = CYCLE; // Write the new PWM period
> PWMMCR = 0x01; // Allow the INT flag for MR0
> PWMTCR = 0x09; // Restart PWM
> PWMIR |= 0x01; // Reset MR0 Int flag
> PWMLER = 0x01; // Enable PWM0 latch
> while ( ! (PWMIR & 0x01)); // Wait for match -> new cycle complete
> PWMMCR = 0; // Disable MR0 Int flagging
>
> /* Setting , for example, PWM5 */
> /***********************/
> PWMMR5 = DUTY; // write duty cycle
> PWMLER = 0x20; // enable PWM5 Latch
>
> Obviously CYCLE is the total PWM cycle and PERIOD makes the
> PWM's dutycycle as = DUTY / CYCLE
>
> So if you eg. set CYCLE to 1000 and DUTY to 150 you would get a 15%
dutycycle
> with a frequency of PCLK / 1000 (cycle), providing Prescaler is set
to ONE (=0).
>
> There might be better ways of doing this, but this way ensures you
wait long enough
> for the PWM period cycle to update, but no longer than
necessary......
>
> B rgds and good luck,
> Kris >