目錄
1 HCSR04超聲波測距傳感器
1.1 基本參數
1.2 引腳說明
1.3 工作原理(時序圖)
2 基于AT89C52單片機的超聲波測距電路原理圖
2.1 硬件連接說明
2.2 工作原理
3 基于AT89C52單片機的超聲波測距控制程序
3.1.1 初始化設置
3.1.2 超聲波測距原理
3.1.3 顯示功能
3.1.4 注意事項
3.1.6 實現程序
3.1.7 _nop_()函數
摘要:
本文介紹基于AT89C52單片機的HC-SR04超聲波測距系統實現方案。HC-SR04模塊工作電壓5V,測量范圍2-400cm,精度±3mm,通過40kHz超聲波實現測距。系統硬件連接包括單片機與傳感器的Trig、Echo引腳對接,以及LCD顯示模塊。軟件采用定時器測量回波高電平時間,按距離=時間×0.017cm/μs公式計算距離值,并通過LCD實時顯示。程序實現包含初始化、超聲波觸發、時間測量和顯示功能,測量周期建議大于60ms。該系統具有結構簡單、成本低的特點,適合短距離測距應用,若需提高精度可增加溫度補償算法。
1 HCSR04超聲波測距傳感器
HC-SR04 是一款非常經典的低成本超聲波測距模塊,通過發射超聲波并接收回波來測量前方障礙物的距離。
1.1 基本參數
參數 | 數值/說明 |
工作電壓 | DC 5V |
工作電流 | < 15mA |
測距范圍 | 2cm ~ 400cm(理論) |
測距精度 | ±3mm(典型) |
工作頻率 | 40kHz |
觸發信號 | 10μs 高電平脈沖 |
回波信號 | 高電平持續時間表示距離 |
測量角度 | ~15° 錐形波束 |
尺寸 | 約 45 × 20 × 15 mm |
1.2 引腳說明
引腳 | 名稱 | 功能說明 |
VCC | 電源 | 接 5V |
GND | 地 | 接地 |
Trig | 觸發 | 輸入觸發信號 |
Echo | 回波 | 輸出回波信號(5V) |
注意:Echo 引腳輸出的是 5V 信號,如果接 3.3V 單片機(如 ESP8266/ESP32),建議加電阻分壓或電平轉換器,避免燒壞 GPIO。
1.3 工作原理(時序圖)
1 向Trig 引腳發送一個 ≥10μs 的高電平脈沖;
2 模塊自動發射 8 個 40kHz 超聲波脈沖;
3 Echo 引腳輸出高電平,持續時間與超聲波往返時間成正比;
4 距離計算公式:
距離(cm)=(Echo高電平時間/2)*聲音傳播速度
2 基于AT89C52單片機的超聲波測距電路原理圖
功能:AT89C52控制HC-SR04超聲波傳感器和LCD顯示
2.1 硬件連接說明
HC-SR04 VCC → 5V
HC-SR04 GND → GND
HC-SR04 Trig → P2.0
HC-SR04 Echo → P2.1
LCD數據線 → P0口
LCD RS → P2.2
LCD RW → P2.3
LCD EN → P2.4
2.2 工作原理
首先,給Trig引腳一個至少10us的高電平脈沖,然后模塊會自動發送8個40kHz的超聲波脈沖,并檢測回波。
當檢測到回波時,Echo引腳會輸出高電平,高電平的持續時間就是超聲波從發射到返回的時間。
距離 = (高電平時間 * 聲速(340m/s)) / 2
注意:由于聲速隨溫度變化,但這里我們忽略溫度補償,使用340m/s。
3 基于AT89C52單片機的超聲波測距控制程序
如上圖所示,示波器中黃色線表示Trig引腳信號,用于產生至少10us的高電平脈沖。藍色線表示Echo引腳會輸出高電平,高電平的持續時間與測量距對應。
-
- 程序功能說明
3.1.1 初始化設置
配置LCD顯示
初始化定時器0用于測量時間間隔
3.1.2 超聲波測距原理
向TRIG引腳發送至少10μs的高電平脈沖
超聲波模塊自動發送8個40kHz的脈沖
檢測ECHO引腳的高電平持續時間
根據時間計算距離:距離 = (時間 × 聲速) / 2
3.1.3 顯示功能
在LCD上顯示測量得到的距離值
3.1.4 注意事項
測量周期最好大于60ms,以防止發射信號對回響信號的影響
實際應用中可能需要添加溫度補償以提高精度
如果測量環境復雜,可能需要添加濾波算法
3.1.6 實現程序
//庫函數與位定義
#include <reg52.h>
#include <intrins.h>#define uint unsigned int
#define uchar unsigned char// LCD引腳定義
sbit LCD_RS = P2^2;
sbit LCD_RW = P2^3;
sbit LCD_EN = P2^4;// HC-SR04引腳定義
sbit TRIG = P2^0;
sbit ECHO = P2^1;// 全局變量
uint distance = 0;
uint time = 0;// LCD延時函數
void lcd_delay(uint ms) {uint i, j;for(i = 0; i < ms; i++)for(j = 0; j < 120; j++);
}// LCD寫命令函數
void lcd_write_cmd(uchar cmd) {LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;P0 = cmd;LCD_EN = 1;lcd_delay(1);LCD_EN = 0;lcd_delay(1);
}// LCD寫數據函數
void lcd_write_data(uchar dat) {LCD_RS = 1;LCD_RW = 0;LCD_EN = 0;P0 = dat;LCD_EN = 1;lcd_delay(1);LCD_EN = 0;lcd_delay(1);
}// LCD初始化函數
void lcd_init() {lcd_write_cmd(0x38); // 16x2顯示,5x7點陣,8位數據接口lcd_write_cmd(0x0C); // 顯示開,光標關,閃爍關lcd_write_cmd(0x06); // 寫入新數據后光標右移lcd_write_cmd(0x01); // 清屏lcd_delay(2);
}// 顯示字符串函數
void lcd_display_string(uchar *str) {while(*str != '\0') {lcd_write_data(*str++);}
}// 顯示數字函數
void lcd_display_number(uint num) {uchar i;uchar digits[4];if(num > 999) {digits[0] = num / 1000 + '0';digits[1] = (num % 1000) / 100 + '0';digits[2] = (num % 100) / 10 + '0';digits[3] = num % 10 + '0';for(i = 0; i < 4; i++) {lcd_write_data(digits[i]);}}else if(num > 99) {digits[0] = num / 100 + '0';digits[1] = (num % 100) / 10 + '0';digits[2] = num % 10 + '0';for(i = 0; i < 3; i++) {lcd_write_data(digits[i]);}}else if(num > 9) {digits[0] = num / 10 + '0';digits[1] = num % 10 + '0';for(i = 0; i < 2; i++) {lcd_write_data(digits[i]);}}else {lcd_write_data(num + '0');}
}// 定時器0初始化
void timer0_init() {TMOD = 0x01; // 定時器0工作方式1TH0 = 0;TL0 = 0;ET0 = 1; // 允許定時器0中斷EA = 1; // 開啟總中斷
}// 超聲波測距函數
uint ultrasonic_measure() {TRIG = 1;_nop_();//空格起延時作用_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();TRIG = 0;while(!ECHO); // 等待ECHO變高TR0 = 1; // 啟動定時器0while(ECHO); // 等待ECHO變低TR0 = 0; // 停止定時器0time = TH0 * 256 + TL0;//計時TH0 = 0;TL0 = 0;// 計算距離 (cm) = (時間 * 聲速) / 2// 聲速 = 340m/s = 0.034cm/μs// 定時器每計數1次為1μsdistance = time * 0.017; // 簡化計算: 0.034/2 = 0.017return distance;
}// 主函數
void main() {lcd_init();timer0_init();lcd_write_cmd(0x80); // 設置LCD顯示位置lcd_display_string("Distance:");while(1) {distance = ultrasonic_measure();lcd_write_cmd(0x89); // 設置顯示位置lcd_display_number(distance);lcd_display_string("cm ");// 延時一段時間再進行下一次測量lcd_delay(5);}
}// 定時器0中斷服務函數
void timer0_isr() interrupt 1 {// 定時器溢出處理TH0 = 0;TL0 = 0;
}
3.1.7 _nop_()函數
_nop_()是8051單片機中的一個內聯函數,它產生一個NOP(空操作)指令,消耗一個機器周期的時間。在12MHz晶振的系統中,一個NOP指令執行時間為1μs。