decoding pwm input

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

decoding pwm input

2,734 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by miccio on Thu Sep 03 15:47:13 MST 2015
Hello everyone,

I have a sensor that outputs a PWM signal of approximately 250 Hz frequency (1us resolution so 12 bits) and I would like to read its output but I am unsure on which peripheral I should use and how. Any suggestion or code example?
I recently moved to the LPC15 series and I'm currently developing on the LPCXpresso1549 board.

Thanks in advance :)
Labels (1)
0 Kudos
18 Replies

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by cgroen on Sat Apr 02 02:14:07 MST 2016
Well, after a good nights sleep, I think I nailed it
I know that there are possibly many other (and perhaps smarter) ways of doing this, but as a first try at convincing the SCT to behave I think it is ok.
Please feel free to give some input on the code. I have only implemented the 3 PWM inputs in the code, I need to implement the 4th using SCT2 but copied the code here before that (and also failsafe detection) so there would be less clutter...

Basically I have defined 6 events, event 0,1 and 2 detects (and captures) rising edge on the 3 inputs. Event 3,4 and 5 detects (and captures) falling edge on the 3 inputs, and also generates an interrupt.
In this interrupt, I simply subtract the capture value from the rising edge with the value from the falling edge (and corrects for counter wrap-around).


//=============================================================================
// PWMIn.c                                                         20160401 CHG
//
//=============================================================================
// 
//-----------------------------------------------------------------------------
#include "chip.h"
#include "System.h"
#include "PWMIn.h"

#define TIMOUT_PWM_DETECTED 10 // Number of 10 mSec ticks where PWM must be seen before channel is set to "failsafe"


int capture[4];// PWM value in uSec
// Status for each channel, set to TRUE if channel in failsafe (no signal detected, or signal out of bounds)
static int inFailsafe[4]= {FALSE, FALSE, FALSE, FALSE};
// Timers for each PWM input, if decremented to 0, channel is in failsafe (no signal detected)
static int pwmInChange[4]={TIMOUT_PWM_DETECTED, TIMOUT_PWM_DETECTED, TIMOUT_PWM_DETECTED, TIMOUT_PWM_DETECTED};

//---------------------------------------------------------------------------------------
// 
//---------------------------------------------------------------------------------------
int getFailsafePWMIn(int channel) {
  return inFailsafe[channel-1];
}


//---------------------------------------------------------------------------------------
// Get PWM value for servo input (in uSec)
//---------------------------------------------------------------------------------------
int getValuePWMIn(int channel) {
  if (getFailsafePWMIn(channel))
  return 1520;
  return capture[channel-1];
}


/*
    for (int i=0; i<4; i++) {
      if (pwmInChange) {
        pwmInChange--;
        if (pwmInChange==0) {
          inFailsafe=TRUE;
          inuSec=0;
        }
      }
*/

//---------------------------------------------------------------------------------------
// Interrupt handler for SCT3 events. 
// We catch event 3,4 and 5. These occurs when SCT detects a falling edge on PWM1, PWM2 or PWM3
// Event 0,1 and 2 are rising edge on the 3 PWM inputs. We don't get an interrupt on these events 
// as they only copy the current counter value to CAP[0/1/2] when rising edge occurs
//---------------------------------------------------------------------------------------
void SCT3_IRQHandler(void) {
// PWM 1 falling
if(LPC_SCT3->EVFLAG & SCT_EVT_3) {
// If we have a wraparound on the counter between the rising and falling edge detection, correct the value
if (LPC_SCT3->CAP[3].U < LPC_SCT3->CAP[0].U)
capture[0]=0xFFFFFFFF + LPC_SCT3->CAP[3].U - LPC_SCT3->CAP[0].U;
else
capture[0] = LPC_SCT3->CAP[3].U- LPC_SCT3->CAP[0].U;
// Set timeout for change detected
pwmInChange[0]=TIMOUT_PWM_DETECTED;
LPC_SCT3->EVFLAG = SCT_EVT_3;
}
// PWM 2 falling
if(LPC_SCT3->EVFLAG & SCT_EVT_4) {
// If we have a wraparound on the counter between the rising and falling edge detection, correct the value
if (LPC_SCT3->CAP[3].U < LPC_SCT3->CAP[0].U)
capture[1]=0xFFFFFFFF + LPC_SCT3->CAP[4].U - LPC_SCT3->CAP[1].U;
else
capture[1] = LPC_SCT3->CAP[4].U- LPC_SCT3->CAP[1].U;
// Set timeout for change detected
pwmInChange[1]=TIMOUT_PWM_DETECTED;
LPC_SCT3->EVFLAG = SCT_EVT_4;
}
// PWM 3 falling
if(LPC_SCT3->EVFLAG & SCT_EVT_5) {
// If we have a wraparound on the counter between the rising and falling edge detection, correct the value
if (LPC_SCT3->CAP[5].U < LPC_SCT3->CAP[2].U)
capture[2]=0xFFFFFFFF + LPC_SCT3->CAP[5].U - LPC_SCT3->CAP[2].U;
else
capture[2] = LPC_SCT3->CAP[5].U- LPC_SCT3->CAP[2].U;
// Set timeout for change detected
pwmInChange[2]=TIMOUT_PWM_DETECTED;
LPC_SCT3->EVFLAG = SCT_EVT_5;
}
}

