Generate 2 PWM from 1 timer

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

Generate 2 PWM from 1 timer

2,131 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tyassin on Fri May 17 05:45:58 MST 2013
Hello,

I want to generate two PWM signals from one timer. I have tried to use Timer0, but nothing happens.
I use the LPC1114 Xpressoboard. I have attached my code.

LPC_TMR16B0->TCR = 0; //Disable Timer0
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7); // System AHB clock control enable clock to timer 0 : 3.5.14
LPC_TMR16B0->EMR = (1<<0)|(1<<1)|(1<<3)|(1<<5)|(1<<7)|(1<<10); // Setup the external match register (1<<0 : EM0 connected to pin) : 18.7.10 External Match Register
// 1<<5 : Set the corresponding External Match bit/output to 1
// 1<<10 : Clear the corresponding External Match bit/output to 0 (CT16Bn_MATm pin is LOW if pinned out : (1<<3).

LPC_IOCON->PIO0_8 &= ~0x07; // Clears the FUNC bits : 8.4.23 IOCON_PIO0_8
LPC_IOCON->PIO0_8 |= 0x02; // Selects function CT16B0_MAT0. PIO0_8/MISO0/CT16B0_MAT0
LPC_IOCON->PIO0_9 &= ~0x07; // Clears the FUNC bits : 8.4.24 IOCON_PIO0_9
LPC_IOCON->PIO0_9 |= 0x02; // Selects function CT16B0_MAT1. PIO0_9/MOSI0/CT16B0_MAT1
// These are compared against the TC ( Timer Counter )
LPC_TMR16B0->MR3 = 1000; // Setup the match registers
LPC_TMR16B0->MR0 = 500; // Match Register 0 - stay low
LPC_TMR16B0->MR1 = 500;
LPC_TMR16B0->MCR = 1<<10; // OK : Match Control Register : 1<<10 = Reset on MR3
// If needed : 1<<9 = Interrupt on MR3: an interrupt is generated when MR3 matches the value in the TC.
LPC_TMR16B0->PWMC = 0b1011; // OK : PWM Control Register to enable the selected PWMs
// 0x01 : PWM mode is enabled for CT16Bn_MAT0
// 0x02 : PWM mode is enabled for CT16Bn_MAT1
// 0x08 : PWM mode is enabled for match channel 3

NVIC_EnableIRQ(TIMER_16_0_IRQn); // Enable the TIMER1 Interrupt
LPC_TMR16B0->TCR = 1; // Enable Timer16
Both GPIO0_8 and GPIO0_9 are high all the time.

If someone could see where it goes wrong i would be happy

Thank you
0 Kudos
Reply
10 Replies

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by alemmat on Thu Mar 31 20:20:20 MST 2016
Hello R2D2

Thanks very much to post this code for me is very usefull

my best regards
0 Kudos
Reply

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Tue May 21 02:49:18 MST 2013
UM10398 should describe CT16B0, what's not clear there?
0 Kudos
Reply

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tyassin on Tue May 21 00:36:10 MST 2013
Hello again,

Thank you very much for the help.
I found my mistake which was as you suggested somewhere else in my code. There was some code that put PIO_8 and PIO_9 as regular outputs, that was why nothing happened.
One more question, is it possible to generate three PWM with CT16B0?

Regards
0 Kudos
Reply

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri May 17 10:08:43 MST 2013

Quote: tyassin
Another thing. What is your system clock frequency...


48MHz

Quote: tyassin
...and where is that set-up in your code?


Nowhere

It's a Standard LPCXpresso project with CMSIS. So cr_startup_lpc11.c (in project->src folder) is using:
...
#ifdef __USE_CMSIS
  [COLOR=RoyalBlue]  SystemInit();[/COLOR]
#endif
...
This SystemInit() is part of CMSIS and can be found in system_LPC11xx.c of CMSISv2p00_LPC11xx/src (via F3 = 'Open declaration'):

/**
 * Initialize the system
 *
 * @param  none
 * @return none
 *
 * @brief  Setup the microcontroller system.
 *         Initialize the System.
 */
[COLOR=RoyalBlue]void SystemInit (void)[/COLOR]
{
#if (CLOCK_SETUP)                                 /* Clock Setup              */
#if (SYSCLK_SETUP)                                /* System Clock Setup       */
#if (SYSOSC_SETUP)                                /* System Oscillator Setup  */
  uint32_t i;
  LPC_SYSCON->PDRUNCFG     &= ~(1 << 5);          /* Power-up System Osc      */
  LPC_SYSCON->SYSOSCCTRL    = SYSOSCCTRL_Val;
  for (i = 0; i < 200; i++) __NOP();
  LPC_SYSCON->SYSPLLCLKSEL  = SYSPLLCLKSEL_Val;   /* Select PLL Input         */
  LPC_SYSCON->SYSPLLCLKUEN  = 0x01;               /* Update Clock Source      */
  LPC_SYSCON->SYSPLLCLKUEN  = 0x00;               /* Toggle Update Register   */
  LPC_SYSCON->SYSPLLCLKUEN  = 0x01;
  while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01));     /* Wait Until Updated       */
#if (SYSPLL_SETUP)
 /* System PLL Setup         */
  LPC_SYSCON->SYSPLLCTRL    = SYSPLLCTRL_Val;
  LPC_SYSCON->PDRUNCFG     &= ~(1 << 7);          /* Power-up SYSPLL          */
  while (!(LPC_SYSCON->SYSPLLSTAT & 0x01));          /* Wait Until PLL Locked    */
