SAMD21 TCC PPW or PWP capture, how?

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I haven't found a complete example of code for the use of TCC PPW/PWP

In Fig. 31-10 http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf#page=545 it shows "external signal/event"

If we use an external signal, which input pins can one use, and how do we associate the TCC with the pin?

If we use events, what events generators are used, and which TCC users? How does the TCC know that one event is from the leading flank, and which from the trailing edge? 

The same method can also used for TC

Could someone point me in the right direction

Thanks, Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you haven't got a complete description then a short description of the necessary steps would be very useful

Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

External signal directly to the TC for capture is not possible, i.e., this looks like a documentation error:

 To enable the capture from the IO pin, the Capture On Pin x Enable bit in CTRLC register (CTRLC.COPENx) must be written to '1'. 

 D21 has no such bits in TC CTRLC.

So it has to be an event, typically it would be from EIC (i.e., from one of the EXTINT). From my testing it will only work when setting up an asynchronous event. You need only one event btw, the edge detection happens in the TCC (or TC). The event user should be obvious since there is only one place where you can configure PPW and PWP (EVACT1[2:0]: Timer/Counter Event Input 1 Action for TCC, and TC has only one input event with setting in EVACT[2:0]: Event Action).

The example captures 128 periods and pulse widths from PA04. Select TCC or TC with the define USE_TCC. Put a breakpoint on the done++ lines to see the result. The first capture should be skipped, i.e., cap0[0] and cap1[0] will not be valid.

#include "sam.h"
#include <stdlib.h>

static volatile uint16_t cap0[128]; // Period with PPW capture
static volatile uint16_t cap1[128]; // Pulse width with PPW capture
static volatile size_t nCap;
#define USE_TCC

void setupInput(void)
{
    PM->APBAMASK.bit.EIC_ = 1;

    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EIC);
    while (GCLK->STATUS.bit.SYNCBUSY);
    
    // Input on PA04
    PORT->Group[0].PMUX[4/2].bit.PMUXE = MUX_PA04A_EIC_EXTINT4;
    const PORT_PINCFG_Type pincfg = {
        .bit.PMUXEN = 1,
        .bit.INEN = 1,
        .bit.PULLEN = 1
    };
    PORT->Group[0].PINCFG[4].reg = pincfg.reg;
   
    EIC->CONFIG[0].bit.SENSE4 = EIC_CONFIG_SENSE4_HIGH_Val; // None of RISE,FALL or BOTH work for this
    EIC->EVCTRL.bit.EXTINTEO4 = 1;
    
    // The EIC interrupt is only for verifying the input
    //REG_EIC_INTENSET = EIC_INTFLAG_EXTINT4;
    //NVIC_EnableIRQ(EIC_IRQn);
    while (EIC->STATUS.reg & EIC_STATUS_SYNCBUSY);
    EIC->CTRL.bit.ENABLE = 1;                  
    while (EIC->STATUS.reg & EIC_STATUS_SYNCBUSY); 
}

#ifdef USE_TCC
void setupTimer(void)
{
    PM->APBCMASK.bit.TCC0_ = 1;

    REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC0_TCC1;
    while (GCLK->STATUS.bit.SYNCBUSY);
    
    TCC0->CTRLA.bit.ENABLE = 0;
    while (TCC0->SYNCBUSY.bit.ENABLE);

    TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1 | TCC_CTRLA_CPTEN0 | TCC_CTRLA_CPTEN1;
    TCC0->PER.reg = 0xFFFFFF;
    while (TCC0->SYNCBUSY.bit.PER);

    TCC0->EVCTRL.reg = TCC_EVCTRL_TCEI1 |  // enable input event
        TCC_EVCTRL_EVACT1_PPW; // event action = PPW
        // | TCC_EVCTRL_MCEI0 | TCC_EVCTRL_MCEI1;

    // Interrupts
    TCC0->INTENSET.bit.MC0 = 1;
    //TCC0->INTENSET.bit.MC1 = 1; // Not needed, can read out both in MC0 interrupt
    NVIC_EnableIRQ(TCC0_IRQn);

    // Enable TCC
    TCC0->CTRLA.bit.ENABLE = 1;
    while (TCC0->SYNCBUSY.bit.ENABLE); // wait for sync

    PM->APBCMASK.bit.EVSYS_ = 1;
    // EVSYS GCLK is needed for interrupts and sync path (so not now)
    // GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EVSYS_1);
    // while (GCLK->STATUS.bit.SYNCBUSY);
    
    // TCC_EVCTRL_TCEI1 is used, must be matched with EVSYS_ID_USER_TCC0_EV_1 here
    REG_EVSYS_USER = EVSYS_USER_USER(EVSYS_ID_USER_TCC0_EV_1)|EVSYS_USER_CHANNEL(2); // Channel n-1 selected so 1 here
    while(!EVSYS->CHSTATUS.bit.USRRDY1);
    // EVSYS_CHANNEL_EDGSEL_BOTH_EDGES // not usable with  PATH_ASYNCHRONOUS
    // For this capture it looks like it needs to be PATH_ASYNCHRONOUS 
    REG_EVSYS_CHANNEL = EVSYS_CHANNEL_PATH_ASYNCHRONOUS|EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4)|EVSYS_CHANNEL_CHANNEL(1);
    while(EVSYS->CHSTATUS.bit.CHBUSY1);
    // Below interrupt is for testing the event (not possible with PATH_ASYNCHRONOUS)
    //EVSYS->INTENSET.reg = EVSYS_INTENSET_EVD1;
    //NVIC_EnableIRQ(EVSYS_IRQn);  
}

