PWM on LPC1343

cancel
Showing results for 
Search instead for 
Did you mean: 

PWM on LPC1343

809 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tinto on Fri Jan 13 00:23:40 MST 2012
Could someone help me to find out the error in this program? I built the program successfully using LPCXpresso and debugged with the LPC1343 development board. But I am not getting any PWM at the output pins. The output is always high. What is the problem with this code?

#include "LPC13xx.h"

int main(void)
{
/*************************************************************************//**
  Set up 16 bit counters CT16B0 and CT16B1 to run as PWM with a cycle
  length of 4096
*****************************************************************************/

    LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7);    // Enable clock to timer 0, CT16B0
    LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8);    // Enable clock to timer 1, CT16B1

    // 16 bit timer 0 - CT16B0
    // PIO0_8 IS A
    LPC_IOCON->PIO0_8 |= 0x02;        // - set bit 1 to connect pin to CT16B0_MAT0
    LPC_IOCON->PIO0_8 &= ~(1 << 3);    // - clear bit 3 (and set 4: pull-up resistor)
    LPC_IOCON->PIO0_8 |= (1 << 4);    // - set bit 4

    // PIO0_9 IS C
    LPC_IOCON->PIO0_9 |= 0x02;        // - set bit 1 to connect pin to CT16B0_MAT1
    LPC_IOCON->PIO0_9 &= ~(1 << 3);    // - clear bit 3 (and set 4: pull-up resistor)
    LPC_IOCON->PIO0_9 |= (1 << 4);    // - set bit 4

    // 16 bit timer 1 - CT16B1
    // PIO1_9 IS B
    LPC_IOCON->PIO1_9 |= 0x01;        // - set bit 0 to connect pin to CT16B1_MAT0
    LPC_IOCON->PIO1_9 &= ~(1 << 3);    // - clear bit 3 (and set 4: pull-up resistor)
    LPC_IOCON->PIO1_9 |= (1 << 4);    // - set bit 4

    // PIO1_10 IS D
    LPC_IOCON->PIO1_10 |= 0x02;        // - set bit 1 to connect pin to CT16B1_MAT1
    LPC_IOCON->PIO1_10 &= ~(1 << 3);// - clear bit 3 (and set 4: pull-up resistor)
    LPC_IOCON->PIO1_10 |= (1 << 4);// - set bit 4

    LPC_TMR16B0->MCR |= (1 << 10);// Reset TC counter when it reaches Match Register 3 value
    LPC_TMR16B1->MCR |= (1 << 10);// Reset TC counter when it reaches Match Register 3 value

    LPC_TMR16B0->EMR |= 0x000000F0;// Toggle output when a match occurs with MR0 and MR1
    LPC_TMR16B1->EMR |= 0x000000F0;// Toggle output when a match occurs with MR0 and MR1

    LPC_TMR16B0->MR0 = 2048;// A duty cycle - TMR16B0 Match register 0
    LPC_TMR16B0->MR1 = 2048;            // C duty cycle - TMR16B0 Match register 1
    LPC_TMR16B0->MR3 = 4096;            // Cycle length 4096 (= 17.8kHz) - Match register 3

    LPC_TMR16B1->MR0 = 2048;            // B duty cycle - TMR16B1 Match register 0
    LPC_TMR16B1->MR1 = 2048;            // D duty cycle - TMR16B1 Match register 1
    LPC_TMR16B1->MR3 = 4096;            // Cycle length 4096 (= 17.8kHz) - Match register 3

    LPC_TMR16B0->PWMC |= (1 << 0);      // A    Timer 0 MAT0 is PWM
    LPC_TMR16B0->PWMC |= (1 << 1);      // C    Timer 0 MAT1 is PWM
    LPC_TMR16B1->PWMC |= (1 << 0);      // B    Timer 1 MAT0 is PWM
    LPC_TMR16B1->PWMC |= (1 << 1);      // D    Timer 1 MAT1 is PWM

    LPC_GPIO0->DIR |= (1 << 8);        // - select OUTPUT
    LPC_GPIO0->DIR |= (1 << 9);        // - select OUTPUT
    LPC_GPIO1->DIR |= (1 << 9);        // - select OUTPUT
    LPC_GPIO1->DIR |= (1 << 10);        // - select OUTPUT

    LPC_TMR16B0->TCR = 1;    //enable timer 0
    LPC_TMR16B1->TCR = 1;    //enable timer 1

while(1){}
}
0 Kudos
8 Replies

263 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tinto on Mon Jan 16 01:55:54 MST 2012
Thanks a lot for your replies. Now everything works fine.
0 Kudos

263 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Sun Jan 15 01:17:21 MST 2012

Quote: tinto
But before that, can you please guide me how to create a new project in LPCXpresso?
...

Is this the right way? I am a very beginner. Please help me.



There is a very good "Getting Started" that is installed together with the LPCXpresso tools. After installation you even have to untick a box in order not to get it on your screen :eek:
I know ... I also always untick the "Open readme.txt" stuff that comes with installations...

