STM32F103RCT6使用HY-SRF05 五針超聲波測距模塊進行測距實現

功能簡述:STM32F103RCT6使用HY-SRF05五針超聲波測距模塊進行測距,再將測距好的值通過串口2DMA方式發送到PC的串口調試助手上。

HY-SRF05五針超聲波測距模塊描述:

軟件實現思路:

1、精準的延時工具

2、超聲波模塊TRIG引腳連接到STM32的某個引腳,推輓輸出,通常情況是低電平。觸發超聲波信號時,將STM32的這個引腳拉高,製造一個上升沿,並延時>10us,再將該引腳拉低,如此超聲波就可以發送測距脈衝信號了。

3、超聲波模塊的ECHO引腳連接到STM32的某個引腳上,下拉輸入,通常情況下是低電平,當檢測到上升沿時開始計時,直到下降沿停止計時。計時單位爲us(微秒),考慮到超聲波測距有效性爲2cm-450cm,因此,需要有一個測距超時的機制。根據聲波的速度爲340m/s,檢測1cm的距離需要的時間爲0.01/340=0.0000294s=0.0294ms=29.4us,即每29.4us的時間換算成距離約等於1cm。超聲波最大測量距離爲450cm,換算成等效時間爲450*29.4=13230。

4、測量距離=高電平時間/29.4,結果即爲計算的釐米數。

硬件電路接線:

具體實現代碼:

1、精準延時

#ifndef __Z_UTIL_TIME_H
#define __Z_UTIL_TIME_H
#include "z_util_time.h"
#endif

void delay_us(uint32_t time_us)
{
	SysTick->LOAD = AHB_INPUT * time_us;
	SysTick->VAL = 0x00;
	SysTick->CTRL = 0x00000005;
	for(;!(SysTick->CTRL & 0x00010000););
	SysTick->CTRL = 0x00000004;
}

void delay_ms(uint32_t time_ms)
{
	for(;time_ms-- > 0;)
	{
		delay_us(1000);
	}
}

2、超聲波測距功能代碼

#ifndef __Z_OUTER_HARDWARE_SUPERSONIC_H
#define __Z_OUTER_HARDWARE_SUPERSONIC_H
#include "z_outer_hardware_supersonic.h"
#endif

void init_hardware_supersonic()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_ResetBits(GPIOB, GPIO_Pin_7);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void func_trig_supersonic()
{
	GPIO_SetBits(GPIOB, GPIO_Pin_7);
	delay_us(12);
	GPIO_ResetBits(GPIOB, GPIO_Pin_7);
}

u8 func_get_supersonic_echo_signal(u16 *distance_cm)
{
	u16 counter_high;
	u16 timeout;
	
	func_trig_supersonic();
	for(;;)
	{
		delay_us(1);
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_8) == Bit_SET)
		{
			counter_high ++;
			if(counter_high > 13235)
			{
				return 2;
			}
		}
		else
		{
			if(counter_high > 1)
			{
				*distance_cm = ((counter_high)*10)/294;
				return 0;
			}
			timeout++;
		}
		if(timeout > 13235)
		{
			return 2;
		}
	}
}

3、USART2串口DMA通訊代碼

#ifndef __Z_HARDWARE_USART2_DMA_H
#define __Z_HARDWARE_USART2_DMA_H
#include "z_hardware_usart2_dma.h"
#endif

u8 dma_recv_buf[LEN_DMA_RECV_BUF];
u8 dma_send_buf[LEN_DMA_RECV_BUF];
u8 usart2_cache[LEN_DMA_RECV_BUF];

void init_hardware_usart2_dma(u32 bound)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	USART_InitStructure.USART_BaudRate = bound;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART2, &USART_InitStructure);
	
	DMA_DeInit(DMA1_Channel6);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR;
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)dma_recv_buf;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	DMA_InitStructure.DMA_BufferSize = LEN_DMA_RECV_BUF;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel6, &DMA_InitStructure);
	DMA_Cmd(DMA1_Channel6, ENABLE);
	
	DMA_DeInit(DMA1_Channel7);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR;
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)dma_send_buf;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
	DMA_InitStructure.DMA_BufferSize = 0;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel7, &DMA_InitStructure);
	DMA_Cmd(DMA1_Channel7, DISABLE);
	DMA_ClearFlag(DMA1_FLAG_GL7);
		
	USART_Cmd(USART2, ENABLE);
	USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
	USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
}

void func_usart2_dma_send_bytes(u8 *bytes, u8 bytes_len)
{
	DMA_Cmd(DMA1_Channel7, DISABLE);
	memcpy(dma_send_buf, bytes, bytes_len);
	DMA_SetCurrDataCounter(DMA1_Channel7, bytes_len);
	DMA_Cmd(DMA1_Channel7, ENABLE);
	while(DMA_GetCurrDataCounter(DMA1_Channel7));
	while(USART_GetFlagStatus(USART2, USART_FLAG_TC) != SET);
}

u8 func_usart2_dma_recv_bytes(u8 *buf_recv, u8 *len_recv)
{
	u8 len_dma_recv;
	if(USART_GetFlagStatus(USART2, USART_FLAG_IDLE) != RESET)
	{
		USART_ReceiveData(USART2);
		DMA_Cmd(DMA1_Channel6, DISABLE);
		len_dma_recv = LEN_DMA_RECV_BUF - DMA_GetCurrDataCounter(DMA1_Channel6);
		memcpy(buf_recv, dma_recv_buf, len_dma_recv);
		memset(dma_recv_buf, 0, len_dma_recv);
		DMA_SetCurrDataCounter(DMA1_Channel6, LEN_DMA_RECV_BUF);
		USART_ClearFlag(USART2, USART_FLAG_IDLE);
		DMA_Cmd(DMA1_Channel6, ENABLE);
		*len_recv = len_dma_recv;
		return 0;
	}
	return 1;
}

4、主功能函數實現:

#include "stm32f10x.h"

#ifndef __Z_HARDWARE_USART2_DMA_H
#define __Z_HARDWARE_USART2_DMA_H
#include "z_hardware_usart2_dma.h"
#endif

#ifndef __Z_OUTER_HARDWARE_SUPERSONIC_H
#define __Z_OUTER_HARDWARE_SUPERSONIC_H
#include "z_outer_hardware_supersonic.h"
#endif

void init_led0(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
}

int main()
{
	u8 buf_tmp[LEN_DMA_RECV_BUF];
	
	u16 distance_cm;
	
	init_hardware_usart2_dma(9600);
	init_led0();
	init_hardware_supersonic();
	
	while(1)
	{
		if(func_get_supersonic_echo_signal(&distance_cm) == 0)
		{
			buf_tmp[1] = (u8)distance_cm;
			buf_tmp[0] = (u8)(distance_cm >> 8);
			func_usart2_dma_send_bytes(buf_tmp, 2);
			
			distance_cm = 0;
		}
		GPIO_SetBits(GPIOA, GPIO_Pin_8);
		delay_ms(1000);
		GPIO_ResetBits(GPIOA, GPIO_Pin_8);
		delay_ms(200);
		
	}
}


最終的效果如下:

以上,僅供參考。

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