Fong PWM Blinky v0.1

Fong PWM Blinky Function v0.1 tlfong 2013aug08

// Set function of PIO0_8 pin as CT16B0_MAT_0 (Somy Board P4 pin 3)

LPC_IOCON->PIO0_8 &= ~0x3; // set bits 2:0 to 0b00 (0x0);
LPC_IOCON->PIO0_8 |= ~0x2; // set bits 2:0 to 0b10 (0x2); 

// Enable clock for CT16B0 timer
LPC_SYSCON ->SYSAHBCLKCTRL |= (1 << 7); // Enable Clock for CT16B0

// Set PWM mode for CT16B0_MAT0.
LPC_TMR16B0 ->PWMC |= (1 << 0); // bit 0 = 1 for CT16B0_MAT0 PWM (ie, not by EMR)

// Resets timer counter on a match
LPC_TMR16B0 ->MCR |= (1 << 1); // timer counter reset on match

// Set prescale 12000 count of AHB clock  = 120 uS
LPC_TMR16B0 ->PR = 12000; // (1/(50,000,000/2) x 12000 = 120 uS

// Set cycle length 120uS x 4000 = 0.96 == 1 second
LPC_TMR16B0 ->MR3 = 4000; // cycle length = 1 second

// Set duty cycle 240uS x 2000 = 1 second
LPC_TMR16B0 ->MR0 = 2000; // 0.5 sec = 50% duty cycle

// Start timer
LPC_TMR16B0 ->TCR |= (1 << 0); // enable/start timer



*** ARM Cortex M0 LPC1114FBD48/302 PWM Design Notes v1.0 tlfong01 2013aug08 ***.  

0. Introduction

This is the design notes of using PWM to blink a LED.  


1. Selecting PIO0_8 pin for PWM

The pin to use is Pin 27, PIO0_8/MISO0/CT16B0_MAT0.


2. Setting PIO0_8 for 16 bit timer match register output (CT16B0_MAT0)

LPC11xx.h v1.1 2012nov24 uses the following struct for IO control/data registers.  

typedef struct
{
...
__IO uint32_t PIO0_8;  /*!< Offset: 0x060 (R/W) I/O con for pin PIO0_8/MISO0/CT16B0_MAT0 */
...
} LPC_IOCON_TypeDef;

LPC111x/LPC11Cxx User manual UM10398 Rev12 2012sep24 Table 79 says that bits 2:0 of the IOCON_PIO0_8 register selects the pin function.

IOCON_PIO0_8 register (IOCON_PIO0_8, address 0x4004 4060)

2:0 FUNC Selects pin function. All other values are reserved. 000

0x0 Selects function PIO0_8.
0x1 Selects function MISO0.
0x2 Selects function CT16B0_MAT0.

I will use PIO0_8 as CT16B0_MAT_0.  So I will use the following 2 statements to set IOCON_PIO0_8 bits 2:0 to 0x2.

***** LPC_IOCON->PIO0_8 &= ~0x3; // set bits 2:0 to 0b00 (0x0);
***** LPC_IOCON->PIO0_8 |= ~0x2; // set bits 2:0 to 0b10 (0x2);  


3. Enabling clock for 16 bit Timer/Counter 0.

LPC11xx.h uses the following struct for clock control. 

typedef struct
{
...
  __IO uint32_t MAINCLKSEL; /*!< Offset: 0x070 (R/W)  Main clock source select Register */
  __IO uint32_t MAINCLKUEN; /*!< Offset: 0x074 (R/W)  Main clock source update enable */
  __IO uint32_t SYSAHBCLKDIV; /*!< Offset: 0x078 (R/W)  System AHB clock divider Register */
...
  __IO uint32_t SYSAHBCLKCTRL; /*!< Offset: 0x080 (R/W)  System AHB clock control Register */
...
} LPC_SYSCON_TypeDef;


UM10398  Table 21. System AHB clock control register (SYSAHBCLKCTRL, address 0x4004 8080) 

... 

bit 6 GPIO Enables clock for GPIO. reset value = 1
0 Disable
1 Enable

bit 7 CT16B0 Enables clock for 16-bit counter/timer 0. reset value = 0
0 Disable
1 Enable

bit 8 CT16B1 Enables clock for 16-bit counter/timer 1. reset value = 0
0 Disable
1 Enable

bit 9 CT32B0 Enables clock for 32-bit counter/timer 0. reset value = 0
0 Disable
1 Enable

bit 10 CT32B1 Enables clock for 32-bit counter/timer 1. reset value = 0
0 Disable

1 Enable

So I will enable timer CT16B0 by setting bit 7 by the following statement.


***** LPC_SYSCON ->SYSAHBCLKCTRL |= (1 << 7); // Enable Clock for CT16B0


4.  This section timer structure in lpc11xx.h and registers in UM10398

LPC11xx.h has the following struct definition and declaration for timers (and GPIO).