//---------------------------------------------------------------------------------------
// Initialize PWMIn module
//---------------------------------------------------------------------------------------
void initPWMIn(void) {

// Input capture on SCT3/SCT2:
// P0.07=PWMIN1 (SCT3)
// P1.11=PWMIN2 (SCT3)
// P1.21=PWMIN3 (SCT3)
// P1.19=PWMIN4 (SCT2)

// Enable pulldown on all 4 PWM inputs
Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 7, (IOCON_MODE_PULLDOWN));
Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 11, (IOCON_MODE_PULLDOWN));
Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 21, (IOCON_MODE_PULLDOWN));
Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 19, (IOCON_MODE_PULLDOWN));

Chip_SCT_Init(LPC_SCT3);

//unified 32bit counter, SYNC all inputs, enable prescaler in CTRL register
LPC_SCT3->CONFIG =  SCT_CONFIG_32BIT_COUNTER | (1<<9) | (1<<10) | (1<<11);
//set prescaler 72 to count µs
Chip_SCT_SetControl(LPC_SCT3, SCT_CTRL_PRE_L(72-1));

//input capture setting
LPC_INMUX->SCT3_INMUX[0] = 0;// SCT3_IN0 = P0.07
LPC_INMUX->SCT3_INMUX[1] = 1;// SCT3_IN1 = P1.11
LPC_INMUX->SCT3_INMUX[2] = 2;// SCT3_IN2 = P1.21

LPC_SCT3->REGMODE  = (SCT_EVT_0)| (SCT_EVT_1) | (SCT_EVT_2)| (SCT_EVT_3)| (SCT_EVT_4)| (SCT_EVT_5);//set capture register(s)
// Set event for each capture register
// Rising capture:
LPC_SCT3->CAPCTRL[0].U  = (SCT_EVT_0);
LPC_SCT3->CAPCTRL[1].U  = (SCT_EVT_1);
LPC_SCT3->CAPCTRL[2].U  = (SCT_EVT_2);

// Falling capture:
LPC_SCT3->CAPCTRL[3].U  = (SCT_EVT_3);
LPC_SCT3->CAPCTRL[4].U  = (SCT_EVT_4);
LPC_SCT3->CAPCTRL[5].U  = (SCT_EVT_5);

//---------------------------------------------------------------------------------------
// Define 6 events for the 3 inputs. 
// Event 0,1 and 2 are for the rising edge on each input
//  When one of these events occurs, SCT will store the current counter value in the CAP[0/1/2] regsiter
// Event 4,5 and 6 are for the falling edge on each input
//  When one of these events occurs, SCT will store the current counter value in the CAP[3/4/5] regsiter and generate an interrupt
//
//---------------------------------------------------------------------------------------
// Event 0: capture rising, only used for capture, no interrupt
LPC_SCT3->EVENT[0].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[0].CTRL = (0)       |  // capture, not used
                           (0 << 5)  |  // OUTSEL[5]     = selects input
                           (0 << 6)  |  // IOSEL[9:6]    = 0 select SCT3_IN0
                           (1 << 10) |  // IOCOND[11:10] = 1 rising
                           (2 << 12) |  // COMBMODE[13:12] = IO condition
                           (1 << 14) |  // STATELD[14]   = STATEV is loaded
                           (1 << 15);   // STATEV[19:15] = new state 1

