4.3.6 - Timers & Counters [U3 Datasheet] | LabJack
« Close

Datasheets and User Guides

App Notes

Software & Driver


4.3.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_ioPUT_COUNTER_RESET    //Sets flag to reset on next read.


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_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.


Hi, I wanna know if there any way to make U3 output TWO independent PWM? Maybe by using Counter0 as TimerClockDivisor register for Timer0, likewise, Counter1 for Timer1

By independent you mean different frequencies?  No, all timers use the same clock so the only way to get different frequencies is by using different modes on different timers (PWM16, PWM8, FreqOut).  If the frequencies are low enough, you can just toggle the lines through software timing rather than using the U3 timers.


there is no definition for the Timer-Mode 14 like LJ_tm... (line-to-line Measurement) up to now in the header-file. Is there already a definition in the dll? Or is it possible to update the dll and the header-file? It would be much easier to develop a Labview-File with the update.

Thank you


We have now added this to the driver.  It will be available in the next release.  The constant is LJ_tmLINETOLINE.


I am using your pseudo code to get counter 1 value with .net interface
What is the correct enum value for third parameter ch? LabJack.LabJackUD.LJUD.CHANNEL.? Cannot just put 1 there, it needs an enum value.
//Read the count from Counter1.  This is an unsigned 32-bit value.
LJUD.eGet(labJackHandle, LJUD.IO.GET_COUNTER, ch, ref val, 0);


You should be able to cast the parameter with the following code: LJUD.eGet(labJackHandle, LJUD.IO.GET_COUNTER, (LJUD.CHANNEL) ch, ref val, 0);

Is it possible to run a PWM continuously while using other Labjack Functions? 

I would like to run a 16bit PWM while using other features of the Labjack, however, the PWM turns on momentarily then turns off when I try this.

Thanks for your help.

Yes.  PWM is created by hardware and should not be affected by other operations.  I suggest you post on our forum and show snippets of you code that are causing problems.

I can't seem to properly reset the counters. Im using VB and I use the code below to reset counter 0 (and just change the first 0 to a 1 for counter1) but it does not seem to actually reset the counters (Am I doing something wrong?). The way I have had better success is with just actually recalling the set up of the counters but that causes both counters to reset. If i only want one to reset what should I do?

LJUD.ePut(device.ljhandle, LJUD.IO.PUT_COUNTER_RESET, 0, 1, 0)

Perhaps you are running into the details from the end of this section above?  1) The reset does not get sent to the device until you do a read.  2) That read will return the value read just before the count is set to 0.