void TCC0_Handler()
{  
    if (TCC0->INTFLAG.bit.MC0) { 
        // The interrupt flag is cleared by reading CC
        cap0[nCap] = TCC0->CC[0].bit.CC;
        cap1[nCap] = TCC0->CC[1].bit.CC;
        if (++nCap == sizeof(cap0)/sizeof(cap0[0])) {
            static volatile size_t done;
            done++;
            nCap = 0;
        }     
    }
}
#else
void setupTimer(void)
{
    PM->APBCMASK.bit.TC3_ = 1;

    REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3;
    while ( GCLK->STATUS.bit.SYNCBUSY);

    GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EIC));
    while ( GCLK->STATUS.bit.SYNCBUSY);
        
    TC3->COUNT16.CTRLA.bit.ENABLE = 0;
    while (TC3->COUNT16.STATUS.bit.SYNCBUSY);
    TC3->COUNT16.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT16;
    TC3->COUNT16.CTRLA.bit.PRESCALER |= TC_CTRLA_PRESCALER_DIV1_Val;
    while (TC3->COUNT16.STATUS.bit.SYNCBUSY);
    TC3->COUNT16.CTRLC.bit.CPTEN0 = 1;
    TC3->COUNT16.CTRLC.bit.CPTEN1 = 1;   
    while (TC3->COUNT16.STATUS.bit.SYNCBUSY);
    TC3->COUNT16.EVCTRL.bit.TCEI = 1;
    //TC3->COUNT16.EVCTRL.bit.TCINV = 1; // Optional invert
    TC3->COUNT16.EVCTRL.bit.EVACT = TC_EVCTRL_EVACT_PPW_Val;
    // Interrupts
    TC3->COUNT16.INTENSET.bit.MC0 = 1;
    //TC3->COUNT16.INTENSET.bit.MC1 = 1; // Not needed, can read out both in MC0 interrupt

    // Enable InterruptVector
    NVIC_EnableIRQ(TC3_IRQn);

    // Enable TC
    TC3->COUNT16.CTRLA.bit.ENABLE = 1;
    while (TC3->COUNT16.STATUS.bit.SYNCBUSY);

    PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;
     
    // EVSYS GCLK is needed for interrupts and sync path (so not now)
    //GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EVSYS_1);
    //while (GCLK->STATUS.bit.SYNCBUSY);
    REG_EVSYS_USER = EVSYS_USER_USER(EVSYS_ID_USER_TC3_EVU)|EVSYS_USER_CHANNEL(2); // Channel n-1 selected so 1 here
    while(!EVSYS->CHSTATUS.bit.USRRDY1);
        
    // EVSYS_CHANNEL_EDGSEL_BOTH_EDGES // not usable with  PATH_ASYNCHRONOUS
    REG_EVSYS_CHANNEL = EVSYS_CHANNEL_PATH_ASYNCHRONOUS|EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4)|EVSYS_CHANNEL_CHANNEL(1);
    while(EVSYS->CHSTATUS.bit.CHBUSY1);
    // Below interrupt is for testing the event (not possible with PATH_ASYNCHRONOUS)
    //EVSYS->INTENSET.reg = EVSYS_INTENSET_EVD1;
    //NVIC_EnableIRQ(EVSYS_IRQn);
}