// Event 1: capture rising, only used for capture, no interrupt
LPC_SCT3->EVENT[1].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[1].CTRL = (0)       |  // capture, not used
                           (0 << 5)  |  // OUTSEL[5]     = selects input
                           (1 << 6)  |  // IOSEL[9:6]    = 0 select SCT3_IN0
                           (1 << 10) |  // IOCOND[11:10] = 1 rising
                           (2 << 12) |  // COMBMODE[13:12] = IO condition
                           (1 << 14) |  // STATELD[14]   = STATEV is loaded
                           (1 << 15);   // STATEV[19:15] = new state 1

// Event 2: capture rising, only used for capture, no interrupt
LPC_SCT3->EVENT[2].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[2].CTRL = (0)       |  // capture, not used
                           (0 << 5)  |  // OUTSEL[5]     = selects input
                           (2 << 6)  |  // IOSEL[9:6]    = 0 select SCT3_IN0
                           (1 << 10) |  // IOCOND[11:10] = 1 rising
                           (2 << 12) |  // COMBMODE[13:12] = IO condition
                           (1 << 14) |  // STATELD[14]   = STATEV is loaded
                           (1 << 15);   // STATEV[19:15] = new state 1

//---------------------------------------------------------------------------------------

// Event 3: capture falling, used for capture and generates an interrupt
LPC_SCT3->EVENT[3].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[3].CTRL = (0)       |  // capture, not used
                           (0 << 5)  |  // OUTSEL[5]     = selects input
                           (0 << 6)  |  // IOSEL[9:6]    = 0 select SCT3_IN0
                           (2 << 10) |  // IOCOND[11:10] = 1 falling
                           (2 << 12) |  // COMBMODE[13:12] = IO condition
                           (1 << 14) |  // STATELD[14]   = STATEV is loaded
                           (1 << 15);   // STATEV[19:15] = new state 1

// Event 4: capture falling, used for capture and generates an interrupt
LPC_SCT3->EVENT[4].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[4].CTRL = (0)       |  // capture, not used
                           (0 << 5)  |  // OUTSEL[5]     = selects input
                           (1 << 6)  |  // IOSEL[9:6]    = 0 select SCT3_IN0
                           (2 << 10) |  // IOCOND[11:10] = 1 falling
                           (2 << 12) |  // COMBMODE[13:12] = IO condition
                           (1 << 14) |  // STATELD[14]   = STATEV is loaded
                           (1 << 15);   // STATEV[19:15] = new state 1

// Event 5: capture falling, used for capture and generates an interrupt
LPC_SCT3->EVENT[5].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[5].CTRL = (0)       |  // capture, not used
                           (0 << 5)  |  // OUTSEL[5]     = selects input
                           (2 << 6)  |  // IOSEL[9:6]    = 0 select SCT3_IN0
                           (2 << 10) |  // IOCOND[11:10] = 1 falling
                           (2 << 12) |  // COMBMODE[13:12] = IO condition
                           (1 << 14) |  // STATELD[14]   = STATEV is loaded
                           (1 << 15);   // STATEV[19:15] = new state 1


LPC_SCT3->STATE = 1;//start state

//---------------------------------------------------------------------------------------
// Only generate interrupts on the falling edge events (event 3,4 and 5)
//---------------------------------------------------------------------------------------
LPC_SCT3->EVFLAG = (SCT_EVT_3)| (SCT_EVT_4)| (SCT_EVT_5); //reset flags
LPC_SCT3->EVEN   = (SCT_EVT_3)| (SCT_EVT_4)| (SCT_EVT_5); //enable interrupts
NVIC_SetPriority(SCT3_IRQn, 0);//set priority
NVIC_EnableIRQ(SCT3_IRQn);

Chip_SCT_ClearControl(LPC_SCT3, SCT_CTRL_HALT_L | SCT_CTRL_HALT_H);//and start
}



0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by cgroen on Fri Apr 01 09:49:16 MST 2016
Argh,
my head hurts from all this SCT stuff. I don't know where to start.....

I finally have new PCB's here, and all is good and tested....except my 4 PWM inputs!
The 4 inputs are connected:
P0.07=PWMIN1 (SCT3)
P1.11=PWMIN2 (SCT3)
P1.19=PWMIN3 (SCT2)
P1.21=PWMIN4 (SCT3)

