cubemx下的輸入捕獲進行超聲波測距

主控板

  • NUCLEO-F411RE

NUCLEO-F411RE 是ST公司推出的一款針對STM32F4系列設計的Cortex-M4開發板,具有 mbed 功能,支持Arduino。同時還提供 ST Morpho 擴展排針,可連接微控制器的所有周邊外設。
開發板基於STM32F411RET6設計,開發板還集成了ST-LINK/V2-1仿真下載器(但僅對外提供SWD接口),免除另外採購仿真器或下載器的麻煩。並且具備Arduino接口,可接入 Arduino 巨大生態系統的各種 Shield 擴展板,能夠輕鬆快速增加特殊功能。

超聲波模塊

  • HC-SR04超聲波模塊

使用HC-SR04超聲波模塊,此模塊性能穩定,測度距離精確,模塊高精度,盲區小。主要的電氣參數如下:

電氣參數 HC-SR04超聲波模塊
工作電壓 DC 5V
工作電流 15mA
工作頻率 40Hz
最遠射程 4m
最近射程 2cm
測量角度 15度
輸入觸發信號 10Us的TTL脈衝
輸出迴響信號 輸出TTL電平信號,與射程成比例
規格尺寸 45*20*15mm

基本工作原理:
1、採用IO口TRIG觸發測距,給至少10us的高電平信號;
2、模塊自動發送8個40khz的方波,自動檢測是否有信號返回;
3、有信號返回,通過IO口ECHO輸出一個高電平,高電平持續的時間就是超聲波從發射到返回的時間。測試距離=(高電平時間*聲速(340M/S))/2;

本模塊使用方法簡單,一個控制口發一個10US以上的高電平,就可以在接收口等待高電平輸出.一有輸出就可以開定時器計時,當此口變爲低電平時就可以讀定時器的值,此時就爲此次測距的時間,方可算出距離.如此不斷的週期測,即可以得到你移動測量的值。超聲波模塊時序圖如下:
這裏寫圖片描述

輸入捕獲簡介

輸入捕獲可以用來測量脈衝寬度或者測量頻率。超聲波用到的是測量脈寬,這裏我以測量脈寬爲例,用一個簡圖來說明輸入捕獲的原理,如下圖:
這裏寫圖片描述

如上圖所示,就是輸入捕獲測量高電平脈寬的原理,假定定時器工作在向上計數模式,圖中t1-t2時間,就是我們需要測量的高電平時間。測量方法如下:首先設置定時器通道x爲上升沿捕獲,這樣,t1時刻就會捕捉到CNT值,然後立即清零CNT,並設置通道x爲下降沿捕獲,這樣t2時刻又會發生捕獲事件,得到此時的CNT值,記爲CCRx2。這樣,根據定時器的計數頻率,我們就可以算出t1-t2的時間,從而得到高電平的脈寬。

在t1-t2之間,可能產生N次定時器溢出,這就要求我們對定時器溢出做處理,防止高電平太長,導致數據不準確。如上圖所示,t1-t2之間CNT計數的的次數等於:N*ARR+CRRx2,有了這個計數次數,再乘以CNT的計數週期,即可得到t1-t2的時間長度,即高電平持續時間。

STM32CubeMX配置定時器輸入捕獲功能

使用STM32CubeMX配置輸入捕獲功能初始化代碼步驟如下:

  1. 在Pinout->TIM2配置項中,配置Channel1的值爲Input Capture direct mode,然後選中Internal Clock。操作過程如下圖所示
    這裏寫圖片描述
  2. 進入Configuration->TIM2配置頁,在彈出的界面中點擊Parameter Settings選項卡,Counter Settings配置欄下面的四個選項就是用來配置定時器的預分頻係數,自動裝載值,計數模式以及時鐘分頻因子。在界面的Input Capture Channel 1配置欄配置輸入捕獲通道1的捕獲極性,分頻係數、映射、濾波器等參數,操作方法如下圖:
    這裏寫圖片描述

  3. 進入Configuration->NVIC配置頁,在彈出的界面中點擊NVIC選項卡,配置Interrupt
    這裏寫圖片描述

  4. 配置PA1口爲輸出口
    這裏寫圖片描述

配置完上面步驟後,生成代碼。在生成的代碼中,並沒有使能相應中斷的代碼,也沒有改寫中斷處理回調函數,這都需要我們自己來編寫

軟件設計

tim.c文件新增的內容如下

/* USER CODE BEGIN 1 */
uint8_t   TIM2CH1_CAPTURE_STA=0;    //ÊäÈ벶»ñ״̬                          
uint32_t    TIM2CH1_CAPTURE_VAL;    //ÊäÈ벶»ñÖµ(TIM2/TIM5ÊÇ32λ)