typedef struct
{
  __IO uint32_t IR;             /*!< Offset: 0x000 (R/W)  Interrupt Register */
  __IO uint32_t TCR;            /*!< Offset: 0x004 (R/W)  Timer Control Register */
  __IO uint32_t TC;             /*!< Offset: 0x008 (R/W)  Timer Counter Register */
  __IO uint32_t PR;             /*!< Offset: 0x00C (R/W)  Prescale Register */
  __IO uint32_t PC;             /*!< Offset: 0x010 (R/W)  Prescale Counter Register */
  __IO uint32_t MCR;            /*!< Offset: 0x014 (R/W)  Match Control Register */

  __IO uint32_t MR0;            /*!< Offset: 0x018 (R/W)  Match Register 0 */
  __IO uint32_t MR1;            /*!< Offset: 0x01C (R/W)  Match Register 1 */
  __IO uint32_t MR2;            /*!< Offset: 0x020 (R/W)  Match Register 2 */
  __IO uint32_t MR3;            /*!< Offset: 0x024 (R/W)  Match Register 3 */
  
  __IO uint32_t CCR;            /*!< Offset: 0x028 (R/W)  Capture Control Register */
  __I  uint32_t CR0;            /*!< Offset: 0x02C (R/ )  Capture Register 0 */
  __IO uint32_t EMR;            /*!< Offset: 0x03C (R/W)  External Match Register */
  __IO uint32_t CTCR;           /*!< Offset: 0x070 (R/W)  Count Control Register */
  __IO uint32_t PWMC;           /*!< Offset: 0x074 (R/W)  PWM Control Register */
} LPC_TMR_TypeDef;

/* Peripheral declaration */
...

#define LPC_TMR16B0           ((LPC_TMR_TypeDef    *) LPC_CT16B0_BASE)
#define LPC_TMR16B1           ((LPC_TMR_TypeDef    *) LPC_CT16B1_BASE)
#define LPC_TMR32B0           ((LPC_TMR_TypeDef    *) LPC_CT32B0_BASE)
#define LPC_TMR32B1           ((LPC_TMR_TypeDef    *) LPC_CT32B1_BASE)

#define LPC_IOCON             ((LPC_IOCON_TypeDef  *) LPC_IOCON_BASE )
#define LPC_SYSCON            ((LPC_SYSCON_TypeDef *) LPC_SYSCON_BASE)

#define LPC_GPIO0             ((LPC_GPIO_TypeDef   *) LPC_GPIO0_BASE )
#define LPC_GPIO1             ((LPC_GPIO_TypeDef   *) LPC_GPIO1_BASE )
#define LPC_GPIO2             ((LPC_GPIO_TypeDef   *) LPC_GPIO2_BASE )

#define LPC_GPIO3             ((LPC_GPIO_TypeDef   *) LPC_GPIO3_BASE )

... 

/*  Peripheral memory map */

/* Base addresses */
#define LPC_FLASH_BASE        (0x00000000UL)
#define LPC_RAM_BASE          (0x10000000UL)
#define LPC_APB0_BASE         (0x40000000UL)
#define LPC_AHB_BASE          (0x50000000UL)

/* APB0 peripherals */

#define LPC_CT16B0_BASE       (LPC_APB0_BASE + 0x0C000)
#define LPC_CT16B1_BASE       (LPC_APB0_BASE + 0x10000)
#define LPC_CT32B0_BASE       (LPC_APB0_BASE + 0x14000)
#define LPC_CT32B1_BASE       (LPC_APB0_BASE + 0x18000)

/* AHB peripherals */

#define LPC_GPIO_BASE         (LPC_AHB_BASE  + 0x00000)
#define LPC_GPIO0_BASE        (LPC_AHB_BASE  + 0x00000)
#define LPC_GPIO1_BASE        (LPC_AHB_BASE  + 0x10000)
#define LPC_GPIO2_BASE        (LPC_AHB_BASE  + 0x20000)

#define LPC_GPIO3_BASE        (LPC_AHB_BASE  + 0x30000)


5. To set PWM mode for CT16B0_MAT0.

UM10398 18.7.12 PWM Control register (TMR16B0PWMC and TMR16B1PWMC) syas the following.

The PWM Control Register is used to configure the match outputs as PWM outputs. Each match output can be independently set to perform either as PWM output or as match output whose function is controlled by the External Match Register (EMR).

For timer 0, three single-edge controlled PWM outputs can be selected on the CT16B0_MAT[2:0] outputs. 

For timer 1, two single-edged PWM outputs can be selected on the CT16B1_Mat[1:0] outputs. 

One additional match register determines the PWM cycle length. 

When a match occurs in any of the other match registers, the PWM output is set to HIGH. 

The timer is reset by the match register that is configured to set the PWM cycle length. When the timer is reset to zero, all currently HIGH 
match outputs configured as PWM outputs are cleared.

Table 293. PWM Control Register (TMR16B0PWMC - address 0x4000 C074 and
TMR16B1PWMC- address 0x4001 0074) 

bit 0 PWMEN0 PWM channel0 enable reset value = 0

0 CT16Bn_MAT0 is controlled by EM0.
1 PWM mode is enabled for CT16Bn_MAT0.

