上一節我們已經完成了超聲波接收模組的自製,並嘗試用單片機加反相器構建 40kHz 發射電路,但發現發射功率嚴重不足,對齊情況下最多僅 10 cm。本篇將詳細記錄如何攻克功率瓶頸,打造大功率發射裝置,並進一步實現「一發兩收」的二維平面定位算法。
針對上一版利用 Timer 2 產生 40kHz 方波的程式,通過調整定時器重裝值,功率略有提升,但仍屬微弱(苦無示波器,只能靠碼表調試)。以下為優化後的 51 單片機核心代碼(11.0592 MHz 晶振,Timer 2 16-bit 自動重載):
/* Timer 2 初始化:產生 40kHz 互補方波 */
void TIM2Inital(void) {
RCAP2H = (65536 - 12) / 256;
RCAP2L = (65536 - 12) % 256;
ET2 = 1; EA = 1; TR2 = 1;
}
void TIM2(void) interrupt 5 using 1 {
TF2 = 0;
P10 = ~P10; // 輸出互補波形
P11 = ~P11;
}

在 Proteus 中嘗試 555 定時器、離散元件推挽等方案,大多需要 9V 以上驅動電壓,且模擬電路較複雜,受限於手頭元件與無示波器,均未實測成功。

參考某畢業設計,在脈衝輸出級加入 2N3904 三極管放大,集電極接 12V。初期功率明顯增強,但極短時間後失效,推測三極管被燒毀,方案宣告失敗。

觀察商用 HC-SR04 模組發現:它僅用 5V 供電卻能輸出強勁超聲波。研究其原理圖後發現,其發射端採用 STC 单片机輸出兩路反相 40kHz 方波,直接接入 MAX232 兩個通道的輸入端,利用 MAX232 內部電荷泵將電平提升至 ±10V 差分驅動換能器。這是一個極簡且高效的方案!

手頭正好有 USB-TTL 模組(板載 MAX232),飛線測試後確認信號幅度大幅增強。隨後設計專用發射模組 PCB,雙通道並聯驅動,功率更足:



發射、接收硬體就緒,接著解決「一發兩收」在二維平面定位的核心難題:時間同步與多通道計時。
早期接收算法僅輪詢單一腳位。雙接收頭下,需區分信號來源並統計到達時間差。引入狀態標記 ok(0:無信號, 1:僅1號, 2:僅2號, 3:雙雙收到),在主迴圈中以 + 計數表達時差。核心邏輯如下:
while(1) {
SBUF = '+'; // 發送基準脈衝給上位機
if(IN1==0 && ok!=1 && ok!=3) { SBUF='a'; ok = (ok==2)?3:1; }
if(IN2==0 && ok!=2 && ok!=3) { SBUF='b'; ok = (ok==1)?3:2; }
if(ok==3) { if(++i==100) { ok=0; i=0; } }
while(!TI); TI=0;
}


先在一片 MCU 上實現「一發一收」直線測距,驗證流程:發射 100 個週期 40kHz → 開啟 Timer 0 計數 → 外部中斷 INT0 捕捉接收下降沿 → 停止計數 → 換算距離 → 串口上傳。代碼用盡 51 所有中斷資源(INT0, Timer0, Timer1, Timer2),邏輯緊湊。


優化後將串口發送移出中斷,放入主迴圈,避免中斷嵌套過深:
/* 主迴圈片段 */
while(1) {
P10=P11=0; flag=0; TR0=1; times=0; TIM2Inital();
while(times<200); ET2=0;
if(flag) { /* 計算距離並發送 */ }
EX0=1;
}
嘗試在單 Timer 0 上同時計兩路時間失敗:先觸發中斷的處理會打斷計時,導致第二路數據丟失。靈感來自分時作業系統——將一個測量週期拆為兩個時隙,分別啟用 INT0 與 INT1,交替測量。代碼關鍵片段:
bit ok=0;
while(1) {
if(ok==0) { EX0=1; /* 測量通道1 */ ok=1; }
else { EX1=1; /* 測量通道2 */ ok=0; }
}
實測成功,兩路距離數據穩定輸出:


將發射與接收拆分為兩塊獨立 PCB,核心挑戰是跨 MCU 時間同步。方案:接收端準備好後,拉低 P2.0 產生下降沿,經一根導線連接發射端 INT0 (P3.2);發射端進入中斷即刻啟動發射與計時,接收端同步啟動 Timer 0。接收端採用可被中斷打斷的延時等待有效回波,極大簡化了協議。
發射端核心代碼:
void InterruptInit(void) { /* INT0 下降沿觸發 */ }
main() {
InterruptInit();
while(1) { flag=0; while(!flag); EX0=0; times=0; TIM2Inital(); while(times<80); ET2=0; EX0=1; }
}
void intersvro0(void) interrupt 0 { flag=1; }
接收端核心代碼:
void delays() { times=0; while(times<1000) times++; } // 可中斷延時
main() {
bit ok=0; USRT_init(); InterruptInit();
while(1) {
P20=1;
if(ok==0) { EX0=1; P20=0; TR0=1; delays(); if(flag==1) { /* 處理通道1 */ ok=1; } }
else { EX1=1; P20=0; TR0=1; delays(); if(flag==2) { /* 處理通道2 */ ok=0; } }
}
}

經過三個階段,我們完成了從需求分析、資料調研、原料採購、硬體焊接、軟硬聯調到算法優化的完整閉環,成功自製了具備二維定位潛力的超聲波測距硬體模組。下一階段將開發基於 C# 的上位機客戶端,實現可視化定位與軌跡記錄,敬請期待!