How to Use Timers in dsPic Microcontrollers
The author completed his final year engineering project with the dsPic micro-controllers, gaining extensive insight in these devices.
A timer module is an important peripheral inside a dsPic micro controller and can be used in a variety of applications.
This tutorial will make use of ready C-language code examples, coded in MplabX IDE and tested on a Microchip dsPic30f4011 micro-controller, to walk you through the process of initializing and configuring timers for your dsPic applications.
Introduction to the Timer Module in dsPic30f and dsPic33f devices
The timer module in dsPic30f series devices contains a total of five 16-bit timers, namely:
- Timers 1 through 5.
Similarly, a dspic33f series device contains up to nine 16-bit timers, namely:
- Timers 1 through 9.
Each of these timers are grouped into three types, Type A, Type B, and Type C, depending on their special characteristics.
Type - A | Type - B | Type - C |
---|---|---|
Can be operated from low power 32 Khz oscillator. | Can be concatenated with Type - C timer to form 32 - bit timer.** | Can be concatenated with Type - B timer to form 32 - bit timer.** |
Can run in Asynchronous mode with external source. | - | Has the ability to trigger A/D conversion. |
External clock source can be synchronized with internal clock | External clock source is always synchronized with internal clock.* | External clock source is always synchronized with internal clock.* |
Timer Modes of Operation in dsPic30f and dsPic33f Devices
In addition to being grouped into Type A, B, or C, each timer can be operated in four different modes:
- Timer Mode
- Gated Timer Mode
- Synchronous Counter Mode
- Asynchronous Counter Mode
Timer Mode | Gated Timer Mode | Synchronous Counter Mode | Asynchronous Counter Mode |
---|---|---|---|
Increments by one on every rising edge of the input clock | Increments by one on every rising edge of the input clock as long as the external gate signal at the TxCK pin is high | Increments by one on every rising edge of the input clock | Increments by one on every rising edge of the input clock |
Internal clock is used | Internal clock is used | External clock is used on TxCK pin | External clock is used on TxCK pin |
_ | _ | External and internal device clock is synchronized | External and internal device clock is not synchronized |
Interrupt is generated on period match | Interrupt is generated on falling edge of the TxCK pin | Interrupt is generated on period match | Interrupt is generated on period match |
Example Code to Initialize a Timer for dsPic30f and dsPic33f
void init_Timer( void )
{
T1CONbits.TON = 1; //Activate the timer module
T1CONbits.TCKPS = 0; //Select input clock prescaler as 1:1
T1CONbits.TGATE = 0; //Disable Gate Time Accumulation Mode
T1CONbits.TCS = 0; //Select internal clock as the timer clock source
T1CONbits.TSYNC = 0; //External clock source is left unsynchronized
PR1 = 0xFFFF;
}
General Procedure to Initialize a Timer in dsPic30f and dsPic33f MicroController
The following general procedure can be followed when initializing a timer for any application:
- Decide which timer to use.
- Decide if a 16-bit timer is required or a 32-bit timer is required.
- Decide the timer mode of operation.
- Set the clock pre-scaler.
- Decide if a timer interrupt or any other special event trigger is required.
1) Which Timer to Use
Each of the timers can be enabled by the TON bit in the TxCON register, where 'x' being the number of timer that is to be enabled.
In our example code, we have enabled Timer 1 by setting the TON bit in the T1CON register to 1.
2) 16-bit Timer or 32-bit Timer?
Type-B and Type-C timers can be combined to operate as a single 32-bit timer. When combined, configuration of Type-B timer will prevail over the Type-C timer.
- In a dsPic30f device, Timers 2 and 3 can be concatenated in one 32-bit timer.
- dsPic33f devices have more then one 32-bit timer pairs where timers 2/3, 4/5, 6/7 and 8/9 can also form 32-bit timer pairs.
For this purpose, the T32 bit in the TxCON register of a Type-B timer should be set to 1.
TxCON.T32* | Timer Configuaration |
---|---|
1 | Concatenated with its other timer pair. |
0 | Will operate as an independent 16-bit timer. |
3) Timer Mode of Operation
Timer Mode of operation can be selected according to the following table.
Bit Name | Bit Value | Mode Selected |
---|---|---|
TxCON.TCS | 0 | Timer Mode |
TxCON.TGATE, TxCON.TCS | 1, 0 | Gated Timer Mode |
TxCON.TCS, TxCON.TSYNC* | 1, 1 | Synchronous Counter Mode |
TxCON.TSYNC | 0 | Asynchronous Counter Mode |
4) Clock-Prescaler
A clock pre-scaler can be used to increase or decrease the frequency at which the clock source increments the time base value.
It can be selected with the help of the following table.
TxCON.TCKPS* | Prescaler Value |
---|---|
3 | 1 : 256 |
2 | 1 : 64 |
1 | 1 : 8 |
0 | 1 : 1 |
5) Initialize the Timer Interrupt
Each timer can be programmed to trigger an interrupt.
- Compare match between the value of Timer Counter Register (TMRx) and Period Register (PRx).
- Detecting a falling edge in Gated Time Accumulation Mode.
This interrupt can be initialized in dsPic microcontrollers with the help of the following registers and bits.
Bit Name | Register and Bit Identification | Value |
---|---|---|
Interrupt Enable Control bit | IEC0/1.TxIE | 1 = Enable 0 = Disable |
Interrupt Flag Status bit | IFS0/1.TxIF | This bit must be reset in software after each interrupt trigger |
Interrupt Priority Control bit | IPC0/1/5.TxIP | 6 - 0 depending on the priority |
This sample code can be used to initialize an interrupt service routine for timer 1. (Pick the timer initialization function from above and call the functions in main() as suitable.)
For a detailed procedure on interrupts, follow
Example Code to Initialize Interrupt in dsPic30f and dsPic33f Controllers
void Interrupt_Init( void )
{
IEC0bits.T1IE = 1;
IPC0bits.T1IP = 6;
}
void __attribute__((interrupt, auto_psv)) _T1Interrupt( void )
{
//Your code here
IFS0bits.T1IF = 0;
}
Complete Code Example to Initialize and Test a Timer and Timer Interrupt for dsPic30f and dsPic33f
[Tested by author on: 22/09/2018]
The following code can be used to initialize and test Timer 1 in the 'Timer Mode' of operation. It is made by incorporating the two code snippets given above.
This code will generate an interrupt when ever a compare match occurs between the value of PR1 register and TMR1 registers.
- Interrupt has been programmed to flash an led for 10 milliseconds.
- Value of PR1 register: 0x8FF4 has been set such that a compare match occurs every 20 milliseconds.
So the led should be on for 10 milliseconds (as long as the program counter stays in interrupt function) and off for another 10 milliseconds when program counter exits the interrupt. The off time is being controlled by Timer 1.
_FOSC(CSW_FSCM_OFF & FRC); // Fosc = 7.37 MHz, internal fast RC oscillator
void init_Timer( void )
{
T1CONbits.TON = 1; //Activate the timer module
T1CONbits.TCKPS = 0; //Select input clock prescaler as 1:1
T1CONbits.TGATE = 0; //Disable Gate Time Accumulation Mode
T1CONbits.TCS = 0; //Select internal clock as the timer clock source
T1CONbits.TSYNC = 0; //External clock source is left unsynchronized
PR1 = 0x8FF4;
}
void Interrupt_Init( void )
{
IEC0bits.T1IE = 1;
IPC0bits.T1IP = 6;
}
void __attribute__((interrupt, auto_psv)) _T1Interrupt( void )
{
_LATD0 = 1;
__delay_ms(10);
_LATD0 = 0;
IFS0bits.T1IF = 0;
}
void main( void )
{
init_Timer();
Interrupt_Init();
while( 1 )
{
}
}

Logic analyzer trace showing interrupt being triggered every 20 ms and 10 ms second pulses through the interrupt function on RD0.
This article is accurate and true to the best of the author’s knowledge. Content is for informational or entertainment purposes only and does not substitute for personal counsel or professional advice in business, financial, legal, or technical matters.
© 2018 StormsHalted
Comments
StormsHalted (author) from Pullman, Washington, United States on January 26, 2019:
I did intentionally omit this bit for the sake of simplicity in main article. Here is how you do it:
The oscillator frequency at my end is configured at 7.37 MHz and Fcy is defined as 4 / 7.37 MHz = 1842500.
This means that the timer will increment by 1 after every 1 / 1842500 = 0.5427 microseconds. (when it gets the trigger from internal clock source.)
To count up to 20 milliseconds the timer needs to count 20,000 us / 0.5427 us = 36,852 increments.
36,852 is equal to 0x8FF4 in hexadecimal.
Make sure you keep track of the conversion from milliseconds to microseconds.
Ali FARES on January 24, 2019:
Can explain me how did you find PR1 = 0X8FF4?
Thanks.