void TC3_Handler()
{
    if (TC3->COUNT16.INTFLAG.bit.MC0) {
        // The interrupt flag is cleared by reading CC
        cap0[nCap] = TC3->COUNT16.CC[0].bit.CC;
        cap1[nCap] = TC3->COUNT16.CC[1].bit.CC;
        if (++nCap == sizeof(cap0)/sizeof(cap0[0])) {
            static volatile size_t done;
            done++;
            nCap = 0;
        }
    }       
}
#endif

int main(void)
{
    SystemInit();
    
    setupInput();
    setupTimer();

    while (1) {
    }
}

/Lars
 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks again for your quick answer, especially considering the amount of work that you must have done.

I'd tried some more with my application, and it at least captured the pulse width. I'll adapt it in line with your results, and report if it worked

In spite of its length, the SAMD21 datasheet seems to have many omissions and inaccuracies, a spell checker would also not been amiss

My application must do very accurate timing, and this section measures the exact CPU frequency by timing the period of the PPS signal from a GPS receiver (error 10-50ns). The PPS signal pin generates the appropriate event.

Best wishes, Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I at last persuaded the program to capture the period using an event. The TC3 with XOSC32M clock generates an event on overflow every second, TCC1 counted the period in units of DFFL48M/48. 

DFLL48M is not constant, the measured frequency varies by about +-6ppm, the value SYSCTRL->DFLLVAL.DIFF (the difference between the set reference frequency multiplier and the actual value) is 0 for about half the time, +-1 for about the same time, and rarely +-2.

If needed I can send the complete code on request

Thanks again for Lars' help

Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just wanted to say, was having problems getting the PPW and.or PWP working using the EIC to the EVSYS to the TC/TCC.  

 

This post help me determine that the EIC needed to be set to High Detect Edge, and the EVSYS needed to be set to Asynchronous.

 

Originally was getting the right period, but the pulse width was wrong.  Playing around with things at some point I got the pulse width to equal the period, but this wasnt helping.

 

I'm hoping by highlighting these two values may help someone else trying to figure this out.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Lajon wrote:

External signal directly to the TC for capture is not possible, i.e., this looks like a documentation error:

 To enable the capture from the IO pin, the Capture On Pin x Enable bit in CTRLC register (CTRLC.COPENx) must be written to '1'. 

 D21 has no such bits in TC CTRLC.

So it has to be an event, typically it would be from EIC (i.e., from one of the EXTINT). From my testing it will only work when setting up an asynchronous event. You need only one event btw, the edge detection happens in the TCC (or TC). The event user should be obvious since there is only one place where you can configure PPW and PWP (EVACT1[2:0]: Timer/Counter Event Input 1 Action for TCC, and TC has only one input event with setting in EVACT[2:0]: Event Action).

The example captures 128 periods and pulse widths from PA04. Select TCC or TC with the define USE_TCC. Put a breakpoint on the done++ lines to see the result. The first capture should be skipped, i.e., cap0[0] and cap1[0] will not be valid.

#include "sam.h"
#include <stdlib.h>

static volatile uint16_t cap0[128]; // Period with PPW capture
static volatile uint16_t cap1[128]; // Pulse width with PPW capture
static volatile size_t nCap;
#define USE_TCC

void setupInput(void)
{
    PM->APBAMASK.bit.EIC_ = 1;

    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EIC);
    while (GCLK->STATUS.bit.SYNCBUSY);
    
    // Input on PA04
    PORT->Group[0].PMUX[4/2].bit.PMUXE = MUX_PA04A_EIC_EXTINT4;
    const PORT_PINCFG_Type pincfg = {
        .bit.PMUXEN = 1,
        .bit.INEN = 1,
        .bit.PULLEN = 1
    };
    PORT->Group[0].PINCFG[4].reg = pincfg.reg;
   
    EIC->CONFIG[0].bit.SENSE4 = EIC_CONFIG_SENSE4_HIGH_Val; // None of RISE,FALL or BOTH work for this
    EIC->EVCTRL.bit.EXTINTEO4 = 1;
    
    // The EIC interrupt is only for verifying the input
    //REG_EIC_INTENSET = EIC_INTFLAG_EXTINT4;
    //NVIC_EnableIRQ(EIC_IRQn);
    while (EIC->STATUS.reg & EIC_STATUS_SYNCBUSY);
    EIC->CTRL.bit.ENABLE = 1;                  
    while (EIC->STATUS.reg & EIC_STATUS_SYNCBUSY); 
}

