Home/Support/Support Forum/How do I use the capture counter on the Rabbit 5000 to count pulses?
Welcome to Digi Forum, where you can ask questions and receive answers from other members of the community.

How do I use the capture counter on the Rabbit 5000 to count pulses?

0 votes
I would like to use the capture counter on the Rabbit 5000 to count pulses. There is no Start capture nor End capture signal. I simply want to reset the counter and read it later. The documentation does not quite explain how to define the input signal but I gather that the port/pin assigned to the start capture signal is the input signal (ask_larry/2009/0521). Neither does the documentation say where to read the counter. I tried reading the IC(L/M)nR registers but they stay at 0.
asked Feb 14, 2015 in Rabbit Software by ygrignon New to the Community (2 points)

Please log in or register to answer this question.

1 Answer

+1 vote
Have a look at the Samples\Rabbit4000\ic_test.c and see if that sheds some light on what you are trying to do.

I think setting b6/b7 of the ICCR will allow counting pulse edges on the capture inputs. You will have to configure the ICTxR register to determine if you want to count rising/falling/both edges.

Regards,
Peter
answered Feb 15, 2015 by petermcs Veteran of the Digi Community (1,130 points)
This example uses the input pin to gate an internal clock to the counter.  This is not what I need.  I have also seen an example counting input pulses gated by an internal timer.  This is closer to what I need but I want the gate to be always opened.
It does in deed work that way but it gives a good starting point in terms of showing how to access the registers for configuring the Input Capture peripheral and reading the results.

I'd be inclined to start with this and see what changing the ICCR b6 and b7 achieves in terms of setting input count mode.
Thanks Peter for sticking with this.
I thought that I would describe what I am doing.  I was hoping that I would spot the problem while explaining but no.  You might.  Here goes:
1. Initialize input pins PD1,3
/* Initialize PDO to output for heartbeat led, rest to input for capture ctr */
   WrPortI(PDDDR, &PDDDRShadow, 0x01);
   // Make sure PD0 not set to alternate function
   WrPortI(PDFR,  &PDFRShadow, 0x0);
2. Initialize the 2 capture counters
/* configure capture counters ICC1 & ICC2 */
   WrPortI (ICCR,  NULL, 0xC0);        // count mode
   WrPortI (ICT1R, NULL, 0x84);            // countinuous count, start on 1st positive edge
   WrPortI (ICT2R, NULL, 0x84);            // countinuous count, start on 1st positive edge
   WrPortI (ICS1R, NULL, 0x44);          // source port D1
   WrPortI (ICS2R, NULL, 0x55);          // source port D3
3. Reset counters
#define CLRCTRS    WrPortI(ICCSR,  NULL, 0x0C) // reset counters
4. Read counter for valve 1
/*******************************************************************************
        Returns the cycle cntr of vlv1
*******************************************************************************/
unsigned RdVlv1Ctr (void)             // read cycle cntr of vlv1
{
   unsigned x;
   x=RdPortI(ICL2R);                  // reading lsb locks msb, must be first
   return x+=RdPortI(ICM2R)<<8;
}

The purpose of the program is to measure the time necessary for a motorized valve to go from limit stop to limit stop.  The valve motor is fed with 24Vac 60 Hz through a 1 ohm resistor.  When the valve is moving, a small voltage is developed across the resistor, squared and amplified and fed to the capture input pin.  The capture counter will count AC cycles while the valve is moving.  The valve takes approximately 30 seconds to go from stop to stop.  This should generate 30x60=1800 cycles.  The program is
    CLRCTRS;
    TurnOnValve();
    DelaySec(60);
    cnt1=RdVlv1Ctr();
cnt1 always returns 0.
I think the ICTxR setting is wrong. Reading the instructions at section 24.3.5 :

24.3.5 Count Mode
The following steps explain how to count pulses.
1. Set the counter to run continuously until the stop condition occurs and to latch on the
start condition.
2. If an interrupt is desired at a particular count, write that value into the LSB and MSB
registers.
3. Set the start condition for the pulse type desired.
4. Reset the counter by writing to ICCSR.
5. Reading the counter at any time will give the current count.

ICTxR should probably have 0x94
Well I tried setting ICTnR to 0x94 to no avail.  Still 0.  I am giving up on the counter and will do it another way.
The documentation is misleading.  The doc for bits 5:4 of ICTnR says to set to 00 to "Disable the count latching function. In this case, and with Counter operation only, the ICLxR and ICMxR return the programmed match value.".  I did not want to latch and I hoped that the part about returning the programmed match value was a mistake.
You suggested to use 01 to "Latch the count on the Stop condition only.".  This makes sense as there is no stop condition in counter mode, bits 1:0 are documented as "Ignore the ending input. These two bits are ignored in Counter operation.".  I was hopeful that it might work.  Thanks for your help.  At least now I feel confident that I did not miss something stupid.
Regards,
Yves
I've tested the following on an RCM5700 board with digital I/O accessory board using sw1 linked to PC5 with a flying lead and it works fine (I started with the test_ic.c and modified it to count pulses instead of timing them).

void main(void)
{
    char capture_status;
    unsigned multiplier;
    unsigned long pulse_count;
    unsigned long temp;

    // Set PC5 as an input.
    WrPortI(PCDDR, &PCDDRShadow, PCDDRShadow & 0xDF);

    // PC5 is pulse capture pin for channel 1
    // Available pins are Ports C, D and E pins 1,3,5 and 7
    WrPortI(ICS1R, NULL, 0x22);

    // use freq_divider as basis for input capture prescaler
    //  (freq_divider-1) runs at 19200*16Hz; for better range multiply by the
    //  largest value that keeps the result within the 8-bit unsigned range
    for (multiplier = 1; 256u >= freq_divider*(1+multiplier); ++multiplier);
    WrPortI(TAT8R, NULL, (freq_divider*multiplier)-1);    // (TA8 prescaler)
    WrPortI(ICCR, NULL, 0xC0);        // count operation; no interrupts

    // run counter continuously
    // latch count on start
    // start is both edges
    WrPortI(ICT1R, NULL, 0xAC);
    WrPortI(ICCSR, NULL, 0x0C);    // zero out counters

        pulse_count = RdPortI(ICL1R);
        pulse_count += RdPortI(ICM1R) * 256L;

    while(1)
    {
        temp = RdPortI(ICL1R);
        temp += RdPortI(ICM1R) * 256L;
        if(temp != pulse_count)
        {
            printf("pulse count = %d\n", (int)temp);
            pulse_count = temp;
        }
    }
}
There are 3 differences between your code and mine:
1. I am using pin D1 as input instead of C5 and my ICS1R reflects that difference;
2. You specify start condition as both edges and I specify positive edge.  I don't think that it should make a difference especially that there is no need for a start condition as we are counting continuously;
3. You configured TA8 and I did not.  I suspect that is the big difference but I fail to see why we need TA8 or a scaled down perclk when we are continuously counting input pulses with no gating.
As I mentioned before, I have used a software approach to solve the problem easily but I am still curious.
Thanks,
Yves
The start condition just determines which edge or edges are counted, I've tried all three settings and they work.
The TA8 code is directly from the test_ic.c example and I just left it inb. I haven't tried removing it but there is the following paragraph in the manual:

In the input-count mode the channel simply increments the counter each time a desired
edge is detected. The start condition is enabled by the first Timer A8 clock after the mode
is selected and the stop condition generated when the count matches the value written into
the counter registers; this allows an interrupt to be generated when a particular count is
reached.

This might be why it is needed...
Regards,
Peter
Most likely is.  How could I have missed that!  Thanks again Peter.
...