//¶¨Ê±Æ÷¸üÐÂÖжϣ¨¼ÆÊýÒç³ö£©Öжϴ¦Àí»Øµ÷º¯Êý£¬ ¸Ãº¯ÊýÔÚHAL_TIM_IRQHandlerÖлᱻµ÷ÓÃ
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//¸üÐÂÖжϣ¨Òç³ö£©·¢ÉúʱִÐÐ
{

    if((TIM2CH1_CAPTURE_STA&0X80)==0)//»¹Î´³É¹¦²¶»ñ
    {
            if(TIM2CH1_CAPTURE_STA&0X40)//ÒѾ­²¶»ñµ½¸ßµçƽÁË
            {
                if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//¸ßµçƽ̫³¤ÁË
                {
                    TIM2CH1_CAPTURE_STA|=0X80;      //±ê¼Ç³É¹¦²¶»ñÁËÒ»´Î
                    TIM2CH1_CAPTURE_VAL=0XFFFFFFFF;
                }
                else TIM2CH1_CAPTURE_STA++;
            }    
    }       
}


//¶¨Ê±Æ÷ÊäÈ벶»ñÖжϴ¦Àí»Øµ÷º¯Êý£¬¸Ãº¯ÊýÔÚHAL_TIM_IRQHandlerÖлᱻµ÷ÓÃ
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//²¶»ñÖжϷ¢ÉúʱִÐÐ
{
    if((TIM2CH1_CAPTURE_STA&0X80)==0)//»¹Î´³É¹¦²¶»ñ
    {
        if(TIM2CH1_CAPTURE_STA&0X40)        //²¶»ñµ½Ò»¸öϽµÑØ      
            {               
                TIM2CH1_CAPTURE_STA|=0X80;      //±ê¼Ç³É¹¦²¶»ñµ½Ò»´ÎµÍµçƽÂö¿í
                TIM2CH1_CAPTURE_VAL=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//»ñÈ¡µ±Ç°µÄ²¶»ñÖµ.

                long long temp=0;
                temp=TIM2CH1_CAPTURE_STA&0X3F; 
                temp*=0XFFFFFFFF;               //Òç³öʱ¼ä×ܺÍ
                temp+=TIM2CH1_CAPTURE_VAL;      //µÃµ½×ܵĸߵçƽʱ¼ä
                temp=temp*17/1000;
                printf("distence:%lld cm\r\n",temp);//´òÓ¡×ܵĸߵãƽʱ¼ä 
                __HAL_TIM_DISABLE(&htim2);        //¹Ø±Õ¶¨Ê±Æ÷2
            }
        else                                //»¹Î´¿ªÊ¼,µÚÒ»´Î²¶»ñÉÏÉýÑØ
            {
                TIM2CH1_CAPTURE_STA=0;          //Çå¿Õ
                TIM2CH1_CAPTURE_VAL=0;
                TIM2CH1_CAPTURE_STA|=0X40;      //±ê¼Ç²¶»ñµ½ÁËÉÏÉýÑØ
                __HAL_TIM_DISABLE(&htim2);        //¹Ø±Õ¶¨Ê±Æ÷2
                __HAL_TIM_SET_COUNTER(&htim2,0);
                TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1);   //Ò»¶¨ÒªÏÈÇå³ýÔ­À´µÄÉèÖã¡£¡
                TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1, TIM_ICPOLARITY_FALLING);//¶¨Ê±Æ÷2ͨµÀ1ÉèÖÃΪÉÏϽµÑز }           
    }       

}
/* USER CODE END 1 */

定義了兩個全局變量,用於輔助實現高電平捕獲。其中TIM2CH1_CAPTURE_STA是用來記錄捕獲狀態,各位描述如下:輔助實現高電平捕獲。其中TIM2CH1_CAPTURE_STA是用來記錄捕獲狀態,各位描述如下:
bit7:捕獲完成標誌
bit6:捕獲到高電平的標誌
bit5~0:捕獲高電平後定時器溢出的次數
另一個變量TIM2CH1_CAPTURE_VAL,則用來記錄捕獲到下降沿的時候,TIM2_CNT的值。

main函數內容

int main(void)
{

  /* USER CODE BEGIN 1 */
    long long temp=0;
  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_TIM2_Init();

  /* USER CODE BEGIN 2 */

    HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);   //¿ªÆôTIM5µÄ²¶»ñͨµÀ1£¬²¢ÇÒ¿ªÆô²¶»ñÖжÏ
  __HAL_TIM_ENABLE_IT(&htim2,TIM_IT_UPDATE);   //ʹÄܸüÐÂÖжÏ
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
            HAL_Delay(1);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
        if(TIM2CH1_CAPTURE_STA&0X80)        //³É¹¦²¶»ñµ½ÁËÒ»´ÎµÍµçƽ
        {
            HAL_Delay(1000);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
            HAL_Delay(1);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);

            __HAL_TIM_SET_COUNTER(&htim2,0);
            TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1);   //Ò»¶¨ÒªÏÈÇå³ýÔ­À´µÄÉèÖã¡£¡
            TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//¶¨Ê±Æ÷2ͨµÀ1ÉèÖÃΪÉÏÉýÑز¶»ñ
            __HAL_TIM_ENABLE(&htim2);//ʹÄܶ¨Ê±Æ÷5
            TIM2CH1_CAPTURE_STA=0; 
        }
  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

完整工程下載:http://download.csdn.net/detail/sensiki/9825937

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章