STM32F429使用HC-SR04輸出距離到串口助手

本次實驗是用HAL庫編寫定時器捕獲程序,來獲得距離值,並通過串口助手顯示距離值。移植的是原子的實驗九輸入捕獲實驗的程序

實驗前準備:

  • 阿波羅STM3F429開發板
  • HC-SR04超聲波模塊
  • 串口調試助手
  • 四根杜邦線

關於HC-SR04超聲波測距模塊,需要注意看它的時序圖,如下:
在這裏插入圖片描述
可知使用該模塊我們需要給至少10us的觸發信號,在本實驗中我給了20us的觸發信號:

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);//打開PB6
delay_us(20);//向PB6輸入一個長爲20us的高電平方波
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);//關閉PB6

而模塊內部發出信號是傳感器自動迴應的,不需要代碼去實現。

輸出迴響信號是通過對輸入捕獲實現,在向上計數模式下,通過計算高電平的時間,即捕獲一次上升沿,清零計數器的值後再捕獲一次下降沿的值,根據定時器的計數頻率,就可以算出兩次捕獲的時間,從而得到高電平脈寬,也就得到了距離。(詳細請看正點原子STM32F429開發指南-HAL庫版本_V1.1——實驗九輸入捕獲實驗)

接線如下:

HC-SR04 STM32
VCC -> VCC
Trig -> PB6
Echo -> PA0
GND -> GND

下面貼出我覺得需要注意的地方的代碼:

//定時器5初始化
void ultrasound_init()
{
    TIM5_Handler.Instance=TIM5;//定時器5
    TIM5_Handler.Init.Prescaler=90-1;//預分屏係數
    TIM5_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上計數
    TIM5_Handler.Init.Period=0xFFFFFFFF;//自動裝載值
    TIM5_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; //時鐘分頻因子   
    HAL_TIM_IC_Init(&TIM5_Handler);
    
    TIM5_CH1Config.ICPolarity=TIM_ICPOLARITY_RISING;//上升沿捕獲
    TIM5_CH1Config.ICSelection=TIM_ICSELECTION_DIRECTTI;//映射到TI1上
    TIM5_CH1Config.ICPrescaler=TIM_ICPSC_DIV1;//配置輸入分頻,不分頻
    TIM5_CH1Config.ICFilter=0;//配置輸入濾波器,不濾波
    HAL_TIM_IC_ConfigChannel(&TIM5_Handler,&TIM5_CH1Config,TIM_CHANNEL_1);
    
    HAL_TIM_IC_Start_IT(&TIM5_Handler,TIM_CHANNEL_1);   //開啓TIM5的捕獲通道1,並且開啓捕獲中斷
    __HAL_TIM_ENABLE_IT(&TIM5_Handler,TIM_IT_UPDATE);   //使能更新中斷
}

//定時器5回調函數
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM5)
    {        
        __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA時鐘
        __HAL_RCC_TIM5_CLK_ENABLE();//使能TIM5時鐘
        
        GPIO_Initure.Pin=GPIO_PIN_0;//Pin0
        GPIO_Initure.Mode=GPIO_MODE_AF_PP;//複用推輓輸出
        GPIO_Initure.Speed=GPIO_SPEED_HIGH;//高速
        GPIO_Initure.Pull=GPIO_PULLDOWN;//下拉
        GPIO_Initure.Alternate=GPIO_AF2_TIM5;//PA0 複用爲 TIM5 通道 1
        HAL_GPIO_Init(GPIOA,&GPIO_Initure);
        
        HAL_NVIC_SetPriority(TIM5_IRQn,2,0); //設置中斷優先級,搶佔 2,子優先級 0
        HAL_NVIC_EnableIRQ(TIM5_IRQn); //開啓 ITM5 中斷通道
    }
    
    __HAL_RCC_GPIOB_CLK_ENABLE();  //使能PB時鐘
    
    GPIO_InitStructure.Pin= GPIO_PIN_6;
    GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP;//推輓輸出
    GPIO_InitStructure.Pull=GPIO_PULLUP;//上拉
    GPIO_InitStructure.Speed=GPIO_SPEED_HIGH;//高速
    HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
}

一開始調試的時候我得到的距離是0,後來對比了一下別人的代碼,發現我GPIOA的管腳模式選擇錯了,應該要選擇GPIO_MODE_AF_PP(複用推完輸出),第二個是 HAL_TIM_IC_Start_IT(&TIM5_Handler,TIM_CHANNEL_1); 開啓中斷函數弄錯了,不知怎麼就少寫了_IT,導致後面檢查才發現沒開啓中斷。實在是太大意了。

接下來是主函數的測距實現:

int main(void)
{      
    long time=0;  
    float Distance;
        
    HAL_Init();                     //初始化HAL庫   
    Stm32_Clock_Init(360,25,2,8);   //設置時鐘,180Mhz
    delay_init(180);                //初始化延時函數
    uart_init(115200);              //初始化USART
    LED_Init();                     //初始化LED    
    ultrasound_init(); //以1MHZ的頻率計數
        
    while (1)
    {
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);//打開PB6
        delay_us(20);//向PB6輸入一個長爲20us的高電平方波
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);//關閉PB6
        //delay_us(20);
        if(TIM5CH1_CAPTURE_STA&0X80)        //成功捕獲到了一次高電平
        {
            time=TIM5CH1_CAPTURE_STA&0X3F; 
            time*=0XFFFFFFFF;               //溢出時間總和
            time+=TIM5CH1_CAPTURE_VAL;      //得到總的高電平時間
            Distance=time*340/20000;
            printf("the distance is %.2f cm\r\n",Distance);
            delay_ms(1000);
            TIM5CH1_CAPTURE_STA=0;          //開啓下一次捕獲
        }
    }
}


Distance=time*340/20000;聲音在空氣中傳播的大約速度爲340m/s,而且是一個回傳,所以得到的距離還需要除以2纔是最後的實際距離。(計算的Distance單位是cm)
詳細解釋看mc.six的帖子
在這裏插入圖片描述
實驗測出距離如下:
在這裏插入圖片描述

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