Introduction
Additionally to Timer0, PIC16F887 has an 16-bit timer - Timer1. This timer is more advanced than Timer0. It has some additional features over Timer0
- Optional LP oscillator
- Synchronous or asynchronous operation
- Gate mode
- Interrupt on overflow
- Capture/compare function, etc.
![]() |
Block diagram of Timer1 |
There are some registers to Timer1.
![]() |
Registers relate to Timer1 |
Timer1 Control Register (T1CON) set the overall operations of Timer1.
![]() |
Timer1 Control Register (T1CON) |
Timer1 Application of Ultra-Sonic Range Measurement
An application of timer is pulse width measurement of external incoming event. For instance Ultrasonic Ranging Module HC-SR04, is a low cost popular range measurement for electronics hobbyist.
![]() |
Popular HC-SR04 sample (Ali Express) |
This module is a non-contact measuring type of sensor. It uses sounds wave traveling in space, along with its echo signal to get the distance. Measurement ranges from 4cm to 4 meters.
To make its measurement works properly the programmer must check its timing diagram.
![]() |
Timing Diagram |
It has a formula to measure range in term of receiving pulse width.
Range = (high level time)*(velocity)/2
Velocity of sound is 340m/s.
In short form we use only high time in us,
Range (in cm) = high level time (in us) / 58
To get range in Inch,
Range (in inch) = high level time (in us) / 148
Programming in MikroC
System has HC-SR04 as its input. A character LCD output displays sampling range measurement. PIC16F887 controller uses its internal 8MHz oscillator.
Timer1 measure echo signal from HC-SR04 input to RD1. RD1 of PIC16F887 is trigger pin initiating range measurement of sensor. Prescaler is assigned to 1:2 to get a 1us timing.
![]() |
Schematic Diagram |
MikroC source code:
sbit LCD_RS at RB4_bit; | |
sbit LCD_EN at RB5_bit; | |
sbit LCD_D4 at RB0_bit; | |
sbit LCD_D5 at RB1_bit; | |
sbit LCD_D6 at RB2_bit; | |
sbit LCD_D7 at RB3_bit; | |
sbit LCD_RS_Direction at TRISB4_bit; | |
sbit LCD_EN_Direction at TRISB5_bit; | |
sbit LCD_D4_Direction at TRISB0_bit; | |
sbit LCD_D5_Direction at TRISB1_bit; | |
sbit LCD_D6_Direction at TRISB2_bit; | |
sbit LCD_D7_Direction at TRISB3_bit; | |
#define TRIG PORTD.RD0 // Trigger Pin is connected to RD0 | |
#define ECHO PORTD.RD1 // ECHO Pin is connected to RD1 | |
void main() | |
{ | |
unsigned long Tm; | |
char Tl, Th; | |
unsigned distance; | |
char Txt[7]; | |
PORTD=0x00; | |
TRISD=0x02; | |
ANSELH = 0; | |
OSCCON|=0x70; | |
Lcd_Init(); | |
Lcd_Cmd(_LCD_CURSOR_OFF); | |
Lcd_Out(1,1,"Starting Up."); | |
Delay_Ms(2000); | |
T1CON=0x10; // select 1:2 Prescaler and Ignore others | |
while(1) | |
{ | |
TMR1H = 0; | |
TMR1L = 0; | |
// initialize the communication | |
TRIG = 0; | |
Delay_us(5); | |
TRIG = 1; | |
Delay_us(10); | |
TRIG = 0; | |
// wait for echo back | |
while(ECHO == 0); | |
T1CON.TMR1ON=1; | |
while(ECHO == 1); | |
T1CON.TMR1ON = 0; // sampling | |
// end of transmission | |
Tl = TMR1L; | |
Th = TMR1H; | |
Tm = Th*256 + Tl; // making 16-bit value | |
Distance=Tm/58; | |
IntToStr(Distance, Txt); | |
Lcd_Cmd(_LCD_CLEAR); | |
Lcd_Out(1,1, "Distance (cm)"); | |
Lcd_Out(2,1, Txt); | |
Delay_Ms(1000); | |
} | |
} |
Click here to download its zip file.