首頁 > 評測 > 基于CH32V103實現(xiàn)HC-SR04 超聲波測距模塊輪詢讀取距離數(shù)據(jù)

基于CH32V103實現(xiàn)HC-SR04 超聲波測距模塊輪詢讀取距離數(shù)據(jù)

  
  • 作者:
  • 來源:
  • [導讀]
  • 本帖最后由 lilijin1995 于 2023-3-17 23:13 編輯 一般的我自己學習單片機,為了更加了解硬件,我都會畫了一塊CH32V103最小系統(tǒng)板,然后外接其他功能模塊實現(xiàn)一些應(yīng)用,現(xiàn)在秀一秀自己畫的板子,雖然設(shè)計得不

本帖最后由 lilijin1995 于 2023-3-17 23:13 編輯

一般的我自己學習單片機,為了更加了解硬件,我都會畫了一塊CH32V103最小系統(tǒng)板,然后外接其他功能模塊實現(xiàn)一些應(yīng)用,現(xiàn)在秀一秀自己畫的板子,雖然設(shè)計得不怎樣,哈哈哈。!



最近翻箱底有一款超聲波測距,HC-SR04,


那么現(xiàn)在就開始實現(xiàn)HC-SR04 超聲波測距模塊輪詢讀取距離數(shù)據(jù)

硬件接口:根據(jù)規(guī)格書可以看到接口定義如下圖:

我們定義PA0映射TRIG,PA1-TIM2CH2映射ECHO,供電為5V。

軟件說明:
超聲波時序圖如下:

以上時序圖表明你只需要提供一個 10uS 以上脈沖觸發(fā)信號,該模塊內(nèi)部將
發(fā)出 8 個 40kHz 周期電平并檢測回波。一旦檢測到有回波信號則輸出回響信號 。
回響信號的脈沖寬度與所測的距離成正比。由此通過發(fā)射信號到收到的回響信號
時間間隔可以計算得到距離。公式:uS/58=厘米或者 uS/148=英寸;或是:距離=
高電平時間*聲速(340M/S)/2;建議測量周期為 60ms 以上,以防止發(fā)射信號對
回響信號的影響。
這里主要是ECHO配置TIMCH2輸入捕獲配置,如下代碼:

  1. /*********************************************************************
  2. * @fn      TIM2_ICapture_Init
  3. *
  4. * [url=home.php?mod=space&uid=247401]@brief[/url]   Initializes TIM1 input capture.
  5. *
  6. * @param   arr - the period value.
  7. *          psc - the prescaler value.
  8. *          ccp - the pulse value.
  9. *
  10. * [url=home.php?mod=space&uid=266161]@return[/url]  none
  11. */
  12. void TIM2_ICapture_Init(u16 arr, u16 psc)
  13. {
  14.     GPIO_InitTypeDef        GPIO_InitStructure = {0};
  15.  
  16.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};
  17.     NVIC_InitTypeDef        NVIC_InitStructure = {0};
  18.  
  19.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  20.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2時鐘
  21.  
  22.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  23.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  24.     GPIO_Init(GPIOA, &GPIO_InitStructure);
  25.     GPIO_ResetBits(GPIOA, GPIO_Pin_1);
  26.  
  27.     TIM_TimeBaseInitStructure.TIM_Period = arr;
  28.     TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
  29.     TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  30.     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  31.     TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
  32.  
  33.     TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  34.     TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  35.     TIM_ICInitStructure.TIM_ICFilter = 0x00;
  36.     TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  37.     TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  38.     TIM_ICInit(TIM2,&TIM_ICInitStructure);
  39.  
  40.     NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  41.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  42.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  43.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  44.     NVIC_Init(&NVIC_InitStructure);
  45.  
  46.     TIM_ITConfig(TIM2, TIM_IT_Update | TIM_IT_CC2, ENABLE);
  47.  
  48.     TIM_Cmd(TIM2, ENABLE);
  49. }
復制代碼

