首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

[自娛自樂] 超聲波測距模組DIY實戰筆記(三):高功率發射電路與雙接收定位算法

     編輯:關於C語言

前言

上一節我們已經完成了超聲波接收模組的自製,並嘗試用單片機加反相器構建 40kHz 發射電路,但發現發射功率嚴重不足,對齊情況下最多僅 10 cm。本篇將詳細記錄如何攻克功率瓶頸,打造大功率發射裝置,並進一步實現「一發兩收」的二維平面定位算法。


目錄

  1. 浪裡淘金:尋找最簡功率提升方案
  2. 步步為營:打造高效精準測距算法
  3. 階段小結與後續規劃
  4. 相關資源鏈接

一、浪裡淘金:尋找最簡功率提升方案

1.1 優化波形產生程式

針對上一版利用 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;
}

波形輸出示意圖

1.2 嘗試其他模組方案

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

Proteus 仿真截圖

1.3 三極管放大嘗試

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

三極管放大電路

1.4 MAX232 充當驅動器——靈感來自 HC-SR04

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

HC-SR04 發射電路原理圖

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

MAX232 實測波形

發射模組正面

發射模組背面


二、步步為營:打造高效精準測距算法

發射、接收硬體就緒,接著解決「一發兩收」在二維平面定位的核心難題:時間同步與多通道計時。

2.1 單 MCU 雙接收頭時差統計初試

早期接收算法僅輪詢單一腳位。雙接收頭下,需區分信號來源並統計到達時間差。引入狀態標記 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;
}

時差統計示意

實測波形

2.2 單 MCU 整合收發——直線測距儀原型

先在一片 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;
}

2.3 雙接收頭分時測量——破解單計時器瓶頸

嘗試在單 Timer 0 上同時計兩路時間失敗:先觸發中斷的處理會打斷計時,導致第二路數據丟失。靈感來自分時作業系統——將一個測量週期拆為兩個時隙,分別啟用 INT0 與 INT1,交替測量。代碼關鍵片段:

bit ok=0;
while(1) {
    if(ok==0) { EX0=1; /* 測量通道1 */ ok=1; }
    else      { EX1=1; /* 測量通道2 */ ok=0; }
}

實測成功,兩路距離數據穩定輸出:

雙通道測試實物

雙通道波形

2.4 分體式收發——硬體層面的時間同步

將發射與接收拆分為兩塊獨立 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# 的上位機客戶端,實現可視化定位與軌跡記錄,敬請期待!


四、相關鏈接

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved