首先,先來(lái)看一下這個(gè)模塊的基本功能和原理。
HC-SR04超聲波測(cè)距模塊可提供2cm-400cm的非接觸式距離感測(cè)功能,測(cè)距精度可達(dá)高到3mm;模塊包括超聲波發(fā)射器、接收器與控制電路。像智能小車的測(cè)距以及轉(zhuǎn)向,或是一些項(xiàng)目中,常常會(huì)用到。智能小車測(cè)距可以及時(shí)發(fā)現(xiàn)前方的障礙物,使智能小車可以及時(shí)轉(zhuǎn)向,避開障礙物。
注意是5v輸入,但是我用stm32 的3.3v輸入也是沒有問題的。
二.工作原理 1.給超聲波模塊接入電源和地。
2.給脈沖觸發(fā)引腳(trig)輸入一個(gè)長(zhǎng)為20us的高電平方波 3.輸入方波后,模塊會(huì)自動(dòng)發(fā)射8個(gè)40KHz的聲波,與此同時(shí)回波引腳(echo)端的電平會(huì)由0變?yōu)?;(此時(shí)應(yīng)該啟動(dòng)定時(shí)器計(jì)時(shí))
4.當(dāng)超聲波返回被模塊接收到時(shí),回波引 腳端的電平會(huì)由1變?yōu)?;(此時(shí)應(yīng)該停止定時(shí)器計(jì)數(shù)),定時(shí)器記下的這個(gè)時(shí)間即為超聲波由發(fā)射到返回的總時(shí)長(zhǎng)。
5.根據(jù)聲音在空氣中的速度為344米/秒,即可計(jì)算出所測(cè)的距離。 要學(xué)習(xí)和應(yīng)用傳感器,學(xué)會(huì)看懂傳感器的時(shí)序圖是很關(guān)鍵的,所以我們來(lái)看一下HC-SR04的時(shí)序觸發(fā)圖。
我們來(lái)分析一下這個(gè)時(shí)序圖,先由觸發(fā)信號(hào)啟動(dòng)HC-RS04測(cè)距模塊,也就是說(shuō),主機(jī)要先發(fā)送至少10us的高電平,觸發(fā)HC-RS04,模塊內(nèi)部發(fā)出信號(hào)是傳感器自動(dòng)回應(yīng)的,我們不用去管它。輸出回響信號(hào)是我們需要關(guān)注的。信號(hào)輸出的高電平就是超聲波發(fā)出到重新返回接收所用的時(shí)間。用定時(shí)器,可以把這段時(shí)間記錄下來(lái),算出距離,別忘了結(jié)果要除于2,因?yàn)榭倳r(shí)間是發(fā)送和接收的時(shí)間總和。 下面是親測(cè)可用的驅(qū)動(dòng)程序。 芯片型號(hào)為stm32f103zet6,超聲波測(cè)距后通過(guò)串口打印到電腦上面。 驅(qū)動(dòng)和測(cè)距;
實(shí)驗(yàn)結(jié)果:
好了,其實(shí)這個(gè)模塊很簡(jiǎn)單,但是要是把他用的很好的話還是比較困難的,比如用超聲波做一個(gè)四軸定高的程序,還是有一定的挑戰(zhàn)性的。 寫這篇博客的目的不僅僅是介紹這個(gè)模塊的使用,其實(shí)這種使用介紹網(wǎng)上一搜一大把,我只是想紀(jì)錄一下,我在做這個(gè)模塊的時(shí)候遇到的一些其他的問題。 其中有一個(gè)小插曲,就是當(dāng)吧寫好的程序燒進(jìn)去之后,運(yùn)行時(shí)總是出現(xiàn)每次返回一個(gè)同樣的比正常值小的多的數(shù)據(jù),比如說(shuō)0.034cm,這明顯是一個(gè)錯(cuò)誤的數(shù)據(jù),但是剛開始的時(shí)候,不知道為什么 總是這樣,多次復(fù)位從新上電總是這一個(gè)數(shù)據(jù)。讓我很是苦惱。但是幸運(yùn)的是,在這樣的情況中間,他又會(huì)有時(shí)出現(xiàn)一兩個(gè)正常的的數(shù)據(jù),讓你有點(diǎn)摸不著頭腦。 上網(wǎng)查了一下才慢慢明白,這種現(xiàn)象叫做“余震”,網(wǎng)上關(guān)于余震的解釋大致有三種: 1、探頭的余震。即使是分體式的,發(fā)射頭工作完后還會(huì)繼續(xù)震一會(huì),這是物理效應(yīng),也就是余震。這個(gè)余震信號(hào)也會(huì)向外傳播。如果你的設(shè)計(jì)是發(fā)射完畢后立刻切換為接收狀態(tài)(無(wú)盲區(qū)),那么這個(gè)余震波會(huì)通過(guò)殼體和周圍的空氣,直接到達(dá)接收頭、干擾了檢測(cè)(注:通常的測(cè)距設(shè)計(jì)里,發(fā)射頭和接收頭的距離很近,在這么短的距離里超聲波的檢測(cè)角度是很大的,可達(dá)180度)。
2、殼體的余震。就像敲鐘一樣,能量仍來(lái)自發(fā)射頭。發(fā)射結(jié)束后,殼體的余震會(huì)直接傳導(dǎo)到接收頭,當(dāng)然這個(gè)時(shí)間很短,但已形成了干擾。另外,在不同的環(huán)境溫度下,殼體的硬度和外形會(huì)有所變化,其余震有時(shí)長(zhǎng)、有時(shí)短、有時(shí)干擾大、有時(shí)干擾小,這是設(shè)計(jì)工業(yè)級(jí)產(chǎn)品時(shí)必須要考慮的問題。
3、電路串?dāng)_。超聲波發(fā)射時(shí)的瞬間電流很大,例如某種工業(yè)級(jí)連續(xù)測(cè)距產(chǎn)品瞬間電流會(huì)有15A,通常的產(chǎn)品也能達(dá)到1A,瞬間這么大的電流會(huì)對(duì)電源有一定影響,并干擾接收電路。通過(guò)改善電源設(shè)計(jì)可以緩解這種情況,但在低成本設(shè)計(jì)中很難根除。所以每次發(fā)射完畢,接收電路還需要一段時(shí)間穩(wěn)定工作狀態(tài)。在此期間,其輸出的信號(hào)很難使用。
消除上述現(xiàn)象的方法之一就是在檢測(cè)的時(shí)候多次循環(huán)檢測(cè),取平均值,也就是加權(quán)平均濾波,一個(gè)簡(jiǎn)單的濾波處理。就是下面這一段: - u32 t = 0;
- int i = 0;
- float lengthTemp = 0;
- float sum = 0;
- while(i!=5)
- {
- TRIG_Send = 1; //發(fā)送口高電平輸出
- Delay_Us(20);
- TRIG_Send = 0;
- while(ECHO_Reci == 0); //等待接收口高電平輸出
- OpenTimerForHc(); //打開定時(shí)器
- i = i + 1;
- while(ECHO_Reci == 1);
- CloseTimerForHc(); //關(guān)閉定時(shí)器
- t = GetEchoTimer(); //獲取時(shí)間,分辨率為1US
- lengthTemp = ((float)t/58.0);//cm
- sum = lengthTemp + sum ;
-
-
- lengthTemp = sum/5.0;
- return lengthTemp;
復(fù)制代碼
加了這個(gè)之后,基本上就沒有出現(xiàn)余震現(xiàn)象了。
還有一點(diǎn)就是測(cè)試程序前一定要檢查引腳有沒有接錯(cuò),不管多有把握,也要看一遍,不然很容易出大事的,一個(gè)芯片也許就因?yàn)槟愕拇笠饨oGG了。切記,這個(gè)應(yīng)該也算我們這個(gè)行業(yè)的基本素養(yǎng)吧。
- //超聲波測(cè)距
-
- #include "hcsr04.h"
-
- #define HCSR04_PORT GPIOB
- #define HCSR04_CLK RCC_APB2Periph_GPIOB
- #define HCSR04_TRIG GPIO_Pin_5
- #define HCSR04_ECHO GPIO_Pin_6
-
- #define TRIG_Send PBout(5)
- #define ECHO_Reci PBin(6)
-
- u16 msHcCount = 0;//ms計(jì)數(shù)
-
- void Hcsr04Init()
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //生成用于定時(shí)器設(shè)置的結(jié)構(gòu)體
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);
-
- //IO初始化
- GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG; //發(fā)送電平引腳
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
- GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
- GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
-
- GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO; //返回電平引腳
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
- GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
- GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);
-
- //定時(shí)器初始化 使用基本定時(shí)器TIM6
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); //使能對(duì)應(yīng)RCC時(shí)鐘
- //配置定時(shí)器基礎(chǔ)結(jié)構(gòu)體
- TIM_DeInit(TIM2);
- TIM_TimeBaseStructure.TIM_Period = (1000-1); //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值 計(jì)數(shù)到1000為1ms
- TIM_TimeBaseStructure.TIM_Prescaler =(72-1); //設(shè)置用來(lái)作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值 1M的計(jì)數(shù)頻率 1US計(jì)數(shù)
- TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//不分頻
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
- TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
-
- TIM_ClearFlag(TIM6, TIM_FLAG_Update); //清除更新中斷,免得一打開中斷立即產(chǎn)生中斷
- TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE); //打開定時(shí)器更新中斷
- hcsr04_NVIC();
- TIM_Cmd(TIM6,DISABLE);
- }
-
-
- //tips:static函數(shù)的作用域僅限于定義它的源文件內(nèi),所以不需要在頭文件里聲明
- static void OpenTimerForHc() //打開定時(shí)器
- {
- TIM_SetCounter(TIM6,0);//清除計(jì)數(shù)
- msHcCount = 0;
- TIM_Cmd(TIM6, ENABLE); //使能TIMx外設(shè)
- }
-
- static void CloseTimerForHc() //關(guān)閉定時(shí)器
- {
- TIM_Cmd(TIM6, DISABLE); //使能TIMx外設(shè)
- }
-
-
- //NVIC配置
- void hcsr04_NVIC()
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-
- NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; //選擇串口1中斷
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占式中斷優(yōu)先級(jí)設(shè)置為1
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應(yīng)式中斷優(yōu)先級(jí)設(shè)置為1
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中斷
- NVIC_Init(&NVIC_InitStructure);
- }
-
-
- //定時(shí)器6中斷服務(wù)程序
- void TIM6_IRQHandler(void) //TIM3中斷
- {
- if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) //檢查TIM3更新中斷發(fā)生與否
- {
- TIM_ClearITPendingBit(TIM6, TIM_IT_Update ); //清除TIMx更新中斷標(biāo)志
- msHcCount++;
- }
- }
-
-
- //獲取定時(shí)器時(shí)間
- u32 GetEchoTimer(void)
- {
- u32 t = 0;
- t = msHcCount*1000;//得到MS
- t += TIM_GetCounter(TIM6);//得到US
- TIM6->CNT = 0; //將TIM2計(jì)數(shù)寄存器的計(jì)數(shù)值清零
- Delay_Ms(50);
- return t;
- }
-
-
- //一次獲取超聲波測(cè)距數(shù)據(jù) 兩次測(cè)距之間需要相隔一段時(shí)間,隔斷回響信號(hào)
- //為了消除余震的影響,取五次數(shù)據(jù)的平均值進(jìn)行加權(quán)濾波。
- float Hcsr04GetLength(void )
- {
- u32 t = 0;
- int i = 0;
- float lengthTemp = 0;
- float sum = 0;
- while(i!=5)
- {
- TRIG_Send = 1; //發(fā)送口高電平輸出
- Delay_Us(20);
- TRIG_Send = 0;
- while(ECHO_Reci == 0); //等待接收口高電平輸出
- OpenTimerForHc(); //打開定時(shí)器
- i = i + 1;
- while(ECHO_Reci == 1);
- CloseTimerForHc(); //關(guān)閉定時(shí)器
- t = GetEchoTimer(); //獲取時(shí)間,分辨率為1US
- lengthTemp = ((float)t/58.0);//cm
- sum = lengthTemp + sum ;
-
- }
- lengthTemp = sum/5.0;
- return lengthTemp;
- }
-
-
- /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- ** 函數(shù)名稱: Delay_Ms_Ms
- ** 功能描述: 延時(shí)1MS (可通過(guò)仿真來(lái)判斷他的準(zhǔn)確度)
- ** 參數(shù)描述:time (ms) 注意time<65535
- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
- void Delay_Ms(uint16_t time) //延時(shí)函數(shù)
- {
- uint16_t i,j;
- for(i=0;i<time;i++)
- for(j=0;j<10260;j++);
- }
- /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- ** 函數(shù)名稱: Delay_Ms_Us
- ** 功能描述: 延時(shí)1us (可通過(guò)仿真來(lái)判斷他的準(zhǔn)確度)
- ** 參數(shù)描述:time (us) 注意time<65535
- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
- void Delay_Us(uint16_t time) //延時(shí)函數(shù)
- {
- uint16_t i,j;
- for(i=0;i<time;i++)
- for(j=0;j<9;j++);
- }
復(fù)制代碼
但是關(guān)于USART的函數(shù)我就不往上寫了,這個(gè)簡(jiǎn)單的串口打印大家應(yīng)該都會(huì)寫。下面簡(jiǎn)單貼一下我的主函數(shù)吧。 - /*
- 教訓(xùn):實(shí)驗(yàn)前一定要檢查引腳連接是否正確,萬(wàn)不可搞錯(cuò),不然又要燒壞芯片。。!
- 2017.6.8
- */
-
- #include "hcsr04.h"
- #include "chao_usart.h"
-
- int main()
- {
-
- float length;
-
- GPIO_cfg();
- NVIC_cfg();
- USART_cfg();
- printf("串口初始化成功!");
-
- Hcsr04Init();
- printf("超聲波初始化成功!");//測(cè)試程序是否卡在下面兩句上面
-
- length = Hcsr04GetLength();
- printf("距離為:%.3f",length);
-
-
- }
復(fù)制代碼
全部資料51hei下載地址:
programcsb.rar
(347.19 KB, 下載次數(shù): 342)
2018-4-7 00:45 上傳
點(diǎn)擊文件名下載附件
|