天天看點

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

文章目錄

  • STM32CubeMX-輸入捕獲讀取超音波子產品資料
    • 一、初始準備
      • 1.硬體平台
      • 2.軟體平台
      • 3.原理圖接線
    • 二、操作步驟
      • 1.CubeMX生成初始化代碼
        • 1.1 建立工程(通用步驟)
        • 1.2 開啟序列槽
        • 1.3 開啟輸入捕獲
        • 1.4 配置GPIO
        • 1.5 生成代碼(通用步驟)
      • 2.編寫代碼
      • 3.程式下載下傳(通用步驟)
    • 三、實驗現象

STM32CubeMX-輸入捕獲讀取超音波子產品資料

本章内容使用STM32CubeMX軟體配置STM32F407ZGT6定時器輸入捕獲功能,讀取超音波傳回的距離電平資訊,轉換成實際的距離值

教程包含通用步驟以及專用步驟,其中,通用步驟為STM32CubeMX配置其他外設工程的通用操作,STM32CubeMX系列教程基本通用,專用操作則是針對目前工程進行的配置

一、初始準備

1.硬體平台

主要使用正點原子STM32F4探索者:

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

超音波子產品HC-SR04:

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

HC-SR04是一款經典的超音波子產品,其有四個引腳,分别對應着VCC(電源引腳)、GND(電源引腳),TRIG(觸發控制信号輸入端)、ECHO(回響信号傳回端);使用時我們使用單片機對TRIG引腳輸入一個電平,接着子產品内部産生連續脈沖發射出去,當發射的超音波撞到障礙物時會被反彈回來,反彈的波再被超音波子產品接受到,然後ECHO産生一段高電平,高電平維持的時間就是超音波子產品到障礙物一個來回的時間,是以我們用輸入捕獲來讀取電平的持續時間就可以解算出超音波到障礙物的距離,子產品電平示意圖如下:

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

想要進一步了解超音波子產品的同學可以參考這一篇文章:HC-SR04超音波測距子產品的原理介紹與代碼實作

2.軟體平台

STM32CubeMX軟體平台 V6.2.1

Keil5軟體平台 V5.32

STM32CubeProgrammer下載下傳平台

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

3.原理圖接線

因為使用到定時器,是以将超音波子產品和開發闆的引腳按照如下接線,PA7普通引腳輸入觸發電平,PA6使用定時器3的通道1做輸入捕獲

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

二、操作步驟

1.CubeMX生成初始化代碼

1.1 建立工程(通用步驟)

  • 晶片選擇

打開cube軟體,選擇從晶片來建立工程,一般開發都是使用這個來開發,有的時候也可能使用另外兩個,但不多,第二個基于ST提供的開發闆建立工程,針對性高,第三個則選擇ST提供的例程來建立工程

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

F4探索者的主要為STM32F407ZGT6,是以在搜尋框找到STM32F407ZG後點選具體晶片,再開始工程

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料
  • 配置時鐘源

我們點開SystemCore(系統核心設定),再點選RCC配置HSE和LSE時鐘源,這裡我都選擇使用外部時鐘,配置後,我們可以看到右邊晶片引腳配置設定圖的兩個時鐘源引腳點亮,表示時鐘配置為外部源

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料
  • 配置時鐘樹

我們進入ClockConfiguration配置時鐘樹,使時鐘的輸入路徑和大小符合我們預期,探索者的晶振和時鐘倍頻如下

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

一般配置正确時顔色藍白為主,配置錯誤時則會出現紫色,提示我們要修改值

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

具體時鐘樹的了解可以看我很久之前的文章,有做一些分析

CSDN文章連結-時鐘樹分析

1.2 開啟序列槽

開啟序列槽通信,友善我們通過上位機發送資料進行調試,不熟悉配置的話可以參考我以前的文章:

STM32CubeMX-序列槽中斷實驗

配置後引腳圖如下:

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

1.3 開啟輸入捕獲

通過輸入捕獲計算超音波子產品測量距離的原理很簡單,簡單來講就是開啟輸入捕獲和定時器計數,設定上升沿捕獲,當上升沿到來時會進入定時器中斷,此時我們清空定時器的計數值為0,然後設定設定下降沿捕獲,當下降沿到來時,就會再次進入中斷,此時再次讀取計數值,即可得出高電平維持的時間長度,帶入計算得出超音波距離值,配置步驟如下:

點選TIM3,選擇内部時鐘(Internal Clock),配置通道1為直接輸入捕獲模式(Input Capture direct mode)

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

配置輸入捕獲的詳細參數,首先先配置定時器為72MHz配置設定,即1us計數一次,每次計數值加1,計數上限設為最大65535,配置如下:

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

然後配置上升沿觸發(Rising Edge),不分頻(No division),濾波器的值為0不濾波

濾波器就是輸入多個邊沿才算一次觸發,比如設定為4,則輸入4次上升沿才會觸發中斷,一定程度上可以濾除抖動,這裡我們設定為0就行
STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

配置完成後别忘了在中斷管理(NVIC)裡面使能定時器3的中斷,配置中斷優先級

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

1.4 配置GPIO

配置PA7為推挽輸出,用于産生超音波的觸發信号,基本操作,不會配置可參考我之前的文章:STM32CubeMX-流水燈實戰,配置後引腳圖如下:

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

1.5 生成代碼(通用步驟)

點選進入Project Manager 配置生成工程的名字,存儲路徑**(不要有中文)**以及編譯器,這裡我們選MDK-ARM(Keil被收購後改名)

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

配置生成選項,主要為下面三大塊,第一個我們選擇隻拷貝必要的庫,第二個選擇為每個外設生成.c和.h檔案,儲存之前的使用者代碼,以及删除之前的生成代碼,第三個不選擇

PS:使用者代碼段是一下注釋之間的代碼,隻有原始的使用者代碼段注釋才有效,使用者自己添加的無效

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
           
STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

最後點選生成代碼

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

2.編寫代碼

在檔案目錄建立Hardware檔案夾用于存放子產品外設程式,添加hcsr04.c和.h檔案

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

在MDK工程内添加檔案夾和檔案

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

别忘了添加Hardware包含路徑

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

到此工程配置好了,下一步我們先将printf重映射到序列槽1,在uart.c使用者代碼段插入如下代碼

/* USER CODE BEGIN 0 */
#define USE_PRINT
#ifdef USE_PRINT
//編譯器不使用MicroLib庫
#pragma import(__use_no_semihosting)
//定義 _sys_exit() 避免使用半主機
void _sys_exit(int x)
{
    x = x;
}
struct __FILE
{
    int handle;
};
FILE __stdout;
//重映射fputc
int fputc(int ch, FILE *stream)
{
    //判斷序列槽是否發送完成 
	  //不同晶片的序列槽标志位不一定相同,具體查手冊
    while((USART1->SR & 0X40) == 0);
    //如果序列槽已經發送完成,發送下一個字元
    USART1->DR = (uint8_t) ch;
    return ch;
}
#endif
/* USER CODE END 0 */
           
STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

然後在usart.h加入printf的庫

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

我們在hcsr04.h檔案插入如下代碼:代碼注釋都寫在了裡面

#ifndef _HCSR04_H
#define _HCSR04_H

#include "tim.h"
//配置使用的定時器和捕獲通道
#define HCSR04_TIM 		 		  TIM3
#define HCSR04_TIM_HAL 			htim3
#define HCSR04_TIM_CHANNEL  TIM_CHANNEL_1
//聲明一個狀态枚舉常量
typedef enum Run_State
{
	TRIG_WAIT = 0,
	RISING,
	FALLING,
	OVER
}Run_State;
//聲明結構體友善傳遞使用資料
typedef struct 
{
	Run_State STATE;
	int buf[2];
	float len;
}HCSR04;
//聲明一下回調函數
extern void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);
#endif
           

然後我們在hcsr04.c檔案插入如下代碼

#include "hcsr04.h"
//聲明一個子產品的資料結構體
HCSR04 hcsr04;
//重新編寫輸入捕獲回調函數
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	
	if(HCSR04_TIM == htim->Instance)
	{
		//如果上升沿檢測
		if(hcsr04.STATE == RISING)
		{
			//設定定時器CNT為0
			__HAL_TIM_SET_COUNTER(&HCSR04_TIM_HAL,0);
		  //讀取上升沿時的CNT值到buf
			hcsr04.buf[0] = __HAL_TIM_GetCounter(&HCSR04_TIM_HAL);
			//設定下一個捕獲為下降沿
			__HAL_TIM_SET_CAPTUREPOLARITY(&HCSR04_TIM_HAL,HCSR04_TIM_CHANNEL,TIM_ICPOLARITY_FALLING); 
			//改變運作模式
			hcsr04.STATE=FALLING;
		}else if(hcsr04.STATE == FALLING)//如果下降沿檢測
		{
			//擷取目前的CNT到buf2,這樣高電平維持的時間長度就記錄了
			hcsr04.buf[1] = __HAL_TIM_GetCounter(&HCSR04_TIM_HAL);
			//将運作标志設定為完成
			hcsr04.STATE=OVER;  
		}
	}
	
}
           

主函數循環體插入如下代碼

/* USER CODE BEGIN WHILE */
	printf("System Init Ok! jeck666!\r\n"); //序列槽發送資料
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,0);
	while (1)
	{
			/* USER CODE END WHILE */

			/* USER CODE BEGIN 3 */
		if(hcsr04.STATE == TRIG_WAIT)
		{
			//給HCSR04一個1ms觸發電平
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,1);
			HAL_Delay(1);
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,0);
			//啟動上升沿捕獲
			__HAL_TIM_SET_CAPTUREPOLARITY(&HCSR04_TIM_HAL, HCSR04_TIM_CHANNEL, TIM_INPUTCHANNELPOLARITY_RISING);
			//啟動輸入捕獲
			HAL_TIM_IC_Start_IT(&HCSR04_TIM_HAL, HCSR04_TIM_CHANNEL);	
			//設定上升沿捕獲
			hcsr04.STATE = RISING;
		}
		
		if(hcsr04.STATE == OVER)//判斷電平捕獲結束
		{
			//計算高電平時間內插補點代表時間維持的長度,因為定時器設定1us自加一次,是以時長機關為us
			//乘以0.017的是因為聲波速度為340m/s,而1s=1000000us,且技術一次距離是一個來回
			//要除以2,此處機關為cm
			hcsr04.len = (float)(hcsr04.buf[1]- hcsr04.buf[0])*0.017; 
			//重新整理狀态,使可以進行下一次觸發電平
			hcsr04.STATE = TRIG_WAIT;
			//發送資料到上位機
			printf("HCSR04_Len: %.3f cm \r\n",hcsr04.len);
			//延時1s
			HAL_Delay(1000);
		}
	}
/* USER CODE END 3 */
           

當然main.c檔案頭部别忘了添加頭檔案和變量聲明

/* USER CODE BEGIN Includes */
#include "hcsr04.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
extern HCSR04 hcsr04;
/* USER CODE END PTD */
           

到此代碼編寫完畢

3.程式下載下傳(通用步驟)

程式下載下傳我一般用兩種方式:

第一種是使用MDK自帶的下載下傳環境下載下傳程式,我們給單片機連接配接ST-Link後配置下載下傳,點選魔術棒,選擇debug

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

選擇ST-link後,點選setting

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

添加對應F4的Flash

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

keil界面點選下載下傳

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

第二種是使用Stm32Programmer下載下傳軟體,該下載下傳軟體下載下傳方式多,下載下傳快,下面我使用st-link下載下傳

打開軟體,點選connect左邊選擇stlink後再點選connect連接配接下載下傳器

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

點選open file,找到工程路徑下MDK檔案夾下工程生成的hex檔案

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

之後點選downlod下載下傳,下載下傳結果如下

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

三、實驗現象

可以看到序列槽接受到的距離在變化(因為我在移動超音波子產品)

STM32CubeMX-輸入捕獲讀取超音波子產品資料STM32CubeMX-輸入捕獲讀取超音波子產品資料

繼續閱讀