I get the thing about configuring the SCT MUX, but thats it! I can't figure out the rest. I have seen the AN note, they unfortunately only decodes one single input. And I'm not even sure the SCT can be tricked into measuring more than 1 at a time, but I think/hope that I'm wrong.??

Do any of you smart guys have any example code with the SCT for decoding more than 1 input ???
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by miccio on Thu Feb 04 10:02:24 MST 2016
from the omniscient UM (chapt 11.3):


Quote:

The GINT block reads the input from the pin directly bypassing the switch matrix.



So I guess that simply no configuration is needed :)
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by cgroen on Thu Feb 04 09:38:16 MST 2016
Thanks Miccio,
I had not seen that specific tool  8-) But, I'm afraid I'm a little conservative with regards to tools like that, I tend to read the datasheet/users guide instead (which I failed elegantly in this specific case  :D ) But the tool looks really nice!

I'm not sure I can find the GINT functions there (group GPIO input interrupt) ? Is that missing from the tool, or am I missing something`?
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by miccio on Thu Feb 04 07:44:53 MST 2016
remember that you can also use the LPC Initializer and Pinmux tool for checking which pins can be used for what. Nevertheless, reading the UM is always a good idea!! ;)
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by cgroen on Wed Feb 03 05:15:23 MST 2016
Thanks miccio,
then I have understood it correctly. Some of the pins that SCT0/1 can use is in use for other stuff in my design so I can't use these, that leaves me with 3 signals on SCT2 and 1 signal on SC3 (which is a little irritating...)
I know I could use pin interrupts and read a timer etc, but I would rather not have to rely on that (the system is quite heavily loaded to begin with). I was just curious if there was something I had misunderstood or if there were som "magic" I could apply to actually use the pins I already have the signals on.
I will make a respin of the board and fix the signals (lesson learned: Read ALL chapters before doing the design  ;-) )
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by miccio on Wed Feb 03 04:00:35 MST 2016
hi cgroen,


