The Timer0 module is an 8-bit timer/counter that is included with all 8-bit PIC® MCU devices. The Timer is more than just a timer. It has all the following features:
- 8-bit timer/counter register (TMR0)
- 8-bit prescaler (independent of Watchdog Timer)
- Programmable internal or external clock source
- Programmable external clock edge selection
- Interrupt on overflow
- TMR0 can be used to gate Timer1
Below is a simplified block diagram of the Timer0 module.
The Timer0 module can be used as an 8-bit timer. In timer mode it is incremented on every instruction clock pulse unless a prescaler is used to reduce the speed. The TMR0 Register can be written to via software to preload it with a value. If the TMR0 register is written, the increment is inhibited for the following two instruction cycles. This can be adjusted for in the prewritten value.
Timer mode is selected by clearing the TMR0CS bit of the OPTION_REG register.
SOFTWARE PROGRAMMABLE PRESCALER
A software programmable prescaler is available for exclusive use with Timer0. The prescaler is enabled by clearing the PSA bit of the OPTION_REG register. There are eight prescaler options for the Timer0 module ranging from 1:2 to 1:256. The prescale values are selectable via the PS<2:0> bits of the OPTION_REG register. In order to have a 1:1 prescaler value for the Timer0 module, the prescaler must be disabled by setting the PSA bit of the OPTION_REG register.
The prescaler is not readable or writable. All instructions writing to the TMR0 register will clear the prescaler. The prescaler is mutually exclusively shared between the Timer0 module and the Watchdog Timer. When the prescaler is assigned to the Timer0 module, any write to the TMR0 register will immediately update the TMR0 register and clear the prescaler.
In 8-Bit Counter mode, the Timer0 module will increment on every rising or falling edge of the T0CKI I/O pin. This allows the PIC® MCU to count pulses from an external clock source. The signal has voltage limits as specified in the device data sheet but will typically be that the limits of the device's operating voltage.
By selecting this externally triggered counting option to the Timer 0, the software can monitor the pulses from an external sensor to capture data. Timer0 has a 255 count limit before overflowing back to zero. Using a prescaler can extend that count.
8-Bit Counter mode using the T0CKI pin is selected by setting the TMR0CS bit in the OPTION_REG register to ‘1’.
The rising or falling transition of the incrementing edge for either input source is determined by the TMR0SE bit
in the OPTION_REG register.
COUNTER MODE SYNCHRONIZATION
When an external clock input is used for Timer0, it must meet certain timing requirements. These requirements ensure the external clock can be synchronized with the internal instruction clock. Also, there may be a slight delay in the actual incrementing of Timer0 after synchronization.
When no prescaler is used, the external clock input is the same as the prescaler output. The synchronization of T0CKI with the internal phase clocks is accomplished by sampling the prescaler output. The T0CKI signal has to be at a high level for at least two clock periods of the system clock (Fosc) and a small RC delay of 20 nanoseconds. The signal must also be low for at least two Fosc clock periods.
When a prescaler is used, the external clock input is divided by an asynchronous ripple-counter type prescaler so that the prescaler output is symmetrical. For the external TOCKI input to meet the sampling requirement, the ripple-counter must be taken into account. Therefore, it is necessary for T0CKI signal to have a period of at least 4 clock periods of the Fosc clock (and a small RC delay of 40 ns) divided by the prescaler value. The only requirement on T0CKI high and low time is that they do not violate the minimum pulse width requirement for the device (around 10 nanoseconds).
The TMR0IF interrupt flag bit of the INTCON register is set every time the TMR0 register overflows from FFh to 00h, regardless of whether or not the Timer0 interrupt is enabled. This allows software to poll the bit asynchronously. The TMR0IF bit is not automatically reset, it needs to be cleared in software.
To enable the automatic interrupt, the Timer0 interrupt enable bit (TMR0IE) of the INTCON register must be set to one.
With the interrupt enabled, when the TMR0 register overflows, the CPU will direct execution to the interrupt vector which needs to hold the address of the software interrupt routine. When the overflow occurs, the interrupt service routine can preload the TMR0 register and then clear the TMR0IF bit.
Timer0 Operation During Sleep
Timer0 cannot operate while the processor is in Sleep mode. The contents of the TMR0 register will remain unchanged while the processor is in Sleep mode.
Timer0 Example using MPLAB Code Configurator
The MPLAB Code Configurator (MCC) makes setting up the Timer0 peripheral very easy. The MCC will automatically generate the code to load the proper registers and initialize the proper values to produce the desired Timer0 operation.
The best way to show how this is done is through a simple example. In this example Timer0 will be used as a time base for toggling an I/O pin. A PIC16F1825 will be used with the 4 Mhz internal oscillator and the RA2 I/O pin will toggle on every Timer0 overflow. Timer0 will be set to overflow at a 2.5 millisecond rate using a 1:32 prescaler.
The first step after launching the MCC within MPLAB X® is to select the peripherals we will use in this example to setup the System settings, Timer0 configuration and the I/O setup.
The System setup requires two section to be be configured; the oscillator and the configuration.
The first is the oscillator. A 4Mhz internal oscillator is selected and the Timer0 clock sources is the internal clock.
The configuration settings include the defaults plus the MCLR pin is set to be a digital I/O pin so the MCLR pull-up is internal to the PIC® MCU.
Timer0 has various options to select from. The prescaler value of 32 is selected from the drop down menu. The period of the timer is then set to a value as close as possible to the desired 2.5 milliseconds. The Interrupt will not be used so this is left unchecked. Notice that the preload value will automatically change when the desired period is selected.
The pin manager is used to select the RA2 pin. Clicking on the blue unlock for RA2 will change it to a green lock to show that pin was selected.
The I/O setup screen shows the RA2 pin parameters and this is where the pin is configured as an output by checking that box. The name of the pin could also be changed to a custom name but it will be used as the default IO_RA2 in this example.
The generate code button is then clicked to produce the software files. A set of source files including a main.c and a set of header files are both produced by the MCC.
The main.c file is shown below. The MCC places a SYSTEM_Initialize function at the top that includes all the necessary files for the Timer0 setup. In addition to that, a few commands need to be added by the developer. Within the generated code are two functions that make the code easier:
There is also a function created in the pin_manager files that automatically toggles the I/O pin:
The TMR0_HasOverflow_Occurred tests the TMR0IF bit to see if it is a one. An "if statement" is used to test the result of the TMR0_HasOverflow_Occurred function. If the result is one, indicating the TMR0 has overflowed, then the RA2 pin is toggled. Timer0 has to be re-initialized which also clears the TMR0IF bit and preloads the TMR0 register with the proper preload value to create the 2.5 millisecond delay.
The function IO_RA2_Toggle is created in the pin_manager files. This helps to make generating the I/O toggle quite easy as all the port register settings are handled in the pin_manager functions.
The oscilloscope capture below shows the result. The RA2 pin toggles every 2.52 milliseconds. This is a little longer than than the settings in the TMR0 setup screen but this is because of the time it takes to toggle the pin and then re-initialize the timer0. If the timing is critical then the value in the Timer0 setup can be adjusted to change the preload value that produced the desired overflow time.