Skip to main content
Skip table of contents

4.1.6 - Timers & Counters [U3 Datasheet]

All timer/counter feature configurations should be set with a single transaction using using eTCConfig; AddRequest, Go/GoOne, and GetResult/GetNextResult; or eAddGoGet. Timer/counter data can be obtained using any of AddRequest, Go/GoOne, and GetResult/GetNextResult; eGet/ePut; or eAddGoGet. In applicable functions such as eGet/ePut, the x1 parameter is unused for timers/counters, so it can be set to 0.

There are eight IOTypes used to write or read timer and counter information:

LJ_ioGET_COUNTER
LJ_ioPUT_COUNTER_ENABLE
LJ_ioGET_COUNTER_ENABLE
LJ_ioPUT_COUNTER_RESET //Sets flag to reset on next read.

LJ_ioGET_TIMER
LJ_ioPUT_TIMER_VALUE
LJ_ioPUT_TIMER_MODE
LJ_ioGET_TIMER_MODE

In addition to specifying the channel number, the following mode constants are passed in the value parameter when doing a request with the timer mode IOType:

LJ_tmPWM16 //16-bit PWM output
LJ_tmPWM8 //8-bit PWM output
LJ_tmRISINGEDGES32 //Period input (32-bit, rising edges)
LJ_tmFALLINGEDGES32 //Period input (32-bit, falling edges)
LJ_tmDUTYCYCLE //Duty cycle input
LJ_tmFIRMCOUNTER //Firmware counter input
LJ_tmFIRMCOUNTERDEBOUNCE //Firmware counter input (with debounce)
LJ_tmFREQOUT //Frequency output
LJ_tmQUAD //Quadrature input
LJ_tmTIMERSTOP //Timer stop input (odd timers only)
LJ_tmSYSTIMERLOW //System timer low read
LJ_tmSYSTIMERHIGH //System timer high read
LJ_tmRISINGEDGES16 //Period input (16-bit, rising edges)
LJ_tmFALLINGEDGES16 //Period input (16-bit, falling edges)
LJ_tmLINETOLINE //Line-to-line input

The following are special channels, used with the get/put config IOTypes, to configure a parameter that applies to all timers/counters:

LJ_chNUMBER_TIMERS_ENABLED //0-2
LJ_chTIMER_CLOCK_BASE //Set with the constant values below. Gets the low-level value.
LJ_chTIMER_CLOCK_DIVISOR //0-255, where 0=256
LJ_chTIMER_COUNTER_PIN_OFFSET //4-8 only starting with hardware rev 1.30.

With the clock base special channel above, the following constants are passed in the value parameter to select the frequency:

LJ_tc4MHZ //4 MHz clock base
LJ_tc12MHZ //12 MHz clock base
LJ_tc48MHZ //48 MHz clock base
LJ_tc1MHZ_DIV //1 MHz clock base w/ divisor (no Counter0)
LJ_tc4MHZ_DIV //4 MHz clock base w/ divisor (no Counter0)
LJ_tc12MHZ_DIV //12 MHz clock base w/ divisor (no Counter0)
LJ_tc48MHZ_DIV //48 MHz clock base w/ divisor (no Counter0)
LJ_tcSYS //Equivalent to LJ_tc48MHZ

Constant values used to set (put) the timer clock base differ from the low-level timer clock base retrieved (get) from the device. Constant value - 20 = low-level value. Table 2.9-2 documents these values.

Following is example pseudocode for configuring various timers and a hardware counter:

//Execute the pin_configuration_reset IOType so that all
//pin assignments are in the factory default condition.
//The ePut function is used, which combines the add/go/get.
ePut (lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0);


//First, an add/go/get block to configure the timers and counters.

//Set the pin offset to 4, which causes the timers to start on FIO4.
AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_COUNTER_PIN_OFFSET, 4, 0, 0);

//Enable both timers. They will use FIO4-FIO5
AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 2, 0, 0);

//Make sure Counter0 is disabled.
AddRequest (lngHandle, LJ_ioPUT_COUNTER_ENABLE, 0, 0, 0, 0);

//Enable Counter1. It will use the next available line, FIO6.
AddRequest (lngHandle, LJ_ioPUT_COUNTER_ENABLE, 1, 1, 0, 0);

//All output timers use the same timer clock, configured here. The
//base clock is set to 48MHZ_DIV, meaning that the clock divisor
//is supported and Counter0 is not available. Note that this timer
//clock base is not valid with U3 hardware version 1.20.
AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc48MHZ_DIV, 0, 0);

//Set the timer clock divisor to 48, creating a 1 MHz timer clock.
AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, 48, 0, 0);

//Configure Timer0 as 8-bit PWM. It will have a frequency
//of 1M/256 = 3906.25 Hz.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 0, LJ_tmPWM8, 0, 0);

//Initialize the 8-bit PWM with a 50% duty cycle.
AddRequest (lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 32768, 0, 0);

//Configure Timer1 as duty cycle input.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 1, LJ_tmDUTYCYCLE, 0, 0);

//Execute the requests.
GoOne (lngHandle);

The following pseudocode demonstrates reading input timers/counters and updating the values of output timers. The e-functions are used in the following pseudocode, but some applications might combine the following calls into a single add/go/get block so that a single low-level call is used.

//Change Timer0 PWM duty cycle to 25%.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 0, 49152, 0);

//Read duty-cycle from Timer1.
eGet (lngHandle, LJ_ioGET_TIMER, 1, &dblValue, 0);

//The duty cycle read returns a 32-bit value where the
//least significant word (LSW) represents the high time
//and the most significant word (MSW) represents the low
//time. The times returned are the number of cycles of
//the timer clock. In this case the timer clock was set
//to 1 MHz, so each cycle is 1 microsecond.
dblHighCycles = (double)(((unsigned long)dblValue) % (65536));
dblLowCycles = (double)(((unsigned long)dblValue) / (65536));
dblDutyCycle = 100 * dblHighCycles / (dblHighCycles + dblLowCycles));
dblHighTime = 0.000001 * dblHighCycles;
dblLowTime = 0.000001 * dblLowCycles;

//Read the count from Counter1. This is an unsigned 32-bit value.
eGet (lngHandle, LJ_ioGET_COUNTER, 1, &dblValue, 0);

Following is pseudocode to reset the input timer and the counter:

//Reset the duty-cycle measurement (Timer1) to zero, by writing
//a value of zero. The duty-cycle measurement is continuously
//updated, so a reset is normally not needed, but one reason
//to reset to zero is to detect whether there has been a new
//measurement or not.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 1, 0, 0);

//Read & reset Counter1. Note that with the U3 reset is just
//setting a driver flag to reset on the next read, so reset
//is generally combined with a read in an add/go/get block.
//The order of the read & reset within the block does not
//matter ... the read will always happen right before the reset.
AddRequest (lngHandle, LJ_ioGET_COUNTER, 1, 0, 0, 0);
AddRequest (lngHandle, LJ_ioPUT_COUNTER_RESET, 1, 1, 0, 0);
GoOne (lngHandle);
GetResult (lngHandle, LJ_ioGET_COUNTER, 1, &dblValue);
GetResult (lngHandle, LJ_ioPUT_COUNTER_RESET, 1, 0);

Note that if a timer/counter is read and reset at the same time (in the same Add/Go/Get block), the read will return the value just before reset.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.