Interfacing PIC16F877A with HC-SR04 ultrasonic sensor – CCS C

Distance measurement using PIC16F877A microcontroller and HC-SR04 ultrasonic sensor

The distance to an obstacle can be measured with the low cost ultrasonic sensor HC-SR04 (HC-SR05). The HC-SR04 sensor can measure distances form 2 to 400cm with an accuracy of 3mm. This sensor module includes ultrasonic transmitter, ultrasonic receiver and control circuit.

The HC-SR04 ultrasonic sensor has 4 pins as shown below where:
VCC – Positive power supply (+5V)
Trig – Trigger input pin
Echo – Echo output pin
GND – Ground (0V)
HC-SR04 Ultrasonic sensor

HC-SR04 ultrasonic sensor timing diagram:
The timing diagram of the HC-SR04 ultrasonic sensor is shown below.

First we have to supply the sensor trigger pin with a pulse of 10µs and the sensor will automatically send 8 cycles burst of ultrasound at 40 kHz and raise its echo pin. The Echo is a distance object that is pulse width and the range in proportion. You can calculate the range through the time interval between sending trigger signal and receiving echo signal. Formula: uS / 58 = centimeters or uS / 148 =inch; or:
the range = high level time * velocity (340M/S) / 2.
HC-SR04 Ultrasonic sensor signals

Interfacing PIC16F877A with HC-SR04 ultrasonic sensor circuit:
Project circuit schematic is shown below.
PIC16F877A HC-SR04 Ultrasonic sensor interfacing circuit

The microcontroller runs with 8MHz crystal oscillator.
HC-SR04 Ultrasonic sensor Trigger pin is connected to RB0 pin and Echo pin is connected to RB1 pin.

PIC16F877A HC-SR04 Ultrasonic sensor interfacing hardware circuit

Interfacing PIC16F877A with HC-SR04 ultrasonic sensor CCS C code:
Here are some hints about the C code.
The sensor needs at least 10µs pulse at Trigger pin which is done as follows (Trigger pin is connected to RB0 pin:
output_high(PIN_B0);
delay_us(10);
output_low(PIN_B0);

After sending the trigger pulse we have to wait until the module raises its Echo output pin where the Echo pin is connected to pin RB1. If the waiting time is too long that means there is a problem and the code returns error. Timer1 module is used to count elapsed time which is configured to increment by 1 every 1µs (8MHz mcu frequency used).
setup_timer_1 (T1_INTERNAL | T1_DIV_BY_2);

Waiting HC-SR04 module to raise its Echo pin with timeout property code where variable check is used as a return variable (if there is a timeout problem check = 1).
The timeout property is used to prevent the microcontroller from hanging.
while(!input(PIN_B1) && (get_timer1() < 1000));
if(get_timer1() > 990)
  check = 1;

If there is no problem the module raises its Echo pin for a certain time, this time is proportional to distance from the sensor the the obstacle. Timer1 is used to count this time as follows:
while(input(PIN_B1) && (i < 25000))
  i = get_timer1();
if(i > 24990)
  check = 2;

If there is an out of range the code returns error by making the variable check = 2.
For the variable check:
If check = 0: There is no problem
If check = 1: There is a timeout error
If check = 2: There is an out of range error.
Project full code is as below:

Interfacing PIC16F877A with HC-SR04 ultrasonic sensor video:
The following video shows project prototype circuit.

9 thoughts on “Interfacing PIC16F877A with HC-SR04 ultrasonic sensor – CCS C”

  1. Nguyễn Đức Thắng

    Could you Please explain the Oscillator frequency calculation? I don’t have a 8mhz crystal and I would like to use a 20mhz. What changes do I need to do?

  2. sorry sir, i have problem.
    I don’t know why but when i’m using 20MHz crystal or 8Mhz, my simulation didnt work. My lch was just displayed distance and 0cm and change to timeout . Can u have any ideal why i have that problem? Thank you so much for taking your time to help me

    1. Simple Projects

      That’s the header file the PIC16F877A microcontroller, this file comes with CCS C compiler and it’s not a user defined file!

  3. Could you Please explain the Oscillator frequency calculation? I don’t have a 8mhz crystal and I would like to use a 4mhz. What changes do I need to do?

    1. Simple Projects

      Timer1_Frequency = MCU_Frequency/(4 x Prescaler)
      For MCU_Frequency = 8MHz and Prescaler = 2 (because I used setup_timer_1 (T1_INTERNAL | T1_DIV_BY_2);) we get:
      Timer1_Frequency = 8/(4 x 2) = 8/8 = 1MHz
      This means Timer1 will increment by 1 every 1 microsecond (1/1MHz = 1 us which is the period).
      If the MCU_Frequency = 4MHz and to get Timer1_Frequency = 1MHz:
      Prescaler = MCU_Frequency/(4 x Timer1_Frequency) = 4/(4 x 1) = 1.
      Timer1 Prescaler = 1 which is available, so use this:
      setup_timer_1 (T1_INTERNAL | T1_DIV_BY_1);

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top