timers SCT0 and SCT1 support up to 7 inputs so if you set up your pins correctly you could get away with a single timer (which is the most ideal solution).
As far as i remember one of the example in the timer AN reads 2 pwm signals so you could get inspiration from that code (mind that it's not the tidiest).
Unfortunately the project for which i needed the capture functionalities has been postponed so I don't have any useful code to show you.

What kind of resolution do you need to achieve? If you can't move your pins around and don't need more than microsecond resolution then pin interrupts or simply polling and tracking time with the RIT might do (pretty much how you'd do on a Arduino).

More info on timer input mux at 9.6.1 of http://www.nxp.com/documents/user_manual/UM10736.pdf ;)
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by cgroen on Tue Feb 02 06:58:07 MST 2016
I have a question that are somewhat related to this,
I need to measure the width of 4 PWM inputs (instead of 1 as in the example above).
Am I correct in that I need two SCT's to do this ? (3 signals in f.ex SCT3 and 1 signal in SCT2) (SCT1 is not usable in my design because of other signals)
And, is it at the same time possible to measure the 4 PWM signals separate with this, or is there something else I need to consider ?
(I moved from LPC1758 to LPC1549 (QFP100) in the design, and (so far) I think the timer/capture of the 1758 was way easier to comprehend...)

On my prototype I have my signals on P2.0, P2.1, P2.2 and P1.06 as I was not aware of the limitations of the mux/SWM/SCT with regards to pins, I guess there is no easy way to measure the PWM when using these pins.. (don't like the idea of pin interrupts etc)
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by miccio on Wed Sep 23 05:34:05 MST 2015
Hi starblue,

Sorry for the late answer. The mistakes are actually documented, here you should be able to find the corrections.
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by starblue on Tue Sep 08 01:44:45 MST 2015

Quote: miccio
i decided to check whether the silkscreen on the board are 100% correct. Turned out they aren't,


So what's wrong specifically?
Please enlighten the rest of the world so we don't fall into the same trap.
And maybe it can be fixed in the next version.
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by miccio on Mon Sep 07 08:47:35 MST 2015
I was about to post that your code wasn't working either and simply give up when i decided to check whether the silkscreen on the board are 100% correct. Turned out they aren't, which explains why those rising and falling edges were not being detected.

Regardless of this huge mess, thanks for the help in understanding the SCT!! :)
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Sat Sep 05 04:05:27 MST 2015
This is a basic sample to generate a PWM signal and measure the frequency 


Quote:
Connect PIO0_6-PIO0_17 to measure PWM frequency



It's using semihosting in LPCOpen to print measured values (captured time in us and frequency) 


Quote:
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 18 F: 55555 Hz
No valid data!!
No valid data!!
No valid data!!
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz
C1: 4000 F: 250 Hz


/*
===============================================================================
 Name        : LPC15_SCT_Sample.c
 Author      :
 Version : 1.0
 Date  : 01.03.2014
 Copyright   :
 Type : Demo
 Hardware : LQFP48 Target Board
 Description : SCT0 sample to capture PIO0_17 to calculate input frequency
      SCT2 can generate a PWM signal at PIO0_6(SCT2OUT3)
      Connect PIO0_6-PIO0_17 to measure PWM frequency
===============================================================================
*/

#include "board.h"
#include <cr_section_macros.h>

volatile uint32_t capture1;//capture 1
volatile uint32_t freq;//frequency
volatile uint16_t ticks;//SysTick ticks
volatile uint8_t  sec;//second flag
volatile uint32_t valid;//valid flag

//PWM Generator---------------------------------------------------------------
#define GENERATE_PWM//generate PWM signal to test capture function

#ifdef GENERATE_PWM
#define PWM_RATE250       //PWM rate
#define SCT_PIN_OUT3        //SCT output pin
#define SCT_INDEX1        //SCT match register

void SCT2_init(void)
{
 Chip_SCTPWM_Init(LPC_SCT2);//init SCT2
 Chip_SCTPWM_SetRate(LPC_SCT2, PWM_RATE);//set cycle (in SCT Match0 register)
 Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM);//enable SWM
 Chip_SWM_EnableFixedPin(SWM_FIXED_SCT2_OUT3); //switch output: SCT2OUT3 = PIO0_6
 Chip_SCTPWM_SetOutPin(LPC_SCT2, SCT_INDEX, SCT_PIN_OUT);//set output
 Chip_SCTPWM_SetDutyCycle(LPC_SCT2, SCT_INDEX, LPC_SCT2->MATCHREL[0].U/3);//set duty
 Chip_SCTPWM_Start(LPC_SCT2);//and start
}
#endif

void SCT0_IRQHandler(void)
{
 if(LPC_SCT0->EVFLAG & SCT_EVT_1 )//event?
 {
  Board_LED_Toggle(0);//toggle LED
  valid =1;//set valid flag
  LPC_SCT0->EVFLAG = SCT_EVT_1;//reset event
 }//end event
}

//SysTick Interrupt
void SysTick_Handler(void)
{
 ticks++;//inc ticks
 if(ticks >= 10)//second timer
 {
  ticks =0;//reset ticks
  sec =1;//second flag
  Board_LED_Toggle(0);
 }//end second timer
}

void SCT0_init(void)
{
//input capture PIO0_17
 Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 17, (IOCON_MODE_PULLDOWN));
 Chip_SCT_Init(LPC_SCT0);
//unified 32bit counter, SYNC all inputs, enable prescaler in CTRL register
 LPC_SCT0->CONFIG =  SCT_CONFIG_32BIT_COUNTER | (1<<9);
 LPC_SCT0->LIMIT = SCT_EVT_1;//events to limit counter
//set prescaler 72 to count µs
 Chip_SCT_SetControl(LPC_SCT0,SCT_CTRL_PRE_L(72-1));
//input capture setting
 LPC_INMUX->SCT0_INMUX[0] = 2;//SCT0_IN0 = P0IO_17
 LPC_SCT0->REGMODE  = (SCT_EVT_1);//set capture register(s)
 LPC_SCT0->CAPCTRL[1].U  = (SCT_EVT_1);//set capture control event

//event 1: capture rising
 LPC_SCT0->EVENT[1].STATE = (SCT_EVT_1); // event happens in state
 LPC_SCT0->EVENT[1].CTRL = (0)       |  // capture, not used
                           (0 << 5)  |  // OUTSEL[5]     = selects input
                           (0 << 6)  |  // IOSEL[9:6]    = 0 select SCT0_IN0
                           (1 << 10) |  // IOCOND[11:10] = 1 rising
                           (2 << 12) |  // COMBMODE[13:12] = IO condition
                           (1 << 14) |  // STATELD[14]   = STATEV is loaded
                           (1 << 15);   // STATEV[19:15] = new state 1

 LPC_SCT0->STATE =1;//start state

 //interrupts: rising
 LPC_SCT0->EVFLAG = (SCT_EVT_1); //reset flags
 LPC_SCT0->EVEN   = (SCT_EVT_1); //enable interrupts
 NVIC_SetPriority(SCT0_IRQn, 0);//set priority
 NVIC_EnableIRQ(SCT0_IRQn);

 Chip_SCT_ClearControl(LPC_SCT0, SCT_CTRL_HALT_L | SCT_CTRL_HALT_H);//and start
}

int main(void)
{
 SystemCoreClockUpdate();
 Board_Init();
 Board_LED_Set(0, true);
 //init SCT0 to capture PIO0_17
 SCT0_init();//init SCT0
 #ifdef GENERATE_PWM
 //init SCT2 to generate PWM
 SCT2_init();
#endif

 //init SysTick to 10Hz
 SysTick_Config(SystemCoreClock/10);
 NVIC_SetPriority(SysTick_IRQn,2);//set priority
 while(1)//loop
 {
  if(sec)//second timer
  {
   sec =0;//reset second flag
   if(valid)//valid data
   {
    valid=0;//reset valid
    capture1 = LPC_SCT0->CAP[1].U;//get capture value
    freq = SystemCoreClock / capture1 /72;//calculate frequency
    printf("C1: %d ",capture1);
    printf("F: %d Hz\n",freq);
   } //end valid
   else
   {
    printf("No valid data!!\n");
   }
  }//end second timer
 }//end loop
 return 0 ;
}

0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by miccio on Sat Sep 05 03:25:22 MST 2015

Quote:

Anyway, I always recommend to start with a simple example: calculate the frequency with a single event (rising edge).



I tried to strip down the code so that it would only have a single capture on a single event, but it still did not detect the signal :(
Do you have any example code for such task? it needn't be LPCOpen of course
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Sat Sep 05 02:44:04 MST 2015

Quote: miccio
...I didn't wait for Christmas to get a LPC15 board  ;-)



I've feared that already  :D

Sorry, can't compile your project with all this unknown stuff  :((

Anyway, I always recommend to start with a simple example: calculate the frequency with a single event (rising edge).

Then add a second event (falling edge) and switch the states. That's enough to get frequency and high / low times  :)  

SCT isn't easy and unfortunately a lot of samples are very confusing...




0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by miccio on Sat Sep 05 02:04:08 MST 2015

Quote: R2D2

... post a  complete project...



Hi R2D2,
see, I didn't wait for Christmas to get a LPC15 board  ;-)

Here is the complete project; please note that it won't compile with LPCOpen 2.08c as lacks some Chip_SCT_* functions. Please use the version available in the Application Note linked by mc.
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Sep 04 11:11:17 MST 2015

Quote: miccio
Any possible advice or suggestion?



... post a  complete project...
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by miccio on Fri Sep 04 10:59:46 MST 2015
Hi mc,

thanks for the prompt answer.
I downloaded the AN, imported all the examples, and tried to play around with the one called pwm_decod. However, it did not seem to work at all. I then changed the FREQUENCY value and   SCT input mux source with even less luck.

Here is some barebones code i wrote for the state machine, which still seem not to work. After several hours, I couldn't find anything wrong.
#define PWM_RESOLUTION_NS       1000
#define SCT_PRESCALER           (((SystemCoreClock / 1000u) * PWM_RESOLUTION_NS) / 1000000u - 1u)

void SCT0_Init(void)
{
// enable the SCT0 clock
Chip_SCT_Init(LPC_SCT0);

// timer configuration: unified, autolimit through match0
Chip_SCT_Config(LPC_SCT0, SCT_CONFIG_32BIT_COUNTER | SCT_CONFIG_AUTOLIMIT_L);

// set pre-scaler
Chip_SCT_SetControl(LPC_SCT0, SCT_CTRL_PRE_L(SCT_PRESCALER));

// 1x MATCH , 2x CAPTURE used
LPC_SCT0->REGMODE_L = (0 << 0) | (1 << 1) | (1 << 2);

// set up match0 (timeout)
Chip_SCT_SetMatchCount(LPC_SCT0, SCT_MATCH_0, 2000000);
Chip_SCT_SetMatchReload(LPC_SCT0, SCT_MATCH_0, 2000000);

// Event0: rising edge, any->st0, capt1
// Event1: falling edge, any->st0, capt2
// Event2: timeout, any->st0, restart
// setting up events: http://www.nxp.com/documents/user_manual/UM10736.pdf p255

Chip_SCT_EventState(LPC_SCT0, SCT_EVENT_0, ENABLE_ALL_STATES);
Chip_SCT_EventControl(LPC_SCT0, SCT_EVENT_0, SCT_IOSEL_RISEIN0|
 SCT_IOCOND_RAISE|
 SCT_COMBMODE_IO|
 SCT_STATELD_1|
 SCT_STATEEV_0);

Chip_SCT_EventState(LPC_SCT0, SCT_EVENT_1, ENABLE_ALL_STATES);
Chip_SCT_EventControl(LPC_SCT0, SCT_EVENT_1, SCT_IOSEL_RISEIN0|
 SCT_IOCOND_FALL|
 SCT_COMBMODE_IO|
 SCT_STATELD_1|
 SCT_STATEEV_0);

Chip_SCT_EventState(LPC_SCT0, SCT_EVENT_2, ENABLE_ALL_STATES);
Chip_SCT_EventControl(LPC_SCT0, SCT_EVENT_2, SCT_EVECTRL_MATCH0|
 SCT_COMBMODE_MATCH|
 SCT_STATELD_1|
 SCT_STATEEV_0);


// set up captures by event
Chip_SCT_CapControl(LPC_SCT0, SCT_CAPCTRL_1 , SCT_EVT_0);
Chip_SCT_CapControl(LPC_SCT0, SCT_CAPCTRL_2 , SCT_EVT_1);

// set counter limit at rising edge and timeout
LPC_SCT0->LIMIT_L = (1 << 0) | (1 << 2);
// enable interrupt on all events
Chip_SCT_EnableEventInt(LPC_SCT0, SCT_EVT_0 | SCT_EVT_1 | SCT_EVT_2);
NVIC_EnableIRQ(SCT0_IRQn);

// clear halt control bit: turn on timer
Chip_SCT_ClearControl(LPC_SCT0,SCT_CTRL_HALT_L);
}


The code above should simply record in the capture registers 1 and 2 the value of the counter at transition and reset the counter at every rising edge or after 2s of inactivity.

The main.c file goes as follow:
extern void SCT0_Init(void);

void SCT0_IRQHandler(void) {
uint32_t status = Chip_SCT_GetEventFlag(LPC_SCT0);

// event 0: rising edge
if (status & SCT_EVT_0) {
Board_LED_Set(0, true);
}

// event 1: falling edge
if (status & SCT_EVT_1) {
Board_LED_Set(0, false);
}

// event 2: timeout
if (status & SCT_EVT_2) {
Board_LED_Set(0, false);
}

Chip_SCT_SetEventFlag(LPC_SCT0, status);
}

int main(void) {
volatile static int time_on, time_tot;

SystemCoreClockUpdate();
Board_Init();

Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM | // enable SWM clock
 SYSCTL_CLOCK_GPIO0 |// enable GPIO port 0 clock
 SYSCTL_CLOCK_MUX |// enable PMUX clock
 SYSCTL_CLOCK_IOCON);// enable IOCON clock

    Chip_INMUX_SelectSCT0Src(0, SCT0_INMUX_PIO0_2);// SCT0_IN0  = P0.2 = SW1
    SCT0_Init();                                          // Initialize SCT0

    while (1) {
time_tot = LPC_SCT0->CAP[1].U;
time_on = LPC_SCT0->CAP[2].U;

__WFI();
    }
}


Event n2 gets always executed, meaning that the counter timeouts. The error must therefore be in the edge detection events, although I can't quite find it. Any possible advice or suggestion?
0 Kudos

2,048 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mc on Thu Sep 03 16:30:26 MST 2015
Hi miccio,
You can use SCTimer/PWM input to read this signal. Please check below appnote
https://www.lpcware.com/content/nxpfile/an11538-sctimerpwm-cookbook

0 Kudos