超聲波模塊電路圖如下:
超聲波模塊工作原理如下:
超聲波測距的本質是測量“超聲波發射→遇到障礙物反射→回波被接收”的往返時間。對應到模塊引腳,需捕捉 Echo 引腳的上升沿(回波開始)和下降沿(回波結束)?的時間差,再通過公式 距離=(時間差×聲速)/2計算距離。
ECAP是F28035的增強型捕獲外設,核心能力是精準捕捉外部信號的“邊沿時刻”(如上升沿、下降沿),并通過內部定時器記錄時間戳。這與超聲波測距“測 Echo 高電平時間”的需求完全契合:
代碼實現如下:
/******************************************************************************
* FILENAME : Bsp_ECap.c
*
* PURPOSE : 超聲波測距接口函數
*
* Author: 電筆小新 Created on: 2025年9月12日
******************************************************************************/
#include "User_Include.h"
#include "Bsp_ECap.h"
//==================================================================
// * Variables & Function_Defines
//==================================================================
//超聲波發射引腳定義
#define UT_Trig_H (GpioDataRegs.GPBSET.bit.GPI39=1)
#define UT_Trig_L (GpioDataRegs.GPBCLEAR.bit.GPIO39=1)
Uint32 echo_width = 0;
//==================================================================
// * Function : InitECap1
// * Purpose : Initializes the ECap1 register parameters.
// * Parameters : Null
// * Return : Null
//==================================================================
void InitECap1(void)
{
//--- 1. 使能eCAP1時鐘 ---
EALLOW;
SysCtrlRegs.PCLKCR1.bit.ECAP1ENCLK = 1; // eCAP1
EDIS;
//--- 2. 配置UT發射接收GPIO ---
EALLOW;
// UT_Trig 初始化
GpioCtrlRegs.GPBPUD.bit.GPIO39 = 0; // 使能上拉
GpioCtrlRegs.GPBDIR.bit.GPIO39 = 1; // 輸出模式
GpioCtrlRegs.GPBMUX1.bit.GPIO39 = 0; // 普通GPIO功能
// UT_Echo 初始化
GpioCtrlRegs.GPADIR.bit.GPIO19 = 1; // 輸入模式
GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0; // 使能上拉
GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 3; // 選擇eCAP1功能(MUX=3)
EDIS;
//--- 3. eCAP寄存器配置 ---
EALLOW;
ECap1Regs.ECCTL1.bit.CAPLDEN = 0; // 禁止捕獲裝載
ECap1Regs.ECCTL1.bit.PRESCALE = 0; // 分頻系數=1(150MHz直接計數)
ECap1Regs.ECCTL2.bit.CAP_APWM = 0; // 捕獲模式(非PWM)
ECap1Regs.ECCTL2.bit.CONT_ONESHT = 0; // 單次捕獲模式
ECap1Regs.ECCTL2.bit.SYNCO_SEL = 0; // 無同步信號
ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // 使能時間戳計數器
ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // 使能捕獲裝載
EDIS;
//--- 4. 配置捕獲事件(上升沿+下降沿) ---
EALLOW;
ECap1Regs.ECCTL1.bit.CAP1POL = 0; // CAP1上升沿觸發
ECap1Regs.ECCTL1.bit.CTRRST1 = 1; // CAP1事件后計數器復位
ECap1Regs.ECCTL1.bit.CAP2POL = 1; // CAP2下降沿觸發
ECap1Regs.ECCTL1.bit.CTRRST2 = 1; // CAP2事件后計數器復位
EDIS;
//--- 5. 清除中斷標志并啟用中斷(可選) ---
EALLOW;
ECap1Regs.ECCLR.bit.CEVT1 = 1;
ECap1Regs.ECCLR.bit.CEVT2 = 1;
ECap1Regs.ECEINT.bit.CEVT1 = 1; // 使能CAP1中斷
ECap1Regs.ECEINT.bit.CEVT2 = 1; // 使能CAP2中斷
EDIS;
//--- 6. PIE中斷注冊 ---
EALLOW;
PieVectTable.ECAP1_INT = &ECAP1_INT_ISR;// 注冊ISR
PieCtrlRegs.PIEIER4.bit.INTx1 = 1; // 使能eCAP1中斷
EDIS;
//--- 7. 全局中斷使能 ---
IER |= M_INT4; // 使能CPU INT4
EINT; // 開全局中斷
}
//==================================================================
// * Function : Send_Trig_Pulse()
// * Purpose : 發送一個10us的超聲波脈沖
// * Parameters : Null
// * Return : Null
//==================================================================
void Send_Trig_Pulse(void)
{
UT_Trig_H;
DELAY_US(10);
UT_Trig_L;
}
//==================================================================
// * Function : Get_Distance()
// * Purpose : 計算超聲波測量距離
// * Parameters : Null
// * Return : distance_cm
//==================================================================
float Get_Distance(void)
{
float distance_cm = 0.0;
Send_Trig_Pulse();
My_DelayMs(1);
// 計算距離(150MHz時鐘,聲速340m/s)
distance_cm = (echo_width * (1.0/150.0)) * 0.0343 / 2.0;
return distance_cm;
}
// -----------------------------------------------------------
// INT_ISR for ECAP-1:
// -----------------------------------------------------------
// INT 4.1
interrupt void ECAP1_INT_ISR(void) // ECAP-1
{
// Insert ISR Code here
if (ECap1Regs.ECFLG.bit.CEVT1 == 1)
{
ECap1Regs.ECCLR.bit.CEVT1 = 1; // 清除中斷標志
}
if(ECap1Regs.ECFLG.bit.CEVT2 == 1)
{
echo_width =ECap1Regs.CAP2;
ECap1Regs.ECCLR.bit.CEVT2 = 1; // 清除中斷標志
}
ECap1Regs.ECCLR.all = 0xFFFF;// 清除中斷
PieCtrlRegs.PIEACK.all = PIEACK_GROUP4; // 確認PIE組4中斷
}
//==================================================================
// End of file.
//==================================================================