TPM channel on K27

cancel
Showing results for 
Search instead for 
Did you mean: 

TPM channel on K27

162 Views
Contributor II

Good morning.

I'd like to use the TPM counter and its channel for some timing uses.

Prescale must be set at 128, so with a 24 mhz of bus clock I have 187, 5 Khz for tpm clock.

One channel (..ch2) must be set to get an interrupt break at every 1ms. I write the simple code that I use now.

It works properly for just 250 ms. After that, the TPM0 interrupt it does not work anymore and the output is fixed at one.

I don't understand this behavior. Probably something is missing in my code.

Look at CH2

Thanks in advance.

Attilio

#define        TPM_CHANNEL_0                0                                    // tpm channel 0 mask
#define        TPM_CHANNEL_1                1                                    // tpm channel 1 mask
#define        TPM_CHANNEL_2                2                                    // tpm channel 2 mask
#define        TPM_CHANNEL_3                3                                    // tpm channel 3 mask
#define        TPM_CHANNEL_4                4                                    // tpm channel 4 mask
#define        TPM_CHANNEL_5                5                                    // tpm channel 5 mask

#define        TPM_CH0_FLAG                0x01                                // channel 0 event flag
#define        TPM_CH1_FLAG                0x02                                // channel 1 event flag
#define        TPM_CH2_FLAG                0x04                                // channel 2 event flag
#define        TPM_CH3_FLAG                0x08                                // channel 3 event flag
#define        TPM_CH4_FLAG                0x10                                // channel 4 event flag
#define        TPM_CH5_FLAG                0x20                                // channel 5 event flag

#define        TPM_OVERFLOW_COUNTER        0x100                                // overflow counter flag

This the init function

void InitTimers(void)
{

    SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK;                                           // clock gating
    SIM->SOPT2 |= SIM_SOPT2_TPMSRC(0x10);                                         // tpm clock source

    TPM0->SC  = TPM_SC_PS(0x07)    |                                                        // prescaler divide 0x07 = 128 times
                           TPM_SC_CMOD(0x01);                                                        // tpm increment every tpm counter clock

    TPM0->MOD = 46750;                                                                               // timer period

    // CHANNEL 2 SETTING
    TPM0->CONTROLS[TPM_CHANNEL_2].CnV  = 23375;                     // first int. after ~125ms
    TPM0->CONTROLS[TPM_CHANNEL_2].CnSC = (OUT_COMPARE_TOGGLE + TPM_CnSC_CHIE_MASK);        

    PORTA->PCR[5] = PORT_PCR_MUX(ALTERNATE_FUNCTION_3);      // PTA5 wired to out

    ConnectInterruptToCortex(TPM0_IRQn);                                                 // set TPM0 interrupt
}

This the interrupt

void TPM0_IRQHandler(void)
{
    UINT32     status;
    UINT32   l;

    status = TPM0->STATUS;

    // OVERFLOW
    if(status & TPM_OVERFLOW_COUNTER)
    {
    }

    // CH0
    if(status & TPM_CH0_FLAG)
    {
    }

    // CH1
    if(status & TPM_CH1_FLAG)
    {
    }

    // CH2
    if(status & TPM_CH2_FLAG)
    {
        l = TPM0->CNT;
        l = l + 376;
        l = l % 65535;

        TPM0->CONTROLS[TPM_CHANNEL_2].CnV = (UINT16)l;
    }


    // CH3
    if(status & TPM_CH3_FLAG)
    {
    }

    // CH4
    if(status & TPM_CH4_FLAG)
    {
    }

    // CH5
    if(status & TPM_CH5_FLAG)
    {
    }

    TPM0->STATUS |= status;

}

Labels (1)
0 Kudos
5 Replies

12 Views
Contributor I

Exactly what I needed! You just saved me several hours. Thanks!

0 Kudos

12 Views
NXP TechSupport
NXP TechSupport

Hi Attilio,

I can see you configure the TPM0 work as OUT_COMPARE_TOGGLE mode.
Since you just need the ch2 get an interrupt break at every 1ms, why not direct configure TPM0->MOD let the period =1ms. Then the fixed TPM0->CONTROLS[TPM_CHANNEL_2].CnV value will always get 1ms interrupt and toggle waveform.(There is no need to modify ch2.CnV so frequently in IRQ)

