1. 程式人生 > >基於STM32的超聲波HC-SR04歷程

基於STM32的超聲波HC-SR04歷程

我有一些巨集定義沒有貼出來,引腳自己安排就可以,如果有問題可以評論留言

HC-SR04基本工作原理:

(1)採用IO口TRIG觸發測距,給最少10us的高電平信呈。
(2)模組自動傳送8個40khz的方波,自動檢測是否有訊號返回;
(3)有訊號返回, 通過IO口ECHO輸出一個高電平, 高電平持續的時間就是超聲波從發射到返回的時間。 測試距離=(高電平時間*聲速(340M/S))/2。
程式編寫思路是:1、配置好使用到的GPIO以及定時器;2、給模組TRIG埠傳送大於10us的高電平訊號,當收、收到ECHO迴響訊號是,開啟定時器開始定時;3、當迴響訊號消失,關閉定時器;4、通過定時器定時時間來確定距離。
/*Systick延時函式

  Systick 延時初始化*/

void SysTick_Delay_Us( unsigned int us)   //1微妙延時
{
	uint32_t i;
	SysTick_Config(SystemCoreClock/1000000);
	for(i=0;i<us;i++)
	{
	       //當計數器的值減小到0的時候,CRTL暫存器的為16置1,當置1的時候該位清0
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	// 關閉定時器
	SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}


//1毫秒延時
void SysTick_Delay_Ms( unsigned int  ms)
{
	uint32_t i;	
	SysTick_Config(SystemCoreClock/1000);
	for(i=0;i<ms;i++)
	{
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}

/*TIM2定時器初始化

    一些巨集定義再次不多過說明 */

void Timer_Config()
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructer;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);   
	TIM_DeInit(TIM2);
	TIM_TimeBaseInitStructer.TIM_Period=65535;//定時週期  這裡沒開啟定時中斷,這個週期最大到2米距離
	TIM_TimeBaseInitStructer.TIM_Prescaler=72-1; //  分頻係數
	TIM_TimeBaseInitStructer.TIM_ClockDivision=TIM_CKD_DIV1;//不分頻
	TIM_TimeBaseInitStructer.TIM_CounterMode=TIM_CounterMode_Up;
		/*定時器初始化完成*/
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructer);.
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_Cmd(TIM2,DISABLE);//¹關閉定時器使能


}


/*超聲波距離函式*/

#include "Chao.h"

#include "Systick.h"
extern char dis[];    //儲存轉換後的值
int Val=0;
extern int Length;

/*初始化超聲波IO*/
void HS_GPIO_Config()
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);  //´ò¿ªGPIOʱÖÓ
	//Trig
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  
	GPIO_InitStruct.GPIO_Pin = Trig;   
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(HC_SR04_Port,&GPIO_InitStruct );

	//Echo
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin = Echo; 
	GPIO_Init(HC_SR04_Port,&GPIO_InitStruct );
	
}

char  *Convert()  //將整型資料轉換後儲存到字元數組裡
{
	int tmp=0,i=0;
	Length=0;   //資料長度
	Val=UltraSonic();
	//Val=26;
	tmp=Val;
	while(tmp)
	{
	 tmp=tmp/10;
	 Length++;
	}

	for(i=Length-1;i>=0;i--)
	{
		dis[i]=Val%10+'0';
		Val=Val/10;
	}
	
	return dis;
}

int UltraSonic()   //超聲波距離
{
		unsigned int length=0;
		GPIO_ResetBits(HC_SR04_Port, Trig);  //先拉低
		GPIO_SetBits(HC_SR04_Port, Trig);  //拉高電平訊號
		SysTick_Delay_Us(20);   //拉高電平超過10US
		GPIO_ResetBits(HC_SR04_Port, Trig); //拉高夠了就拉低
	      /*等待迴響訊號*/
		while(GPIO_ReadInputDataBit(HC_SR04_Port,Echo)==0);  //高電平就是接收到了
		TIM_Cmd(TIM2,ENABLE);//使能TIM2定時器
		while(GPIO_ReadInputDataBit(HC_SR04_Port,Echo)==1);//迴響訊號消失了
		TIM_Cmd(TIM2,DISABLE);//關閉定時器
		length=TIM_GetCounter(TIM2)/58;
		if(length<=0) length=0;
	       TIM_SetCounter(TIM2,0);  //取出TIM2定時器counter暫存器裡的值
		SysTick_Delay_Ms(200);  
		return length;
	
}

/*    主函式  */

#include "stm32f10x.h"
#include "Chao.h"
#include "Systick.h"
#include "Timer.h"

int distence = 0;   
char dis[4];    
int Length=0;
int main()
{
	char *Tmp;
	HS_GPIO_Config();   
	Timer_Config();      
	while(1)
	{
		Tmp=Convert();
		Speed_Arr(Tmp);
		Speed_Byte(' ');
		Speed_Byte('C');
		Speed_Byte('M');
		Speed_Byte('\n');
		SysTick_Delay_Ms(300);
	}
				
	
}