LPC 824 SCTimer: PWM and pulse count

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

LPC 824 SCTimer: PWM and pulse count

3,920 Views
janblumenkamp
Contributor I

Hello everyone,

the SCTimer is a very complex peripheral and before I put much more time into understanding it, I would like to know if what I am planning to do is actually possible.

I have an application that decodes RFID tags. For that, I need to be able to count pulses. I have a clock and a data line. On every data line edge transition I need to check how many clock pulses occured.

This is the one thing. Additional to that I need two PWM outputs.

The two task seperately from each other are not a big deal. But I want to do both with only one SCTimer (as the LPC824 only has one).

Now I am wondering if that is actually possible - having a counter and a PWM independently from each other with only one SCTimer? If, for the counter part, I need to use the signal that I want to use pulses als SCT clock, of course this would not work, right? Or is it possible to increment the timer counter based on signal transitions independently from the PWM?

With kind regards,

Jan

Tags (2)
0 Kudos
9 Replies

2,175 Views
jean-marcrouxel
Contributor I

Hello,

I want to do the same thing (on a LPC55S69) :

- one normal counter to monitor the frequency of an input signal

- one PWM

I want to use the two 16-bit timers on the same SCTimer.

Separately, the both functions are ok, but together, just the frequency monitor is ok, not the PWM !
I would like to know if you found a solution to your similar problem

Regards,

Jean-Marc

 

0 Kudos

2,285 Views
athmesh_n
Contributor IV

Hello everyone, 

I'm working on delay function using single SCTimer. I've created two delay functions: delay_us(period)delay_ms(period). I want to start timer when I call these functions, and wait till condition (count>period). count gets incremented in us or ms depending on the function called. But I would like to just use a single timer SCtimer2 for both functions.

Device : LPC1517
IDE       : MCUXpresso IDE v10.2.1 [Build 795] [2018-07-25] 

For eg: if delay_us is called, timer is configured as :

LPC_SCT0->MATCH[0].U   =(SystemCoreClock/1000000-1);

LPC_SCT0->MATCHREL[0].U   =(SystemCoreClock/1000000-1);

and then timer is stopped once delay is completed and then if delay_ms is called, timer is configured as :

LPC_SCT0->MATCH[0].U   =(SystemCoreClock/1000-1);
LPC_SCT0->MATCHREL[0].U   =(SystemCoreClock/1000-1);

This works for sometime but then stops randomly.

what can be the issue?

0 Kudos

2,286 Views
jeremyzhou
NXP Employee
NXP Employee

Hi ATHMESH NANDAKUMAR,

Regarding your question, to provide the fastest possible support, I'd highly recommend yout to refer to the application note AN11538 which demonstrates the match function usage, please refer to it for details.
If you have other questions, you'd better create a new thread for it.
Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

2,286 Views
athmesh_n
Contributor IV

Good Day Jeremy,

I've already created a thread : https://community.nxp.com/thread/482101 . I was looking for answers to my questions and I found this thread having similar question to mine. That's why I responded.
Pls do check my thread and help.


Thank you very much for your fast reply.

0 Kudos

2,286 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Jan Blumenkamp,

Thank you for your interest in NXP Semiconductor products and 
for the opportunity to serve you.
1) Having a counter and a PWM independently from each other with only one SCTimer?
    Yes, it's possible.
2) For the counter part, I need to use the signal that I want to use pulses as SCT clock, of course this would not work, right? 
    No, it's unavailable.
3) is it possible to increment the timer counter based on signal transitions independently from the PWM?
    Yes, it's possible as the SCTimer is configurable as two independent16-bit counters.

Have a great day,
TIC

 

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,286 Views
janblumenkamp
Contributor I

I am sorry, but I don't understand how this can work... Just to be clear, I want one normal counter and one PWM. The counter should only count rising and falling edges of a signal, nothing else. This signal CAN NOT be used as the PWM Clock of course! With the other counter I want PWM. If I want a counter, I need to set the SCTimer clock to SCT_CONFIG_CLKMODE_INEDGECLK. If I want PWM, I need to set it to SCT_CONFIG_CLKMODE_BUSCLK. But I can only select one clock for one SCTimer, not two. So how should this work?

