单片机开发无线控制系列-手机无线超声波测距
? ? 用超聲波模塊來測距是非常方便有效的方式,而且精度比較高。超聲波測距模塊就是通過測量聲波從發出到反射回來的時間來計算距離。因為聲音在空氣中傳播的速度大概在340m/s左右,知道了往返時間再乘以速度就可以得出距離了。當然聲速并不一定是固定的,這與空氣溫度、氣壓都是有一定關系的,因此超聲波存在一定的誤差。
? ? 超聲波模塊提供的使用接口很簡單,除了5V和GND的供電接口外,提供了Trig和Echo兩個口。在使用時,如下圖:
?
? ? 首先單片機通過Trig口,產生10微秒以上的高電平(其實時間更長一些也不會有太大影響),然后超聲波模塊會自動發射出一串40kHz的超聲波。發射結束后,超聲波模塊內部開始計數,超聲波被發出后,沿直線方向前進,如果遇到面積比較大的目標,其一部分的聲波會被反射回來,然后在A點時刻,返回的聲波被超聲波探頭接收到。超聲波模塊接收到回波就會立刻拉高Echo引腳,然后持續 “它等待聲波的那段時間” 后,在B點時刻將Echo下拉。
? ? 因此在使用時,我們需要在Echo的上升沿(A點)開始計時,然后在下降沿(B點)停止計時,得到的時間就是聲波傳遞往返的時間。
一、單片機部分
1.1硬件連接
? ? 這里我用兩個普通IO口連接其Trig和Echo。在程序中使用的是Trig為PA6,Echo為PA7。
1.2代碼編寫
1.2.1超聲波程序
? ? 首先初始化,這里采用STM32的EXTI(外部中斷)的功能,用于檢測Echo口的上升沿和下降沿,以確定A點和B點。然后使用STM32的TIM2定時器來計時,當Echo上升沿時開始計時,下降沿時結束,并讀取計時數值。
void initUltraSonic(){
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;?
RCC_APB2PeriphClockCmd(USONIC_PORT_CLOCK, ENABLE);?
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);?
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);?
GPIO_InitStructure.GPIO_Pin = TRIG_PIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;?
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(USONIC_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ECHO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;?
GPIO_Init(USONIC_PORT, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource7);?
EXTI_InitStructure.EXTI_Line = EXTI_Line7;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;?
?EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;?
?EXTI_InitStructure.EXTI_LineCmd = ENABLE;?
?EXTI_Init(&EXTI_InitStructure);?
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;?
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;?
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;?
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;?
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2,ENABLE); // 雖然TIM2掛載在36MHz的APB1下,但是其實際最高時鐘頻率可達72MHz。
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 719; /// 719 = (72000000/100000)-1 ,每10us 計數器加一
TIM_TimeBaseStructure.TIM_ClockDivision = 0;?
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;?
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
GPIO_ResetBits(USONIC_PORT,TRIG_PIN);}
下面是中斷處理函數,STM32外部中斷處理比較奇葩,為了節省函數入口,將Pin5到Pin9的通道合到一起,然后在中斷處理函數中判斷到底是哪個腳觸發了中斷。
void? EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line7))
{
//上升沿
if(GPIO_ReadInputDataBit(USONIC_PORT,ECHO_PIN))
{
//清零定時器值
TIM2->CNT=0;
//開始計時
TIM_Cmd(TIM2,ENABLE);
}else//下降沿
{
//讀取定時器值
c = TIM2->CNT;
TIM_Cmd(TIM2,DISABLE);
}
//清除中斷標志位
EXTI_ClearITPendingBit(EXTI_Line7);
}
}
然后是一個10微秒的延時程序,其實我也不知道是不是10微秒,實測是可以用的。
void delay10us(void){
for(short s=0;s<70;s++)
{}
}
然后是讀取距離的函數:
short procUltraSonic(void){
short distance_mm;
if(c!=0)
distance_mm= (17*c/10);
GPIO_SetBits(USONIC_PORT,TRIG_PIN);
delay10us();
GPIO_ResetBits(USONIC_PORT,TRIG_PIN);
c=0;
return distance_mm;
}
1.2.2通信配置
//根據實際需要的變量,定義數據包中 bool byte short int float 五種類型的數目
#defineTX_BOOL_NUM0
#defineTX_BYTE_NUM0
#defineTX_SHORT_NUM 1?
#defineTX_INT_NUM0
#defineTX_FLOAT_NUM0
在valuepack.h中定義收發的數據,由于只回傳一個距離值,因此定義short的數目為1。
1.2.3主函數
TxPack txpack;
int main(void)
{
initUltraSonic();
initValuePack(115200);
while(1)
{
//延時
for(int i=0;i<1000000;i++)
{}
txpack.shorts[0] =procUltraSonic();
sendValuePack(&txpack);
}
}
在主函數中只需要調用procUltraSonic函數,即可得到毫米為單位的short值。
完整代碼在此
二、手機端(使用藍牙調試器)
2.1配置通信
?
2.2編輯控件
。。。鏈接和布局,具體我就不說了,在我之前的文章已經介紹了,如果有疑問,點擊這里。
掃描下邊的二維碼下載 藍牙調試器 搭建你自己的App界面
俗人一個,只要有人用了我的應用之后回來說一句“挺好用”我就真的滿足了。當然能讓我不餓肚子就更好了,大齡青年真的沒臉問父母要錢。覺得有意思的話,支持一下吧。
總結
以上是生活随笔為你收集整理的单片机开发无线控制系列-手机无线超声波测距的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 两码运营:孕育而生
- 下一篇: Android攻城狮ViewFlippe