So the following statement will set PWM mode for CT16B0_MAT0.

***** LPC_TMR16B0 ->PWMC |= (1 << 0); // bit 0 = 1 for CT16B0_MAT0 PWM (ie, not by EMR)


6. To enable/start timer 

UM10398 18.7.2 Timer Control Register (TMR16B0TCR and TMR16B1TCR) says the following.

The Timer Control Register (TCR) is used to control the operation of the counter/timer.

Table 282. Timer Control Register (TMR16B0TCR - address 0x4000 C004 and TMR16B1TCR - address 0x4001 0004) 

0 CEn Counter Enable. When one, the Timer Counter and Prescale Counter are enabled for counting. When zero, the counters are disabled. reset 
= 0

1 CRst Counter Reset. When one, the Timer Counter and the Prescale Counter are synchronously reset on the next positive edge of PCLK. The 
counters remain reset until TCR[1] is returned to zero. reset = 0

So the following statement enables/starts the timer.

***** LPC_TMR16B0 ->TCR |= (1 << 0); // enable/start timer


7. Resetting timer counter on match

UM10398 18.7.6 Match Control Register (TMR16B0MCR and TMR16B1MCR)

The Match Control Register is used to control what operations are performed when one of
the Match Registers matches the Timer Counter. The function of each of the bits is shown
in Table 286.

Table 286. Match Control Register (TMR16B0MCR - address 0x4000 C014 and TMR16B1MCR - address 0x4001 0014)

bit 0 MR0I Interrupt on MR0: an interrupt is generated when MR0 matches the value in the TC. reset value = 0
1 Enabled
0 Disabled

bit 1 MR0R Reset on MR0: the TC will be reset if MR0 matches it. reset value = 0
1 Enabled
0 Disabled

bit 2 MR0S Stop on MR0: the TC and PC will be stopped and TCR[0] will be set to 0 if MR0 matches
the TC. reset value = 0
1 Enabled
0 Disabled

bit 3 MR1I Interrupt on MR1: an interrupt is generated when MR1 matches the value in the TC. reset value = 0
1 Enabled
0 Disabled

...

The following statement resets timer counter on a match.

***** LPC_TMR16B0 ->MCR |= (1 << 1); // timer counter reset on match


8. Setting prescale register

***** LPC_TMR16B0 ->PR = 12000;


9. Setting cycle length and duty cycle

UM10398 18.7.12 PWM Control register (TMR16B0PWMC and TMR16B1PWMC)

The PWM Control Register is used to configure the match outputs as PWM outputs. Each
match output can be independently set to perform either as PWM output or as match
output whose function is controlled by the External Match Register (EMR).

For timer 0, three single-edge controlled PWM outputs can be selected on the
CT16B0_MAT[2:0] outputs. 

For timer 1, two single-edged PWM outputs can be selected on the CT16B1_Mat[1:0] outputs. 
One additional match register determines the PWM cycle length. When a match occurs in 
any of the other match registers, the PWM output is set to HIGH. The timer is reset 
by the match register that is configured to set the PWM cycle length. When the timer 
is reset to zero, all currently HIGH match outputs configured as PWM outputs are cleared.

18.5 Description

In PWM mode, three match registers on CT16B0 and two match registers on CT16B1 can
be used to provide a single-edge controlled PWM output on the match output pins. 

It is recommended to use the match registers that are not pinned out to control 
the  PWM cycle length.

***** LPC_TMR16B0 ->MR3 = 4000; // Match Register 3 for cycle length
***** LPC_TMR16B0 ->MR0 = 2000; // Match Register 0 for 50% Duty Cycle


10. The PWM Blinky Function v0.1

// Set function of PIO0_8 pin as CT16B0_MAT_0 

LPC_IOCON->PIO0_8 &= ~0x3; // set bits 2:0 to 0b00 (0x0);
LPC_IOCON->PIO0_8 |= ~0x2; // set bits 2:0 to 0b10 (0x2); 

// Enable clock for CT16B0 timer
LPC_SYSCON ->SYSAHBCLKCTRL |= (1 << 7); // Enable Clock for CT16B0

// Set PWM mode for CT16B0_MAT0.
LPC_TMR16B0 ->PWMC |= (1 << 0); // bit 0 = 1 for CT16B0_MAT0 PWM (ie, not by EMR)

// Resets timer counter on a match
LPC_TMR16B0 ->MCR |= (1 << 1); // timer counter reset on match

// Set prescale 12000 count of AHB clock  = 120 uS
LPC_TMR16B0 ->PR = 12000; // (1/(50,000,000/2) x 12000 = 120 uS

// Set cycle length 120uS x 4000 = 0.96 == 1 second
LPC_TMR16B0 ->MR3 = 4000; // cycle length = 1 second

// Set duty cycle 240uS x 2000 = 1 second
LPC_TMR16B0 ->MR0 = 2000; // 0.5 sec = 50% duty cycle

// Start timer
LPC_TMR16B0 ->TCR |= (1 << 0); // enable/start timer

.END

No comments:

Post a Comment