0 Kudos

2,286 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Jan Blumenkamp,

Let me clarify it.

The counter implementation is able to be achieved via configuring the I/O input event to detect the state variation of input pins, when you also enable the event interrupt, you can record the detected pulse in the event interrupt function, so you can choose the system clock as the SCT clock, and the clock configuration also suits the PWM generation.
Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,286 Views
janblumenkamp
Contributor I

Hi jeremyzhou‌,

how is the counter then any different from a normal Pin Change Interrupt? I wanted to use the peripheral because I have a very fast clock signal that I need to count (it's the clock base for a manchester encoding). If an interrupt is generated every time the clock signal toggles, the CPU is completely blocked as it runs on a quiet high frequency there are also other interrupts to be handled.

Something else I discovered is that the values I get from the counter in the debugger are completely false. For some reason, they are always in the range of 100000, but if I let the program run normally, it works. Very strange.

Anyway, for now I solved the problem by using the MRTimer as a Soft-PWM and the SCTimer as a counter. Here is my minimal-example:

int main(void)
{
    SystemCoreClockUpdate();

    Chip_SYSCTL_SetBODLevels(3, 3);                // Set BrownOut detection to 2,8V
    Chip_SYSCTL_EnableBODReset();                  // important for unstable power conditions

    Chip_GPIO_Init(LPC_GPIO_PORT);

    Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 14); // LED

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM);

    ////////IO (EM4095)

    Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 1); // Enable Pin EM4095
    Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 1); // Enable EM4095

    Chip_SWM_MovablePinAssign(SWM_SCT_IN2_I, 9); // Data Pin EM4095

    Chip_SYSCTL_SetPinInterrupt(2, 9); // GPIO9 (Data) at PCINT2 2

    Chip_SYSCTL_EnablePINTWakeup(2);
    
    Chip_PININT_SetPinModeEdge(LPC_PININT, PININTCH2); //Edge sensitive
    Chip_PININT_EnableIntLow(LPC_PININT, PININTCH2); //Rising Flanke
    Chip_PININT_EnableIntHigh(LPC_PININT, PININTCH2); //Falling Flanke

    ////////SCTimer/////////

    Chip_SWM_MovablePinAssign(SWM_SCT_IN1_I, 8); // Pin to count clock

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SCT);
    Chip_INMUX_SetSCTInMux(LPC_INMUX, SCT_INMUX_0, SCT_INP_IN1);

    Chip_SCT_Init(LPC_SCT);
    Chip_SCT_Config(LPC_SCT, SCT_CONFIG_32BIT_COUNTER | SCT_CONFIG_CLKMODE_INCLK); // Rising edge input 1 (user manual p 268)
    Chip_SCT_ClearControl(LPC_SCT, SCT_CTRL_HALT_L | SCT_CTRL_HALT_H); //and start

    /////////Data IRQ/////////

    NVIC_SetPriority(PININT2_IRQn, NVIC_PRIO_RFID_DATA);
    NVIC_EnableIRQ(PININT2_IRQn);

    /* Disable the clock to the Switch Matrix to save power */
    Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SWM);
    Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_IOCON);

    ////////MRTimer///////

    Chip_MRT_Init();
    LPC_MRT_CH_T *mrt = Chip_MRT_GetRegPtr(0);
    Chip_MRT_SetInterval(mrt, 2550);
    Chip_MRT_SetMode(mrt, MRT_MODE_REPEAT);
    Chip_MRT_SetEnabled(mrt);

    NVIC_SetPriority(MRT_IRQn, 4);
    NVIC_EnableIRQ(MRT_IRQn);

    while(1)
    {
        __WFI();
    }
}

void MRT_IRQHandler()
{
    Chip_MRT_IntClear(Chip_MRT_GetRegPtr(0));
    // Do soft PWM here
}

