Frequency Capture Issue: values from Timer TCE0 appearing on TCC1 (Xmega)

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

--------------------------------------------------------------------------------------------

Controller: ATxmega128A3U

Compiler: GCC (on Atmel Studio 7)

 

Code-Name for the three timers on frequency capture mode are "A", "B" and "C":

 

Timer "A": TCF0 -> PORTF - PIN0 ->  OC0A

Timer "B": TCC1 -> PORTC - PIN5 ->  OC1B

Timer "C": TCE0 -> PORTE - PIN0 ->  OC0A

 

Input Signals with Frequency between: 10Hz < F < 900Hz 

--------------------------------------------------------------------------------------------

 

I have successfully configured and tested the Frequency Capture feature on two separate Timers: TCF0 (Timer "A") and TCE0 (Timer "C") on a ATxmega128A3U. 

 

When using the same configuration on a third Timer TCC1 (Timer "B") I noticed that not only the values of the input signal are not being "captured" but also the exact values from Timer TCE0 (Timer "C") are being saved on the respective TCC1.CCB register of Timer TCC1.

 

I have tried the following to find out what the problem might be but without success:

 

  1. I deactivated Timer "A" and "C" to only test only Timer "B" -> no values on TCC1.CCB appear
  2. ...at the same time I deactivated Timer TCC0 (which is generating a PWM signal on PORTC - PIN1) to verify if for some reason this affects Timer TCC1 (Timer "B") on PORTC - PIN5 ->  no difference ->no values on TCC1.CCB
  3. I verified with a scope that the actual input signal is going all the way to PORTC - PIN5 -> it is there
  4. I verified that the PIN5 of PORTC was sensing the rising edge of the input  signal by putting a small piece of code and a breakpoint after the PORT configurations (before the main program and activation of the timers) and it does sense the signal correctly
  5. (as INFO: SPI is being used and active but not on PORC)
  6. I also configured Timer TCC1 as a PWM generator and after that also as a normal timer to change program variables every 100ms, and both functionalities work fine. So only frequency capture does not...

 

Any idea of what the problem could be? I would really appreciate any help.

 

Here is the code with the configurations:

 

* PORTs

 


//Timer "A"
PORTF.PIN0CTRL = PORT_OPC_PULLUP_gc  | PORT_ISC_RISING_gc;

...
//Timer "B"
PORTC.PIN5CTRL = PORT_OPC_PULLUP_gc  | PORT_ISC_RISING_gc;

...
//Timer "C"

PORTE.PIN0CTRL = PORT_OPC_PULLUP_gc  | PORT_ISC_RISING_gc;

* TIMERs

 

//------------------------------------------------
// Periode/TOP:
//------------------------------------------------
TCF0.PER = 0xFFFF;
TCC1.PER = 0xFFFF;
TCE0.PER = 0xFFFF;

//------------------------------------------------
// Event System Channels
//------------------------------------------------
EVSYS.CH0MUX = EVSYS_CHMUX_PORTF_PIN0_gc;
EVSYS.CH0CTRL = EVSYS_DIGFILT_8SAMPLES_gc;

EVSYS.CH1MUX = EVSYS_CHMUX_PORTC_PIN5_gc;
EVSYS.CH1CTRL = EVSYS_DIGFILT_8SAMPLES_gc;

EVSYS.CH2MUX = EVSYS_CHMUX_PORTE_PIN0_gc;
EVSYS.CH2CTRL = EVSYS_DIGFILT_8SAMPLES_gc;	

//------------------------------------------------
// Frequency Capture Mode
//------------------------------------------------
TCF0.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH0_gc;
TCC1.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH1_gc;
TCE0.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH2_gc;

//------------------------------------------------
// - CCxEN: Capture Enable on Pins...
//------------------------------------------------
TCF0.CTRLB = TC0_CCAEN_bm;
TCC1.CTRLB = TC1_CCBEN_bm;
TCE0.CTRLB = TC0_CCAEN_bm;

//------------------------------------------------
// Compare or Capture x Interrupt Level:
//------------------------------------------------
//TCF0.INTCTRLB = TC_OVFINTLVL_LO_gc;	// NOT USED YET
//TCF0.INTCTRLB = TC_CCAINTLVL_LO_gc;

//------------------------------------------------
//  Clock source:
//------------------------------------------------
TCF0.CTRLA = TC_CLKSEL_DIV256_gc;
TCC1.CTRLA = TC_CLKSEL_DIV256_gc;
TCE0.CTRLA = TC_CLKSEL_DIV256_gc;	

 

* Calculation of the frequency on the main loop (not on ISR)

 