This manual can be found in Window's start menu (all programs -. LPCXpresso v4.1.5_219 -> Help and Guides -> Getting Started
It explains how to start importing the examples, building them, debugging your code, creating a new workspace, creating a new project, how to recover your board if it stopped working and much more.

Believe it or not, I did read this manual even though I have a > 20 years profession in embedded software development.

Regards,[INDENT]Rob

-- if everything else fails, read the manual
[/INDENT]
0 Kudos

263 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Sun Jan 15 00:06:55 MST 2012
You should create a LPCXpresso project with CMSIS included. This should be done if you use project wizard:

File-> New -> Project: project wizard is opening

Select 'LPCXpresso C Project', Click Next

Select your project type: 'C project' or 'Semihosting C project', use semihosting to use console output, Click Next

Enter a project name, Click Next

Select your mcu, Click Next

Select options (let the wizard include CMSIS and CRP) and click Finish

Now your project wizard should create you a complete project, CMSIS included and ready to start :)

You can also find a few informative videos in section 'More Information-Literature' of

http://ics.nxp.com/lpcxpresso/
0 Kudos

263 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tinto on Sat Jan 14 23:14:28 MST 2012
Thank you very much for your replies. I will try your codes as well as my code. But before that, can you please guide me how to create a new project in LPCXpresso? I think that I am going some where wrong in the steps.
I used to create a new project in the following way.
File>New> Project>C project (C/C++)>Project Name>LPCXpresso empty C project>Select both Debug and Release>Select LPC1343>Finish. Now I add a folder to file named src and add the program.c file as well as the necessary header files to  the src folder. Then Build and Debug.
Is this the right way? I am a very beginner. Please help me.
0 Kudos

263 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by vasanth on Sat Jan 14 09:43:47 MST 2012
To Zero,

   Now we have a reference to [I]'I'm clean' [/I]code because of that [I]'I'm confused'[/I] code...:D
You must be kept in a seperate league in this forum. I would say "super senior member" is a good name for that category.


To NxP,

        /* Setup the external match register */
        LPC_TMR16B1->EMR = (1<<EMC3)|(1<<EMC2)|(1<<EMC1)|(2<<EMC0)|(1<<3)|(match_enable);
  This code is from an example provided by NxP for PWM (for LPC1100),
The  EMR register has been written needlessly as our "super senior member"  has pointed out. I wouldn't complain this as a serious problem, because this is another way to control the initial state of those MAT pins, but this  is a good way to confuse a beginner :confused: which includes myself...:eek:.

What we need in these examples is much more clearer
/* comments... */
/* comments... */
/* comments... */
0 Kudos

263 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Sat Jan 14 06:52:16 MST 2012
:mad: Forgotten #7 :mad:

#7: Switching PWM outputs continuously high or low can be done with MR register setting without stopping timer:

//switching PIO0_8 low/high/low/PWM(1kHz)
 i=0;while(i<100000){i++;}                //delay
 LPC_TMR16B0->MR0 =LPC_TMR16B0->MR3+1;  //match register > reset register => output low
 i=0;while(i<100000){i++;}                //delay
 LPC_TMR16B0->MR0 =0;                      //match register = 0 => output high
 i=0;while(i<100000){i++;}                //delay
 LPC_TMR16B0->MR0 =LPC_TMR16B0->MR3+1;  //match register > reset register => output low
 i=0;while(i<100000){i++;}                //delay
//reset counter to get full PWM cycle again, don't use this command
//if other MAT outputs of this timer are still working 
//LPC_TMR16B0->TC  = 0;                    //reset counter
 LPC_TMR16B0->MR0 =LPC_TMR16B0->MR3/4;  //valid match register again
0 Kudos

263 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Sat Jan 14 03:42:29 MST 2012
Although this code is running :eek:, I wouldn't go so far to say it's good. It's an[I] 'I'm confused'[/I] code :rolleyes:

#1: Setting direction for non GPIO-functions is nonsense, so don't try to set PWM outputs as GPIO outputs.

 LPC_GPIO0->DIR |= (1 << 8);            // - select OUTPUT
 LPC_GPIO0->DIR |= (1 << 9);            // - select OUTPUT
 LPC_GPIO1->DIR |= (1 << 9);            // - select OUTPUT
 LPC_GPIO1->DIR |= (1 << 10);        // - select OUTPUT
#2: If you enable PWM you don't need to care about setting/resetting PWM outputs, so EMC settings in EMR are useless:

 LPC_TMR16B0->EMR |= 0x000000F0;      // Toggle output when a match occurs with MR0 and MR1
 LPC_TMR16B1->EMR |= 0x000000F0;      // Toggle output when a match occurs with MR0 and MR1
#3: EMR can be used to force outputs high or low with EM0-EM3 bits as shown in sample below.