#ifdef USE_TCC
void setupTimer(void)
{
    PM->APBCMASK.bit.TCC0_ = 1;

    REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC0_TCC1;
    while (GCLK->STATUS.bit.SYNCBUSY);
    
    TCC0->CTRLA.bit.ENABLE = 0;
    while (TCC0->SYNCBUSY.bit.ENABLE);

    TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1 | TCC_CTRLA_CPTEN0 | TCC_CTRLA_CPTEN1;
    TCC0->PER.reg = 0xFFFFFF;
    while (TCC0->SYNCBUSY.bit.PER);

    TCC0->EVCTRL.reg = TCC_EVCTRL_TCEI1 |  // enable input event
        TCC_EVCTRL_EVACT1_PPW; // event action = PPW
        // | TCC_EVCTRL_MCEI0 | TCC_EVCTRL_MCEI1;

    // Interrupts
    TCC0->INTENSET.bit.MC0 = 1;
    //TCC0->INTENSET.bit.MC1 = 1; // Not needed, can read out both in MC0 interrupt
    NVIC_EnableIRQ(TCC0_IRQn);

    // Enable TCC
    TCC0->CTRLA.bit.ENABLE = 1;
    while (TCC0->SYNCBUSY.bit.ENABLE); // wait for sync

    PM->APBCMASK.bit.EVSYS_ = 1;
    // EVSYS GCLK is needed for interrupts and sync path (so not now)
    // GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EVSYS_1);
    // while (GCLK->STATUS.bit.SYNCBUSY);
    
    // TCC_EVCTRL_TCEI1 is used, must be matched with EVSYS_ID_USER_TCC0_EV_1 here
    REG_EVSYS_USER = EVSYS_USER_USER(EVSYS_ID_USER_TCC0_EV_1)|EVSYS_USER_CHANNEL(2); // Channel n-1 selected so 1 here
    while(!EVSYS->CHSTATUS.bit.USRRDY1);
    // EVSYS_CHANNEL_EDGSEL_BOTH_EDGES // not usable with  PATH_ASYNCHRONOUS
    // For this capture it looks like it needs to be PATH_ASYNCHRONOUS 
    REG_EVSYS_CHANNEL = EVSYS_CHANNEL_PATH_ASYNCHRONOUS|EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4)|EVSYS_CHANNEL_CHANNEL(1);
    while(EVSYS->CHSTATUS.bit.CHBUSY1);
    // Below interrupt is for testing the event (not possible with PATH_ASYNCHRONOUS)
    //EVSYS->INTENSET.reg = EVSYS_INTENSET_EVD1;
    //NVIC_EnableIRQ(EVSYS_IRQn);  
}

void TCC0_Handler()
{  
    if (TCC0->INTFLAG.bit.MC0) { 
        // The interrupt flag is cleared by reading CC
        cap0[nCap] = TCC0->CC[0].bit.CC;
        cap1[nCap] = TCC0->CC[1].bit.CC;
        if (++nCap == sizeof(cap0)/sizeof(cap0[0])) {
            static volatile size_t done;
            done++;
            nCap = 0;
        }     
    }
}
#else
void setupTimer(void)
{
    PM->APBCMASK.bit.TC3_ = 1;

    REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3;
    while ( GCLK->STATUS.bit.SYNCBUSY);

    GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EIC));
    while ( GCLK->STATUS.bit.SYNCBUSY);
        
    TC3->COUNT16.CTRLA.bit.ENABLE = 0;
    while (TC3->COUNT16.STATUS.bit.SYNCBUSY);
    TC3->COUNT16.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT16;
    TC3->COUNT16.CTRLA.bit.PRESCALER |= TC_CTRLA_PRESCALER_DIV1_Val;
    while (TC3->COUNT16.STATUS.bit.SYNCBUSY);
    TC3->COUNT16.CTRLC.bit.CPTEN0 = 1;
    TC3->COUNT16.CTRLC.bit.CPTEN1 = 1;   
    while (TC3->COUNT16.STATUS.bit.SYNCBUSY);
    TC3->COUNT16.EVCTRL.bit.TCEI = 1;
    //TC3->COUNT16.EVCTRL.bit.TCINV = 1; // Optional invert
    TC3->COUNT16.EVCTRL.bit.EVACT = TC_EVCTRL_EVACT_PPW_Val;
    // Interrupts
    TC3->COUNT16.INTENSET.bit.MC0 = 1;
    //TC3->COUNT16.INTENSET.bit.MC1 = 1; // Not needed, can read out both in MC0 interrupt

    // Enable InterruptVector
    NVIC_EnableIRQ(TC3_IRQn);

    // Enable TC
    TC3->COUNT16.CTRLA.bit.ENABLE = 1;
    while (TC3->COUNT16.STATUS.bit.SYNCBUSY);

    PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;
     
    // EVSYS GCLK is needed for interrupts and sync path (so not now)
    //GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EVSYS_1);
    //while (GCLK->STATUS.bit.SYNCBUSY);
    REG_EVSYS_USER = EVSYS_USER_USER(EVSYS_ID_USER_TC3_EVU)|EVSYS_USER_CHANNEL(2); // Channel n-1 selected so 1 here
    while(!EVSYS->CHSTATUS.bit.USRRDY1);
        
    // EVSYS_CHANNEL_EDGSEL_BOTH_EDGES // not usable with  PATH_ASYNCHRONOUS
    REG_EVSYS_CHANNEL = EVSYS_CHANNEL_PATH_ASYNCHRONOUS|EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4)|EVSYS_CHANNEL_CHANNEL(1);
    while(EVSYS->CHSTATUS.bit.CHBUSY1);
    // Below interrupt is for testing the event (not possible with PATH_ASYNCHRONOUS)
    //EVSYS->INTENSET.reg = EVSYS_INTENSET_EVD1;
    //NVIC_EnableIRQ(EVSYS_IRQn);
}