我們直接在中斷里面計算高電平時間,這里面參考了正點原子的輸入捕獲實驗

  1. //TIM2CH2_CAPTURE_STA
  2. //bit7:捕獲完成標志
  3. //bit6:捕獲到高電平標志
  4. //bit5~0:捕獲到高電平后定時器溢出的次數(shù)
  5. u8  TIM2CH2_CAPTURE_STA=0;  //輸入捕獲狀態(tài)
  6. u16 TIM2CH2_CAPTURE_VAL;    //輸入捕獲值,用來記錄捕獲到下降沿的時候,TIM2_CNT的值
  7.  
  8. //定時器2中斷服務(wù)程序
  9. void TIM2_IRQHandler(void)
  10. {
  11.  
  12.     if((TIM2CH2_CAPTURE_STA&0X80)==0)//還未成功捕獲
  13.     {
  14.         if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
  15.  
  16.         {
  17.  
  18.             if(TIM2CH2_CAPTURE_STA&0X40)//已經(jīng)捕獲到高電平了
  19.             {
  20.                 if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)//高電平太長了
  21.                 {
  22.                     TIM2CH2_CAPTURE_STA|=0X80;//標記成功捕獲了一次
  23.                     TIM2CH2_CAPTURE_VAL=0XFFFF;
  24.                 }else TIM2CH2_CAPTURE_STA++;
  25.             }
  26.         }
  27.     if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)//捕獲2發(fā)生捕獲事件
  28.         {
  29.             if(TIM2CH2_CAPTURE_STA&0X40)        //捕獲到一個下降沿
  30.             {
  31.                 TIM2CH2_CAPTURE_STA|=0X80;      //標記成功捕獲到一次高電平脈寬
  32.                 TIM2CH2_CAPTURE_VAL=TIM_GetCapture2(TIM2);
  33.                 TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC2P=0 設(shè)置為上升沿捕獲
  34.             }else                               //還未開始,第一次捕獲上升沿
  35.             {
  36.                 TIM2CH2_CAPTURE_STA=0;          //清空
  37.                 TIM2CH2_CAPTURE_VAL=0;
  38.                 TIM_SetCounter(TIM2,0);
  39.                 TIM2CH2_CAPTURE_STA|=0X40;      //標記捕獲到了上升沿
  40.                 TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Falling);     //CC1P=1 設(shè)置為下降沿捕獲
  41.             }
  42.         }
  43.     }
  44.  
  45.     TIM_ClearITPendingBit(TIM2, TIM_IT_CC2|TIM_IT_Update); //清除中斷標志位
  46.  
  47. }
復制代碼


捕獲了高電平時間,直接除以58就是距離值:我們直接看我們的SR04驅(qū)動:

  1. void SR04_Init(void)
  2. {
  3.     GPIO_InitTypeDef  GPIO_InitStructure;
  4.  
  5.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能PB,PE端口時鐘
  6.  
  7.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;               //LED0-->PB.5 端口配置
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //推挽輸出
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //IO口速度為50MHz
  10.     GPIO_Init(GPIOA, &GPIO_InitStructure);                  //根據(jù)設(shè)定參數(shù)初始化GPIOB.5
  11.     GPIO_SetBits(GPIOA,GPIO_Pin_0);                         //PB.5 輸出高
  12.     TIM2_ICapture_Init(0xFFFF,71);
  13.     TRIG(0);
  14. }
  15.  
  16.  
  17.  
  18. u32 SR04_Handler(void)
  19. {
  20.     u32 temp=0,Distance=0;
  21.  
  22.     //TRig
  23.     Delay_Ms(1);
  24.     TRIG(1);
  25.     Delay_Ms(15);
  26.     TRIG(0);
  27.  
  28.     //計算距離
  29. if(TIM2CH2_CAPTURE_STA&0X80)        //成功捕獲到了一次高電平
  30.     {
  31.         temp=TIM2CH2_CAPTURE_STA&0X3F;
  32.         temp*=65536;                    //溢出時間總和
  33.         temp+=TIM2CH2_CAPTURE_VAL;      //得到總的高電平時間
  34.         Distance=(temp/58);
  35.         printf("Distance:%d cm\r\n",Distance);  //打印總的高點平時間
  36.         TIM2CH2_CAPTURE_STA=0;          //開啟下一次捕獲
  37.  
  38.         return Distance;
  39.     }
  40.      return 0;
  41. }
復制代碼


下載驗證:

  • 本文系21ic原創(chuàng),未經(jīng)許可禁止轉(zhuǎn)載!

網(wǎng)友評論