Exploring STC 8051 Microcontrollers – Coding

Using PCA to Measure Pulse Width from HCSR-04 SONAR Module

Apart from frequency measurement, we can apply the same input capture technique to measure pulse widths or PWM duty cycles. Pulse width measurement requires capturing PCA counts of two successive opposite edges unlike two successive same edges. In this segment, we will see how we can measure distance measured by a HCSR-04 SONAR sensor by measuring pulse width output from it.

Code

 #include "STC8xxx.h"
#include "BSP.h"
#include "LCD.c"
#include "lcd_print.c"
 
unsigned char state = 0x00;
unsigned int pulse_width = 0x0000;
 
void setup(void);
 
void PCA_ISR(void)          
interrupt 7
{   
  if(check_PCA_0_flag)
  {
    state ^= 1;
    clear_PCA_0_flag;
  }
  
  switch(state)
  {
    case 1:
    {
      PCA_load_counter(0x0000);
      break;    
    }
    
    default:
    {  
      pulse_width = PCA_get_CCAP0();
      break;
    }
  }
}
 
void main(void)
{
  float range = 0.0;
  
  setup();
 
  LCD_goto(0, 0); 
  LCD_putstr("Range/cm:"); 
  LCD_goto(0, 1); 
  LCD_putstr("Pulse/us:");  
 
  while(1)
  {
    P55_low;
    delay_ms(10);
    
    P16_high; 
    delay_us(10); 
    P16_low; 
    P55_high;
    
    range = ((((float)pulse_width) / 58.0)); 
    print_F(10, 0, range, 1); 
    print_I(10, 1, pulse_width);
    
    delay_ms(490);
  };
}
 
void setup(void)
{
  CLK_set_sys_clk(IRC_24M, 2, MCLK_SYSCLK_no_output, MCLK_out_P54);
 
  P16_push_pull_mode;
  P55_open_drain_mode;
  
  PCA_pin_option(0x00);
  
  PCA_setup(PCA_continue_counting_in_idle_mode, PCA_clk_sys_clk_div_12);
  PCA_load_counter(0x0000);
  
  PCA_0_mode(PCA_16_bit_both_edge_capture);
  
  _enable_PCA_0_interrupt;
  _enable_global_interrupt;  
  
  PCA_start_counter;
  
  LCD_init();
  LCD_clear_home();
}

Schematic

Explanation

HC-SR04 SONAR sensor works by sending a stream of ultrasonic pulses and then timing how long it took for an echo to bounce back from a nearby object. Based on timing, the sensor gives a pulse of variable width. The pulse width is a representation of distance or object range.

There are two pins apart from the power supply pins and these are needed to communicate with the sensor. When the trigger pin of the sensor is pulled high for about 10μs, the sensor acknowledges this short duration pulse as a command from its host micro to measure and return range data. A pulse output from the echo pin is the representation of distance.

Now let’s see how the code is working in this example. Firstly, the system clock is set to 12MHz.

 CLK_set_sys_clk(IRC_24M, 2, MCLK_SYSCLK_no_output, MCLK_out_P54); 

Pins P1.6 and P1.7 are tied to trigger and echo pins of HC-SR04 sensor respectively.

The PCA hardware is setup by setting its clock to 1MHz. Thus, each of PCA counter’s count is equal to 1μs tick. Default PCA pin configuration is used. The PCA counter is set to 0 count and 16-bit both edge capture mode is selected. Interrupt method is used and so PCA and global interrupts are enabled before starting the PCA counter. 

 PCA_pin_option(0x00);
  
PCA_setup(PCA_continue_counting_in_idle_mode, PCA_clk_sys_clk_div_12);
PCA_load_counter(0x0000);
  
PCA_0_mode(PCA_16_bit_both_edge_capture);
 
_enable_PCA_0_interrupt;
_enable_global_interrupt;  
  
PCA_start_counter;

The PCA hardware is now ready to detect edge transitions. When transitions occur, PCA interrupt is triggered. During a low-to-high transition or rising edge, the PCA counter is reset to 0 count and left to continue counting. Upon detecting a high-to-low transition or falling edge, the PCA counter is read.

 void PCA_ISR(void)          
interrupt 7
{   
  if(check_PCA_0_flag)
  {
    state ^= 1;
    clear_PCA_0_flag;
  }
  
  switch(state)
  {
    case 1:
    {
      PCA_load_counter(0x0000);
      break;    
    }
    
    default:
    {  
      pulse_width = PCA_get_CCAP0();
      break;
    }
  }
}

Since the PCA counter is counting with 1µs resolution, the falling edge capture count is the pulse width period in microseconds.

In the main loop, the SONAR sensor is triggered and the result from the PCA interrupt is processed. Target object distance detected by the sensor is a function of pulse width measured in microseconds. Thus, as per datasheet of the sensor, pulse width divided by 58 is equal to distance in centimeters.

The range and the captured pulse width are displayed in an LCD after performing the aforementioned computations.

 P55_low;
delay_ms(10);
    
P16_high; 
delay_us(10); 
P16_low; 
P55_high;
    
range = ((((float)pulse_width) / 58.0)); 
print_F(10, 0, range, 1); 
print_I(10, 1, pulse_width);
    
delay_ms(490);

Demo

Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

Related Posts

7 comments

  • Hi. Can you explain how to use I2C in the slave mode ?

  • Thanks for these tutorials. I’m getting back into STCmicro coding now, having left them alone for the past several years. Back then I only used the STC89C52RC (and C54RD) but this time I’m also using the more powerful STC15 and STC8 types. Your blogs provide a wealth of useful information.

  • Hello,

    You have done great job with all these tutorials. I am an electronics engineer trying to learn some new stuff. I am located in Greece , Europe and I would like to purchase the development board that you are using and download some datasheets in English if possible but I cannot find them anywhere. Could you please help me?

  • i always get excited when you release new tutorials ,you are really doing a great job i wish i could write code and develop libraries like you.

  • Well, this is very nice and thorough tutorial indeed, many thanks!
    Unfortunately I doubt there is good any reason to learn the STC platform beyond curiosity.
    The STC 8051, although pretty evolved from the original 8051 ISA, does not offer anything crucial to justify the relatively high price of these micros and development tools along with certain cumbersomeness of this ancient platform.
    They simply can not compete even with the legacy Cortex M0 in any way. I am even not aware about any affordable debugger/emulator for them.
    All in all, I would never recommend anybody to start learning/using any 8051 without some very good reason to do so.

Leave a Reply

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