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); } }