使用STM32F407控制5路超聲波感測器

2021-07-25 00:06:48 字數 2971 閱讀 4245

最近在做小車避障的功能,需要用stm32f407控制5個感測器,結合板子的示例程式,除錯了一段時間,終於成功讀出5路感測器的測距資訊。

感測器原理不詳細說了,基本上從trig腳給乙個脈寬10us以上的脈衝,然後發射探頭發出8個40khz的脈衝,檢測到回波後,從echo管腳輸出高電平,高電平的持續時間與距離值關係為:(高電平時間*340m/s)/2。使用中,只要採集到echo腳高電平的持續時間,就能測距了。

在stm32f407上測量某一管腳的電平持續時間需要使用定時器的捕獲功能(不知道有沒有更簡單的實現方法),查了手冊,對於捕獲模式的解釋:在輸入捕獲模式下,當相應的icx 訊號檢測到跳變沿后,將使用捕獲/比較暫存器(timx_ccrx)來鎖存計數器的值。發生捕獲事件時,會將相應的ccxif 標誌(timx_sr 暫存器)置1,並可傳送中斷或dma 請求(如果已使能)。如果發生捕獲事件時ccxif 標誌已處於高位,則會將重複捕獲標誌ccxof(timx_sr 暫存器)置1。可通過軟體向ccxif 寫入0 來給ccxif清零,或讀取儲存在timx_ccrx暫存器中的已捕獲資料。向ccxof 寫入0 後會將其清零。其實就是在上公升沿和下降沿分別記錄定時器計數器的值,其差值相當於脈衝寬度。關於指點,網上找的圖可以較清晰地表達:

首先設定定時器通道 x 為上公升沿捕獲,這樣, t1 時刻,就會捕獲到當前的 cnt 值,然後立即清零 cnt,並設定通道 x為下降沿捕獲,這樣到 t2 時刻,又會發生捕獲事件,得到此時的 cnt 值,記為 ccrx2。 這樣,根據定時器的計數頻率,可以算出 t1~t2 的時間,從而得到高電平脈寬。 在t1~t2時,可能計數器會超過設定值arr,產生定時器溢位,這樣就要對定時器溢位處理。最終,如圖所示,t1~t2之間,cnt計數的次數等於:n*arr+ccrx2,有了這個計數次數,再乘以 cnt 的計數週期,即可得到 t2-t1 的時間長度,即高電平持續時間。

我用了tim2和tim5兩個定時器,這兩個定時器可提供8路通道,我用了5個。其中tim5的ch2通道被占用,只要開中斷就會不停進中斷服務程式,故不用。定時器的設定是最重要的部分,放在tim_cap_init()中,**流程如下:

首先配置tim2和tim5的中斷優先順序(nvic_initstructure),註冊中斷型別。然後配置tim2和tim5對應通道時鐘,使能tim時鐘和gpio時鐘,配置gpio工作模式(gpio_init),包括管腳、下拉、功能、速度等,再將管腳復用對映到對應定時器上(gpio_pinafconfig)。設定定時器的計數頻率和計數模式等(tim_timebaseinit)。之後設定捕獲引數(tim_icinit):上公升沿捕獲、分頻、濾波、用到的通道等等。設定完成後允許中斷(tim_itconfig),使能定時器(tim_cmd),定時器開始計數。

當進入中斷服務程式時,先判斷引起中斷的型別,如果是某個通道引起的中斷,呼叫單通道捕獲處理函式,否則表示update中斷,需要清除中斷標誌位。根據實際情況,上電時進入中斷服務程式,中斷型別tim_it_update,要是不清除標誌位,會不停進入中斷。中斷服務程式**:

void tim5_irqhandler(void)

if(tim_getitstatus(tim5, tim_it_cc3) !=reset)

}

void tim2_irqhandler(void)

if(tim_getitstatus(tim2, tim_it_cc3) !=reset)

if(tim_getitstatus(tim2, tim_it_cc4) !=reset)

}

void singlechannelhandler(tim_capture * tch )

else tch->capture_val++;

} } if(tim_getitstatus(tch->timx, tch->tim_it_ccx) != reset)//²¶»ñ1·¢éú²¶»ñêâ¼þ

//printf(" tch->tim_it_ccx = %d ",tch->tim_it_ccx); //´òó¡×üµä¸ßµãæ½ê±¼ä

//tim_oc1polarityconfig(tch->timx,tim_icpolarity_rising); //cc1p=0 éèöãîªéïéýñø²¶»ñ

}else //»¹î´¿ªê¼,µúò»´î²¶»ñéïéýñø

tim_cmd(tch->timx,enable ); //ê¹äü¶¨ê±æ÷s

}

}

} tim_clearitpendingbit(tch->timx, tch->tim_it_ccx | tim_it_update); //çå³ýöð¶ï±êö¾î»

}

首先自定義了標誌字capture_sta,共8位,最高位d7=1表示成功捕獲到高電平脈寬,即捕獲到上公升沿后又捕獲到下降沿,d6=1表示捕獲到上公升沿,d5~d0表示定時器溢位次數。capture_sta初始為0,程式開始判斷是否成功捕獲,未成功捕獲則繼續,這樣捕獲成功後就不再執行了。然後判斷捕獲型別,如果是某個通道引起的,則檢視標誌字,如果d6=0,說明是由於首次捕獲到上公升沿而進入中斷,設定d6=1,計數器清零,然後配置捕獲下降沿,這樣再次進入中斷時,可以看到標誌字d6=1,說明此時捕獲到了下降沿,讀取計數器的值,可獲得高電平時間。如果進入中斷的型別是tim_it_update,說明定時器計數溢位,根據之前定時器的設定,tim2和tim5均為1us累加1次,32位的定時器,溢位需要4292s,這樣現實中是不會出現的,所以可以不做處理,但是為了以防萬一,強制設定捕獲成功。

在main函式中迴圈判斷capture_sta狀態,成功捕獲後讀取計數值可以計算出距離資訊,將結果通過串列埠列印出來,如圖:

5個感測器能檢測到距離資訊,下一步考慮準備安裝在小車上了。

基於stm32f407建立stm32F427工程

分為三個部分 1.啟動檔案 2.fwilib 包含兩個資料夾inc和src。src裡面是stm32資源的c檔案,inc則是32資源的h檔案 3.user這也是我不太理解的部分 ddbugconfig只包含了用於debug的初始化,則是f4的系統檔案。我是在f407的基礎上改的 總的來說 1.改了晶元...

STM32F407上除錯freeRTOS問題

是在正點原子的阿波羅stm32f429開發板上的例子改來的,他們的編譯沒有問題,我編譯時出現如下問題 定位到出錯的地方,是 再追 configmax syscall interrupt priority 的定義是 define configmax syscall interrupt priority...

STM32F407 驅動外部SRAM

需要驅動的sram型號為is61lv25616al,價效比比51216的高很多 配置cubemx 這幾個時序比較關鍵,可以按照手冊來計算,我用下來這幾個數值比較合適。然後就沒有然後了,生成 就可以用了。檢查sram內容是否正確 uint8 t bsp testextsram void 寫sram p...