Example of the output compare mode when the match toggles the channel output.png

Best Regards,

Robin

 

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

0 Kudos

12 Views
Contributor II

Hi Robin.

Thanks for your interest.

You are right. But in reality the main purpose of this timer it's to generate a slow pwm frequency on channel 1.

So, I have to keep the MOD register at the desidered period. Usually it's 8 hz. (about 46875 value at 187,5 Khz).

But I wanted to use the same timer to get a 1 ms tick on another output.

Below, I send the total code that I'm using now, so may be more clear for you.

As I wrote the strange thing is at the beginning it works fine and properly. I can see the output toggle every 1ms (500 hz frequency) but suddendly afeter 250ms - 300 ms the TPM0 interrupt is no longer call.

Thanks

Attilio

void InitTimers(void)
{
    float     bus_tick, frequency, period, duty;
    UINT8    duty_cycle;

    /* TIMER 0 channels setting */
    GetLampParameters(&frequency, &duty_cycle);

    bus_tick = (1.0 / (BUSCLOCK / Power(2, 0x07)));
    period   = (1.0 / frequency) / bus_tick;
    duty     = (period / 100) * duty_cycle;

    SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK;                                        // clock gating
    SIM->SOPT2 |= SIM_SOPT2_TPMSRC(0x10);                                    // tpm clock source

    TPM0->SC = 0x00UL;
    TPM0->SC |= TPM_SC_PS(0x07);                                            // prescaler divide 0x07 = 128 times
    TPM0->SC |= TPM_SC_CMOD(0x01);                                            // tpm increment every tpm counter clock


    TPM0->MOD = (UINT32)period;                                                // timer period

    // channel 1 setting
    TPM0->CONTROLS[TPM_CHANNEL_1].CnV  = (UINT32)duty;                        // timer duty cycle
    TPM0->CONTROLS[TPM_CHANNEL_1].CnSC = PWM_EDGE_ALIGN_HIGH_PULSE;            // pwm - no CHIE
    PORTA->PCR[4] = PORT_PCR_MUX(ALTERNATE_FUNCTION_3);                        // PTA4 wired to manage lamp


    // channel 2
    TPM0->CONTROLS[TPM_CHANNEL_2].CnSC = OUT_COMPARE_TOGGLE +\
                                         TPM_CnSC_CHIE_MASK;                                                 // ch2 - out.comp. - CHIE request

    TPM0->CONTROLS[TPM_CHANNEL_2].CnV  = 375;                                            // first match after ~2ms
    PORTA->PCR[5] = PORT_PCR_MUX(ALTERNATE_FUNCTION_3);                        // PTA5 wired to lamp

    ConnectInterruptToCortex(TPM0_IRQn);                                    // set TPM0 interrupt
}


void TPM0_IRQHandler(void)
{
            UINT32    status;
            UINT16    l;
    static UINT8     break_test;

    status = TPM0->STATUS;

    // OVERFLOW
    if(status & TPM_OVERFLOW_COUNTER)
    {
        break_test = 1;
    }

    // CH0
    if(status & TPM_CH0_FLAG)
    {
        break_test = 1;
    }

    // CH1
    if(status & TPM_CH1_FLAG)
    {
        break_test = 1;
    }

    // CH2
    if(status & TPM_CH2_FLAG)
    {
        l = TPM0->CNT;
        l = l + 375;
        TPM0->CONTROLS[TPM_CHANNEL_2].CnV = (UINT32)l;
    }

    // CH3
    if(status & TPM_CH3_FLAG)
    {
        break_test = 1;
    }

    // CH4
    if(status & TPM_CH4_FLAG)
    {
        break_test = 1;
    }

    // CH5
    if(status & TPM_CH5_FLAG)
    {
        break_test = 1;
    }

    TPM0->STATUS |= status;
}

0 Kudos

12 Views
NXP TechSupport
NXP TechSupport

Hi Attilio,

I find the value that you give CnV will greater than TPM0->MOD = 46750;

Please limit the value of CnV.

Best Regards,

Robin

 

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

12 Views
Contributor II

Robin thank you very much.

The solution was in front of me without seeing it.

Have a nice day.

Attilio

0 Kudos