Skip to main content
Skip table of contents

4.1.6 - Timers & Counters [UE9 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; 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 //UpdateConfig will be set.
LJ_ioGET_COUNTER_ENABLE
LJ_ioPUT_COUNTER_RESET

LJ_ioGET_TIMER
LJ_ioPUT_TIMER_VALUE
LJ_ioPUT_TIMER_MODE //UpdateConfig will be set.
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)

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 //UpdateConfig will be set if writing.
LJ_chTIMER_CLOCK_BASE //UpdateConfig will be set if writing.
LJ_chTIMER_CLOCK_DIVISOR //UpdateConfig will be set if writing.

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

LJ_tc750KHZ //Fixed 750 kHz clock base.
LJ_tcSYS //System clock: 48 MHz.

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

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

//Enable all 6 timers. Timer0-Timer5 will appear on FIO0-FIO5.
AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 6, 0, 0);

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

//All output timers use the same timer clock, which is
//determined by the base clock divided by the clock divisor.
//Set the timer clock base to 48 MHz.
AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tcSYS, 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 frequency output.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 1, LJ_tmFREQOUT, 0, 0);

//Initialize frequency output at 1M/(2*5) = 100 kHz.
AddRequest (lngHandle, LJ_ioPUT_TIMER_VALUE, 1, 5, 0, 0);

//Configure Timer2 as a firmware counter with debounce.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 2, LJ_tmFIRMCOUNTERDEBOUNCE, 0, 0);

//Configure Timer2 for negative edges (bit 8 of value clear) with
//a debounce period of 87 ms.
AddRequest (lngHandle, LJ_ioPUT_TIMER_VALUE, 2, 1, 0, 0);

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

//Configure Timers 4 & 5 as quadrature input. Two timers
//are needed for phases A & B.
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 4, LJ_tmQUAD, 0, 0);
AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 5, LJ_tmQUAD, 0, 0);

//Execute the requests.
GoOne (lngHandle);

The LabJackUD driver uses the low-level TimerCounter function. That function has a single UpdateConfig bit that must be set to change modes, clock configuration, or enabled/disabled status. When the UpdateConfig bit is set, all timers and counters are re-initialized. The following pseudocode demonstrates reading input timers/counters and updating the values of output timers, which does not cause the UpdateConfig bit to be set. 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);

//Change Timer1 frequency output to 1M/(2*50) = 10 kHz.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 1, 50, 0);

//Read count from Timer2. This is an unsigned 32-bit value.
eGet (lngHandle, LJ_ioGET_TIMER, 2, &dblValue, 0);

//Read duty-cycle from Timer3.
eGet (lngHandle, LJ_ioGET_TIMER, 3, &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 quadrature count from Timer4. Timer5 would return the
//same value. This is a signed 32-bit value.
eGet (lngHandle, LJ_ioGET_TIMER, 4, &dblValue, 0);

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

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

//Reset the firmware counter (Timer2) to zero, by writing a
//value of zero.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 2, 0, 0);

//Reset the duty-cycle measurement (Timer3) 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, 3, 0, 0);

//Reset the quadrature counters (Timer4 & Timer5) to zero, by
//writing a value of zero to either one.
ePut (lngHandle, LJ_ioPUT_TIMER_VALUE, 4, 0, 0);

//Reset Counter0 to zero.
ePut (lngHandle, LJ_ioPUT_COUNTER_RESET, 0, 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.