#endif
#endif
#if (WDTOSC_SETUP)                                /* Watchdog Oscillator Setup*/
  LPC_SYSCON->WDTOSCCTRL    = WDTOSCCTRL_Val;
  LPC_SYSCON->PDRUNCFG     &= ~(1 << 6);          /* Power-up WDT Clock       */
#endif
  LPC_SYSCON->MAINCLKSEL    = MAINCLKSEL_Val;     /* Select PLL Clock Output  */
  LPC_SYSCON->MAINCLKUEN    = 0x01;               /* Update MCLK Clock Source */
  LPC_SYSCON->MAINCLKUEN    = 0x00;               /* Toggle Update Register   */
  LPC_SYSCON->MAINCLKUEN    = 0x01;
  while (!(LPC_SYSCON->MAINCLKUEN & 0x01));       /* Wait Until Updated       */
#endif

  LPC_SYSCON->SYSAHBCLKDIV  = SYSAHBCLKDIV_Val;
  [COLOR=Red]LPC_SYSCON->SYSAHBCLKCTRL = AHBCLKCTRL_Val;[/COLOR]
  LPC_SYSCON->SSP0CLKDIV    = SSP0CLKDIV_Val;
  LPC_SYSCON->UARTCLKDIV    = UARTCLKDIV_Val;
  LPC_SYSCON->SSP1CLKDIV    = SSP1CLKDIV_Val;
#endif
There's also your SYSAHBCLKCTRL setup
0 Kudos
Reply

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tyassin on Fri May 17 09:45:26 MST 2013
OK excellent. As you say there must be a problem in my project somewhere.
Thank you for the help, I will look into it.
Another thing. What is your system clock frequency and where is that set-up in your code?
As you have guessed I am quite new to the LPC world ;-)
0 Kudos
Reply

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri May 17 09:35:20 MST 2013

Quote: tyassin
OK just to make it clear for me. You have used my code and you can generate the two PWM signals on PIO_8 and PIO_9 with different duty cycle?



Exact. Wasn't that the purpose?

/*
===============================================================================
 Name        : main.c
 Author      : 
 Version     :
 Copyright   : Copyright (C) 
 Description : main definition
===============================================================================
*/

#ifdef __USE_CMSIS
#include "LPC11xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

int main(void)
{
 volatile static int i = 0 ;

 LPC_TMR16B0->TCR = 0; //Disable Timer0
 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7); // System AHB clock control enable clock to timer 0 : 3.5.14
 LPC_TMR16B0->EMR = (1<<0)|(1<<1)|(1<<3)|(1<<5)|(1<<7)|(1<<10); // Setup the external match register (1<<0 : EM0 connected to pin) : 18.7.10 External Match Register
 // 1<<5 : Set the corresponding External Match bit/output to 1
 // 1<<10 : Clear the corresponding External Match bit/output to 0 (CT16Bn_MATm pin is LOW if pinned out : (1<<3).

 LPC_IOCON->PIO0_8 &= ~0x07; // Clears the FUNC bits : 8.4.23 IOCON_PIO0_8
 LPC_IOCON->PIO0_8 |= 0x02; // Selects function CT16B0_MAT0. PIO0_8/MISO0/CT16B0_MAT0
 LPC_IOCON->PIO0_9 &= ~0x07; // Clears the FUNC bits : 8.4.24 IOCON_PIO0_9
 LPC_IOCON->PIO0_9 |= 0x02; // Selects function CT16B0_MAT1. PIO0_9/MOSI0/CT16B0_MAT1
 // These are compared against the TC ( Timer Counter )
[COLOR=Red] LPC_TMR16B0->MR3 = 1000-1; // Setup the match registers
 LPC_TMR16B0->MR0 = 500; // Match Register 0 - stay low
 LPC_TMR16B0->MR1 = 250;[/COLOR]
 LPC_TMR16B0->MCR = 1<<10; // OK : Match Control Register : 1<<10 = Reset on MR3
 // If needed : 1<<9 = Interrupt on MR3: an interrupt is generated when MR3 matches the value in the TC.
 LPC_TMR16B0->PWMC = 0b1011; // OK : PWM Control Register to enable the selected PWMs
 // 0x01 : PWM mode is enabled for CT16Bn_MAT0
 // 0x02 : PWM mode is enabled for CT16Bn_MAT1
 // 0x08 : PWM mode is enabled for match channel 3

 NVIC_EnableIRQ(TIMER_16_0_IRQn); // Enable the TIMER1 Interrupt
 LPC_TMR16B0->TCR = 1; // Enable Timer16

 while(1)
 {
  i++;
 }
 return 0 ;
}
Result: 48kHz with 50% ON and 75% ON (Board: LPCXpresso1114 /302)
0 Kudos
Reply

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tyassin on Fri May 17 09:23:38 MST 2013
OK just to make it clear for me. You have used my code and you can generate the two PWM signals on PIO_8 and PIO_9 with different duty cycle?

Regards
0 Kudos
Reply

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri May 17 08:27:46 MST 2013
Included in a Standard LPCXpresso LPC1114 project (48MHz) it's working fine here

I've changed:
LPC_TMR16B0->MR3 = 1000; 
to
LPC_TMR16B0->MR3 = 1000[COLOR=Red] -1[/COLOR]; 
to get a nice 48kHz signal and my scope is confirming this...
0 Kudos
Reply

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tyassin on Fri May 17 07:56:37 MST 2013
OK thanks I will check it out and be back.
You are right about posting the complete code....:-)
0 Kudos
Reply

2,081 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri May 17 06:16:20 MST 2013
Your code looks correct. Probably that's a 'project error' (Therefore it's useful to post complete projects).

My first guess would be a forgotten IOCON bit in SYSAHBCLKCTRL.
0 Kudos
Reply