frequency_capture_TIMER_A = F_TIMER / TCF0.CCA;

frequency_capture_TIMER_B = F_TIMER / TCC1.CCB;

frequency_capture_TIMER_C = F_TIMER / TCE0.CCA;

 

EDIT: Test #6 on the list

This topic has a solution.
Last Edited: Wed. Nov 8, 2017 - 12:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can capture everything with just TCF0, but do you really have to use TCC1 and TCE0?

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

kabasan wrote:

You can capture everything with just TCF0, but do you really have to use TCC1 and TCE0?

 

As far as I know, that would only work in "normal" capture mode, where a time stamp is given to each event but the timer counts up to TOP without being reset, no?.

 

In Frequency Capture Mode the counter is reset on each edge sense.

 

Xmega Manual AU. 14.7.2 Frequency Capture. Page 170:

 

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

By simple trial and error, I have made the program work but it seems to be a problem somewhere, either on my configurations (or lack of them either on the event system or on the timer/counters) or with the internal addresses of the peripherals of the controller.

 

It appears that 

TCC1.CTRLD 

Takes the data from a different event channel than the one being selected (e.g. TC_EVSEL_CH4_gc). In fact, it takes the data from the immediate following channel of the event system. This part of the Timer/Counter configurations made it finally work:

    //------------------------------------------------
    // Event System Channels
    //------------------------------------------------
    EVSYS.CH0MUX = EVSYS_CHMUX_PORTF_PIN0_gc;          //FOR TIMER: TCF0 (Timer "A") -> CHANNEL #0
    EVSYS.CH0CTRL = EVSYS_DIGFILT_8SAMPLES_gc;

    EVSYS.CH5MUX = EVSYS_CHMUX_PORTC_PIN5_gc;          //FOR TIMER: TCC1 (Timer "B") -> CHANNEL #5     
    EVSYS.CH5CTRL = EVSYS_DIGFILT_8SAMPLES_gc;

    EVSYS.CH7MUX = EVSYS_CHMUX_PORTE_PIN0_gc;          //FOR TIMER: TCE0 (Timer "C") -> CHANNEL #7
    EVSYS.CH7CTRL = EVSYS_DIGFILT_8SAMPLES_gc;

    //----------------------------------------------------------------
    // Bit 7:5 – EVACT[2:0]: Event Action -> FRQ (Frequency capture)
    // Bit 3:0 – EVSEL[3:0]:Timer Event Source Select
    //----------------------------------------------------------------
    TCF0.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH0_gc;
    TCC1.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH4_gc; // IT TAKES THE DATA FROM CHANNEL #5, NOT CHANNEL #4 OF THE EVENT SYSTEM!!!??????????????
    TCE0.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH7_gc;

 

The question is: why do Timers TCF0 and TCE0 take the data from the exact event channel (and corresponding pin) being selected on CTRLD but Timer TCC1 does not???

 

I have checked every single bit of registers TCC1.CTRLD and EVSYS.CH5MUX and compared them with the expected values using the Xmega Manual AU and all seems to be fine, but it does not work unless I use that different channel selection on TCC1.CTRLD.

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From the AU Manual:

 

Greg Muth

Portland, OR, US

Atmel Studio 7.0 on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

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

Hi Greg. Thanks a lot for pointing out that part of the docu. I thought I had understood it when I read it a while ago. Apparently, I had not...

 

The way it must be configured (and the explanation itself) was just a bit unclear and indirect at least for me...

 

So that means that my original mistake was that:

 

TCF0.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH0_gc; 

Assigned 

  • Event CHANNEL 0 to TCF0.CCA -> correct
  • Event CHANNEL 1 to TCF0.CCB 
  • Event CHANNEL 2 to TCF0.CCC 
  • Event CHANNEL 3 to TCF0.CCD 

 

and:

TCC1.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH1_gc; 
  • Event CHANNEL 1 to TCC1.CCA 
  • Event  CHANNEL 2 to TCC1.CCB -> (the Timer CC channel I need from PORTC.5) Was automatically assigned to this Event channel, which contains info from the other Timer TCE0.CCA because of "EVSYS.CH2MUX = EVSYS_CHMUX_PORTE_PIN0_gc; "

 

also:

TCE0.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH2_gc;
  • Event  CHANNEL 2 to TCE0.CCA -> correct for this Timer
  • Event CHANNEL 3 to TCE0.CCB 
  • Event CHANNEL 4 to TCE0.CCC 
  • Event CHANNEL 5 to TCE0.CCD 

 

Last Edited: Wed. Nov 8, 2017 - 12:57 PM