1.HC-SR04初識
HC-SR04超聲波測距模塊可提供2cm-400cm的非接觸式距離感測功能,測距精度可達高到3mm;模塊包括超聲波發射器、接收器和控制電路。其基本工作原理采用IO口TRIG觸發測距,給至少10us的高電平信號;模塊自動發送8個40khz的方波,自動檢測是否有信號返回;有信號返回,通過IO口ECHO輸出一個高電平,高電平持續的時間就是超聲波從發射到返回的時間。
超聲波傳感器測距時,被測物體的面積不少於0.5平方米且平面盡量要求平整,否則影響測量的結果。建議測量周期為60ms以上,以防發射信號對回響信號的影響。超聲波時序圖如下圖所示。
2.HC-SR04原理圖
HC-SR04模塊有四個引線接口,VCC、GND、Trig、Echo。VCC供5V電源,GND接地,Trig觸發控制信號輸入,Echo回響信號輸出。HC-SR04原理圖如下圖所示。
HC-SR04模塊中STC11是一款STC單片機(STC單片機的一個系列,而不是一個具體的單片機型號),P65/P64接口外接4MHz的晶振電路,P63口接復位電路,STC11的作用是根據收到的發送信號TRIG,發送一端40kHZ波形給MAX232;還有個作用是根據接收到的超聲波波形,返回一段ECHO信號。MAX232芯片起電平轉換的作用,因為STC11單片機在P51/P52口輸出的波形是TTL。為了使HC-SR04模塊的測距變寬,MAX232對40KHZ的信號進行電平轉換,功率放大。TL074為四路低噪聲輸入運算放大器。其作用為對接收到的超聲波電壓信號進行信號放大、濾波、電壓比較等。接收電路可參考下圖。
注:此圖與HC-SR04模塊圖接收電路不同。
3.基於HC-SR04的測距儀設計
該系統采用51系列單片機為控制核心,LCD1602為顯示電路,HC-SR04為超聲波傳感器。實物圖如下圖所示。
LCD顯示驅動代碼

#include"lcd.h" void Read_Busy() // { unsigned char sta; // LCD1602_DB = 0xff; LCD1602_RS = 0; LCD1602_RW = 1; do { LCD1602_EN = 1; sta = LCD1602_DB; LCD1602_EN = 0; // }while(sta & 0x80); } void Lcd1602_Write_Cmd(unsigned char cmd) // { Read_Busy(); LCD1602_RS = 0; LCD1602_RW = 0; LCD1602_DB = cmd; LCD1602_EN = 1; LCD1602_EN = 0; } void Lcd1602_Write_Data(unsigned char dat) // { Read_Busy(); LCD1602_RS = 1; LCD1602_RW = 0; LCD1602_DB = dat; LCD1602_EN = 1; LCD1602_EN = 0; } void LcdSetCursor(unsigned char x,unsigned char y) // { unsigned char addr; if(y == 0) addr = 0x00 + x; else addr = 0x40 + x; Lcd1602_Write_Cmd(addr|0x80); } // void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData) { Y &= 0x1; X &= 0xF; // if (Y) X |= 0x40; // X |= 0x80; // Lcd1602_Write_Cmd(X); // Lcd1602_Write_Data(DData); // } void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str) { LcdSetCursor(x,y); // while(*str != '\0') { Lcd1602_Write_Data(*str++); } } void InitLcd1602() // { Lcd1602_Write_Cmd(0x38); // Lcd1602_Write_Cmd(0x0c); Lcd1602_Write_Cmd(0x06); Lcd1602_Write_Cmd(0x01); // }
超聲波測距儀主程序

#include<reg51.h> #include<intrins.h> #include"lcd.h" sbit Trig = P2^1; sbit Echo = P2^0; unsigned char PuZh[]=" Test "; unsigned char code ASCII[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','M'}; static unsigned char DisNum = 0; //ÏÔʾÓÃÖ¸Õë unsigned int time=0; unsigned long S=0; bit flag =0; unsigned char disbuff[4] ={ 0,0,0,0,}; void Conut(void) { time=TH0*256+TL0; TH0=0; TL0=0; S=(time*1.7)/100; //Ëã³öÀ´ÊÇCM if((S>=700)||flag==1) //³¬³ö²âÁ¿·¶Î§ÏÔʾ¡°-¡± { flag=0; DisplayOneChar(0, 1, ASCII[11]); DisplayOneChar(1, 1, ASCII[10]); //ÏÔʾµã DisplayOneChar(2, 1, ASCII[11]); DisplayOneChar(3, 1, ASCII[11]); DisplayOneChar(4, 1, ASCII[12]); //ÏÔʾM } else { disbuff[0]=S%1000/100; disbuff[1]=S%1000%100/10; disbuff[2]=S%1000%10 %10; DisplayOneChar(0, 1, ASCII[disbuff[0]]); DisplayOneChar(1, 1, ASCII[10]); //ÏÔʾµã DisplayOneChar(2, 1, ASCII[disbuff[1]]); DisplayOneChar(3, 1, ASCII[disbuff[2]]); DisplayOneChar(4, 1, ASCII[12]); //ÏÔʾM } } void zd0() interrupt 1 //T0ÖжÏÓÃÀ´¼ÆÊýÆ÷Òç³ö,³¬¹ý²â¾à·¶Î§ { flag=1; //ÖжÏÒç³ö±êÖ¾ } void StartModule() //Æô¶¯Ä£¿é { Trig=1; //Æô¶¯Ò»´ÎÄ£¿é _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); Trig=0; } void delayms(unsigned int ms) { unsigned char i=100,j; for(;ms;ms--) { while(--i) { j=10; while(--j); } } } void main(void) { P1 = 0xF0; TMOD=0x01; //ÉèT0Ϊ·½Ê½1£¬GATE=1£» TH0=0; TL0=0; ET0=1; //ÔÊÐíT0ÖÐ¶Ï EA=1; //¿ªÆô×ÜÖÐ¶Ï InitLcd1602(); LcdShowStr(0,0,PuZh); while(1) { StartModule(); while(!Echo); //µ±RXΪÁãʱµÈ´ý TR0=1; //¿ªÆô¼ÆÊý while(Echo); //µ±RXΪ1¼ÆÊý²¢µÈ´ý TR0=0; //¹Ø±Õ¼ÆÊý Conut(); //¼ÆËã delayms(80); } }