#4: To generate more readable code you should set/reset bits in blocks like function, mode...

//PIO0_8
 LPC_IOCON->PIO0_8 &= ~((1<<10)|(1<<5)|(3<<3)|(7<<0)); //reset func,mode,hys,OD
 LPC_IOCON->PIO0_8 |=  ((2<<3)|(2<<0));                   //set CT16B0 MAT0, pullup
#5: Prescale Counter register is also helping to generate more readable code. Just use it as divider.

//set prescaler
 LPC_TMR16B0->PR  = 71;                    //prescaler:72 -> time base: 1/1MHz = 1µs
#6: If this sample isn't running you're not using a standard LPCXpresso project and should check basic settings like IOCON clock...

int main(void)
{
 volatile unsigned int i;
 printf("PWM16 Sample\n");
//Init PWM
 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7);        //enables clock for 16-bit counter/timer 0
 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8);        //enables clock for 16-bit counter/timer 1
//PIO0_8
 LPC_IOCON->PIO0_8 &= ~((1<<10)|(1<<5)|(3<<3)|(7<<0)); //reset func,mode,hys,OD
 LPC_IOCON->PIO0_8 |=  ((2<<3)|(2<<0));                   //set CT16B0 MAT0, pullup
//PIO0_9
 LPC_IOCON->PIO0_9 &= ~((1<<10)|(1<<5)|(3<<3)|(7<<0)); //reset func,mode,hys,OD
 LPC_IOCON->PIO0_9 |=  ((2<<3)|(2<<0));                   //set CT16B0 MAT1, pullup
//PIO1_9
 LPC_IOCON->PIO1_9 &= ~((1<<10)|(1<<5)|(3<<3)|(7<<0)); //reset func,mode,hys,OD
 LPC_IOCON->PIO1_9 |=  ((2<<3)|(1<<0));                   //set CT16B1 MAT0, pullup
//PIO1_10
 LPC_IOCON->PIO1_10 &= ~((1<<10)|(1<<7)|(1<<5)|(3<<3)|(7<<0)); //reset func,mode,hys,admode,OD
 LPC_IOCON->PIO1_10 |=  ((1<<7)|(2<<3)|(2<<0));                //set CT16B1 MAT1, pullup, digital

//set match / interrupts
 LPC_TMR16B0->MCR = (1 << 10);            //MR3 reset, no interrupts
 LPC_TMR16B1->MCR = (1 << 10);            //MR3 reset, no interrupts

//set prescaler
 LPC_TMR16B0->PR  = 71;                    //prescaler:72 -> time base: 1/1MHz = 1µs
 LPC_TMR16B1->PR  = 71;                    //prescaler:72 -> time base: 1/1MHz = 1µs

 LPC_TMR16B0->MR3 = 1000;                //cycle: 1000µs = 1kHz
 LPC_TMR16B0->MR0 = LPC_TMR16B0->MR3/4;    //MAT0 1/4 low, 3/4 high
 LPC_TMR16B0->MR1 = LPC_TMR16B0->MR3/2;    //MAT1 1/2 low, 1/2 high

 LPC_TMR16B1->MR3 = 500;                //cycle: 500µs = 2kHz
 LPC_TMR16B1->MR0 = LPC_TMR16B1->MR3/4;    //MAT0 1/4 low, 3/4 high
 LPC_TMR16B1->MR1 = LPC_TMR16B1->MR3/2;    //MAT1 1/2 low, 1/2 high

 LPC_TMR16B0->PWMC = ((1<<0)|(1<<1));    //enable PMM MAT0/MAT1
 LPC_TMR16B1->PWMC = ((1<<0)|(1<<1));    //enable PMM MAT0/MAT1

 LPC_TMR16B0->TCR = 1;                    //start timer 0
 LPC_TMR16B1->TCR = 1;                    //start timer 1

 while(1)
 {
//switching PIO0_8 low/high/low/PWM(1kHz)
  i=0;while(i<100000){i++;}                //delay

  LPC_TMR16B0->TCR = 0;                    //stop timer 0
  LPC_TMR16B0->EMR &=~(1<<0);            //force CT16B0 MAT0 low

  i=0;while(i<100000){i++;}                //delay

  LPC_TMR16B0->EMR |= (1<<0);            //force CT16B0 MAT0 high

  i=0;while(i<100000){i++;}                //delay

  LPC_TMR16B0->EMR &=~(1<<0);            //force CT16B0 MAT0 low

  i=0;while(i<100000){i++;}                //delay

  LPC_TMR16B0->TC  = 0;                    //reset counter
  LPC_TMR16B0->TCR = 1;                    //start timer 0
 }
 return 0 ;
}
0 Kudos

263 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by vasanth on Fri Jan 13 22:47:05 MST 2012

Quote: tinto
I am not getting any PWM at the output pins. The output is always high. What is the problem with this code?



If my eye is good, my scope shows PWM with your code running on my board.... :)
0 Kudos