Event system/timer problem

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

I'm using a 32A4 running at 32MHz on the internal oscillator. I'm interfacing to a Parallax Ping ultrasonic sensor (on PORTC.0) which is triggered outside the code below. The Ping produces an ultrasonic pulse and then listens for the echo, producing a TTL pulse whose width (115 us - 18.5 ms) is proportional to the distance to an object. My immediate goal is to measure the width of this pulse.

The intent of this code is to connect PORTC.0 to TCC0 CCA (in pulse width capture mode) via the CH0MUX, poll the valid CCA interrupt flag, then read CCA when the flag is set (I'm not using any interrupts). My problem is CCA is always 0, even though the flag gets set.

I can tell from my scope that I'm getting a valid echo from the sensor. This also means that PORTC.0 is connected to the sensor since the pin triggers the pulse as an output and then must be switched to an input to receive the echo. You can see some commented code where I test PORTC.0 before starting to poll to make sure the input is working. I also make sure to clear the CCAIF flag before polling.

Any ideas about what I'm doing wrong? Thanks.

unsigned int GetPW(void)
{
    unsigned int y = 0;

    // Set input sense/config. to both edges for PORTC.0 (0x00)

    PORTC.PIN0CTRL = (PORTC.PIN0CTRL & ~PORT_ISC_gm) | PORT_ISC_BOTHEDGES_gc;     

    // Change PC0 to input.

    PORTC.DIRCLR = PIN0_bm;       

    // Connect PORTC.0 to channel 0 mux (0x60).

    EVSYS.CH0MUX = EVSYS_CHMUX_PORTC_PIN0_gc;     

    // Set TCC0 clock:  32 MHz / 4 / 8 = 1 us.  Pulse is supposed to be between 
    // 115 us and 18.5 ms.

    TCC0.PER = 4;
    TCC0.CTRLA = ( TCC0.CTRLA & ~TC0_CLKSEL_gm ) | TC_CLKSEL_DIV8_gc;

    // Enable capture operation on channel A, normal mode (0x10)

    TCC0.CTRLB = TC0_CCAEN_bm | TC_WGMODE_NORMAL_gc;    

    // Set event action to PW capture and event channel to 0 (0xC8)
       
    TCC0.CTRLD = TC_EVACT_PW_gc | TC_EVSEL_CH0_gc;      

    // Clear flags by wirting to them (just in case either's set).

    TCC0.INTFLAGS |= (TC0_CCAIF_bm | TC0_ERRIF_bm);
//    while ((PORTC.IN & 1) == 0);

    // Wait for buffer valid or overflow

    while (((TCC0.INTFLAGS & TC0_CCAIF_bm) == 0) & 
           ((TCC0.INTFLAGS & TC0_ERRIF_bm) == 0))   
        y = TCC0.CCA;
    if (TCC0.INTFLAGS & TC0_CCAIF_bm)     // We have a valid buffer
    {
        y = TCC0.CCA;

        // The interrupt flag should have been cleared by reading the CC register, but clear it
        // explicitly with a write, just in case.

        TCC0.INTFLAGS |= TC0_CCAIF_bm;     
    } else              //  What to do in the event of a buffer overflow?
    {
        
        // Clear overflow flag by writing a 1 to it.

        TCC0.INTFLAGS |= TC0_ERRIF_bm;     
    }
    return y;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Update: I tested the event system setup by connecting the input to an output pin which goes high and low along with the input (plus a lag), so the problem doesn't appear to be with my event system configuration.

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

Problem solved.

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

I chose to use the CCA interrupt rather than polling the CCAIF, but either method works. Non-ASF code is attached.

Attachment(s): 

Gamu The Killer Narwhal
Portland, OR, US
_________________
Atmel Studio 6.2
Windows 8.1 Pro
Xplained boards mostly