void TC3_Handler()
{
    if (TC3->COUNT16.INTFLAG.bit.MC0) {
        // The interrupt flag is cleared by reading CC
        cap0[nCap] = TC3->COUNT16.CC[0].bit.CC;
        cap1[nCap] = TC3->COUNT16.CC[1].bit.CC;
        if (++nCap == sizeof(cap0)/sizeof(cap0[0])) {
            static volatile size_t done;
            done++;
            nCap = 0;
        }
    }       
}
#endif

int main(void)
{
    SystemInit();
    
    setupInput();
    setupTimer();

    while (1) {
    }
}

/Lars

 

 

I have one problem, whenever i include the asf.h, the code is giving me errors. I hope you could help me out. This error occurs for ENABLE in compiler.h.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Add

#undef ENABLE

after the asf.h include

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks, i resolved the issue by renaming and works, I should have taken deleted my question but was busy with my boss so could not. thanks though i will try your solution also

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello , in the Port function multiplexing for SAM D21 you can found the option that can be used.

i.e  ->PA15  can be selected by WO[1] in TC3  or TCC0 WO[5].

 

Currently I'm in similar issue, I have everything configured  in ATMEL START, but CC always are 0.

 

Thanks.

Sergio Roche

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The WO are waveform outputs only on D21, check the section "6 Signal Descriptions List" :

Timer Counter - TCx

WO[1:0] Waveform Outputs   Output

This is what it looks like for C21:

Timer Counter - TCx

WO[1:0] Waveform Outputs / Capture Inputs   Digital

/Lars

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey guys, I'm new to embedded programming, and surfing this site works wonders, especially the topic here. combining similar discussions, I was able to correctly capturing period using TC, and the signal is routed using event generated by EIC.

 

I was able to continuously measure the period of a signal from a signal generator. I was using the PWP capture mode. No I want to be notified when, say, the signal stopped, and do something in the background, so I am thinking about interrupts.  Can TC generate any kind of interrupts after the measured signal stopped? Thanks.

 

Levi

Last Edited: Thu. Feb 25, 2021 - 10:12 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You might be able to use the overflow interrupt. Or you can add a counter in the capture interrupt and set that counter to 0 periodically (time depends on your expected signals, you can use another TC or TCC for this timing). If the counter is already 0 when you are about to clear it then there is no longer an input signal.

/Lars

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lars,

 

I'm curious about the first suggestion you have there since I prefer to use only a single TC instance. Here is my thought about using the overflow interrupt. As far as I know from the datasheet, when using the capture functionality, an interrupt is only generated when there is a valid value captured. The deployment stage will read a signal generated by a user who presses a switch repeatedly (creating a series of highs, hence generating a signal). The interval between those highs is expected to be <1000 ms, so by that requirement, it is possible to conclude that the signal has "stopped" when the highs are not followed by another signal once it reached 1000 ms. Is it possible to make use of overflow for this condition?

DS snip

 

Levi

Last Edited: Mon. Mar 1, 2021 - 03:26 AM