功能简述: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);
}
}
最终的效果如下:
以上,仅供参考。