void PININT2_IRQHandler()
{
    Chip_PININT_ClearIntStatus(LPC_PININT, PININTCH2);

    if(LPC_SCT->COUNT_U > 48) // 48 clock cycles since last data toggle: logic 1
    {
        Chip_SCT_SetControl(LPC_SCT, SCT_CTRL_HALT_L | SCT_CTRL_HALT_H);
        Chip_SCT_SetControl(LPC_SCT, SCT_CTRL_CLRCTR_L | SCT_CTRL_CLRCTR_H);
        Chip_SCT_ClearControl(LPC_SCT, SCT_CTRL_HALT_L | SCT_CTRL_HALT_H);

        // Do processing here
        Chip_GPIO_SetPinToggle(LPC_GPIO_PORT, 0, 14); // Toggle debug LED
    }
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This is not a nice solution, but for now it works.

If anyone knows a more elegant solution for my purposes, possibly using the SCTimer, please let me know!

With kind regards,

Jan

0 Kudos

2,286 Views
janblumenkamp
Contributor I

Hi jeremyzhou‌,

thank you for your response! This is great news.

I was not able to find a simple sample code that sets up one of the two 16bit counters as counter that counts level transitions. I have found this entry How to count external pulses with SCTimer? but I am not sure if the problem was actually solved. I basically want the same, but because I want to use the PWM for the other counter, I can't set the SCTimer clock to the external clock.

My approach (minimum version) looks like this. I basically one clock and one data line. On a pin change in the data line (pin 9), I want to check how many clock cycles already passed (pin 8). Pin 1 enables the em4095 (RFID), and there is an LED on pin 14 that I toggle in the data interrupt.

int main(void)
{
     SystemCoreClockUpdate();

     Chip_SYSCTL_SetBODLevels(3, 3);                // Set BrownOut detection to 2,8V
     Chip_SYSCTL_EnableBODReset();                  // important for unstable power conditions

     Chip_GPIO_Init(LPC_GPIO_PORT);

     Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 14); // LED

     Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON);
     Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM);

     Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 1); // Enable Pin (SHD)
     Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 1);

     Chip_SWM_MovablePinAssign(SWM_SCT_IN2_I, 9); // Data

     Chip_SYSCTL_SetPinInterrupt(2, 9); // GPIO9 (Data) at PCINT2 2

     Chip_SYSCTL_EnablePINTWakeup(2);

     Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, 0, 9); // Data input (Data)

     Chip_PININT_SetPinModeEdge(LPC_PININT, PININTCH2); //Edge sensitive
     Chip_PININT_EnableIntLow(LPC_PININT, PININTCH2); //Rising Flanke
     Chip_PININT_EnableIntHigh(LPC_PININT, PININTCH2); //Falling Flanke

     /////////////////


     Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SCT);
     Chip_SCT_Init(LPC_SCT);

     Chip_SCT_Config(LPC_SCT, SCT_CONFIG_16BIT_COUNTER | SCT_CONFIG_CLKMODE_BUSCLK);

     Chip_SWM_MovablePinAssign(SWM_SCT_IN0_I, 8); // Pin to count clock
     Chip_INMUX_SetSCTInMux(LPC_INMUX, SCT_INMUX_0, SCT_INP_IN0);


     LPC_SCT->CAPCTRL[0].= (SCT_EVT_0);//set capture control event

     LPC_SCT->EV[0].STATE = (SCT_EVT_0); // event happens in state
     LPC_SCT->EV[0].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_SCT->STATE_U = 1;//start state
     LPC_SCT->EVFLAG = SCT_EVT_1; //reset flags
     Chip_SCT_ClearControl(LPC_SCT, SCT_CTRL_HALT_L); // start

     //////////////////

     //NVIC_SetPriority(PININT1_IRQn, NVIC_PRIO_RFID_CLOCK);
     NVIC_SetPriority(PININT2_IRQn, NVIC_PRIO_RFID_DATA);
     //NVIC_EnableIRQ(PININT1_IRQn);
     NVIC_EnableIRQ(PININT2_IRQn);

     /* Disable the clock to the Switch Matrix to save power */
     Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SWM);
     Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_IOCON);

     while(1);
}

void PININT2_IRQHandler()
{
     Chip_PININT_ClearIntStatus(LPC_PININT, PININTCH2);

     if(LPC_SCT->COUNT_L > 48) // Counter
     {
          Chip_GPIO_SetPinToggle(LPC_GPIO_PORT, 0, 14); // LED
          // Do sth
     }
}

I appreciate your help!

With kind regards,

Jan

0 Kudos