MSP430 Launchpad with Ultrasonic Distance sensor HC-SR04

Here I am going to share my work in getting MSP-EXP430G2 Launchpad interface with Ultrasonic Distance Sensor HC-SR04. Let me make it short and sweet.

Hardware connections

Sensor needs +5V where as MSP430 Launchpad works on +3.5V. But still Launchpad is powered by USB. There is a small hack to get +5V from Launchpad to Sensor. Near USB connector, there are two test points TP1 (+5V) and TP3 (Gnd). Just connect a header pin to it. Then connect them to Sensor Vcc and Gnd. Now connect P1.4 to Trigger pin and P1.1 to Echo pin of Sensor. P1.1 can interrupt a timer, so it should be P1.1 only.




Overview of firmware

The timing diagram shown below shows that sending a 10uS pulse to Sensor’s trigger pin, echoes back a pulse to echo pin, the width of the pulse is proportionate to distance between sensor and object.

The echo pin is connected to P1.1, which is a Timer A0 capture input. So we capture both raising and falling edge of echo signal and find the difference between timer counter values. This value in uS divided by 58 gives distance in cm. We run this system at 1MHz clock, so the timer counter directly gives uS value.

Source code


/* Build: msp430-gcc -mmcu=msp430g2231 -g -o us-dist-proto.elf us-dist-proto.c */

#include <msp430g2231.h>

unsigned int up_counter;
unsigned int distance_cm;

/* Timer A0 Capture Interrupt routine
 P1.1 (echo) causes this routine to be called */
#pragma vector=TIMERA0_VECTOR
__interrupt void TimerA0(void)
	if (CCTL0 & CCI)			// Raising edge 
		up_counter = CCR0;		// Copy counter to variable
	else						// Falling edge
		// Formula: Distance in cm = (Time in uSec)/58 
		distance_cm = (CCR0 - up_counter)/58;
	TA0CTL &= ~TAIFG;			// Clear interrupt flag - handled

int main(void)
	WDTCTL = WDTPW + WDTHOLD;       // Stop Watch Dog Timer

	/* set P1.4 to output direction (trigger) */
	P1DIR |= BIT4;
	P1OUT &= ~BIT4;					// keep trigger at low

    /* Set P1.1 to input direction (echo)
	  Why P1.1? - msp430g2231 datasheet mention this as 
	  input for Timer A0 - Compare/Capture input */
	P1DIR &= ~BIT1;
	// Select P1.1 as timer trigger input select (echo from sensor)
	P1SEL = BIT1;

	/* Timer A0 configure to read echo signal:  
	Timer A Capture/Compare Control 0 =>
	capture mode: 1 - both edges +
	capture sychronize +
	capture input select 0 => P1.1 (CCI1A) + 
    capture mode + 
	capture compare interrupt enable */
	CCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE;
	/* Timer A Control configuration =>
	Timer A clock source select: 1 - SMClock + 
	Timer A mode control: 2 - Continous up + 
	Timer A clock input divider 0 - No divider */
 	TA0CTL |= TASSEL_2 + MC_2 + ID_0;

	// Global Interrupt Enable

	for (;;)
		P1OUT ^= BIT4; 				// assert
		__delay_cycles(10);			// 10us wide
		P1OUT ^= BIT4; 				// deassert
		__delay_cycles(60000);		// 60ms measurement cycle

You can download the code from here >> us-dist-proto.c




Here is my console session of “$ mspdebug rf2500” to programming and testing with two distances. The distance_cm variable is in location 0x0202. By displaying this variable, we come to know that 0x43 is longer distance in cm and 0x12 is shorter distance in cm.



You can also see logic analyzer output for Trigger and Echo in the following two images. Channel-6 is Trigger pin and Channel-7 is Echo pin.






Share this post


  1. hi swamy,
    here i took your code as my source code for my project , i want to use 16 Mhz osc as my clock source.could u help me what was the change i want to made . i under stood that you used 1us as your count.

Leave a Reply

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