STM32超声波模块测距

特别注意!

单独t-link只能提供3.3v电压!模块接5v电压只能收到3.3V。供电的时候请接上micro口!

模块介绍
HC-SR04超声波模块可提供2cm~400cm的距离感测功能,测量精度可以达到3mm。
通过声音340m/s * t / 2可以算出距离.在这里插入图片描述

接线图
A9、A10串口可以选择ttl转usb淘宝十几块一个。B8、B9、5V、GND接在HC-SR04超声波模块
在这里插入图片描述

结合时序图
我们按照时序图从上到下从左到右进行查看,主要分成3块,按照我们的代码,第一块PB8默认低电平随后PB8发起高电平,接着模块内部会工作发送脉冲,同时检测PB9返回的高电平时间。

在这里插入图片描述
主要代码
这里有用到SYSTICK作为全局延时功能,USART1串口通信模块.

#include "stm32f10x.h"
#include "GPIOLIKE51.h"
#include "stdio.h"

static u8  fac_us=0;                                    //us延时倍乘数                           
static u16 fac_ms=0;                                    //ms延时倍乘数

int fputc( int ch, FILE *f ){
		USART_SendData(USART1,(u8) ch );
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
		return ch;
}

//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(){
        SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);       	  //选择外部时钟  HCLK/8
        fac_us=SystemCoreClock/8000000;                               	  //为系统时钟的1/8  
        fac_ms=(u16)fac_us*1000;                                      	  //非OS下,代表每个ms需要的systick时钟数   
} 

//SysTick 微秒计时器
void delay_us(uint32_t nus){
	u32 temp;                     
	SysTick->LOAD=nus*fac_us;                             //时间加载                           
	SysTick->VAL=0x00;                                    //清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;        	  //开始倒数         
	do{
		temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));                 //等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;        	  //关闭计数器
	SysTick->VAL =0X00;                                   //清空计数器  
}

//SysTick 毫秒计时器
void delay_ms(uint32_t nms){
	u32 temp;                  
	SysTick->LOAD=(u32)nms*fac_ms;                        //时间加载(SysTick->LOAD为24bit)
	SysTick->VAL =0x00;                                   //清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;      		  //开始倒数  
	do{
		temp=SysTick->CTRL; 
	}while((temp&0x01)&&!(temp&(1<<16)));                 //等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       		  //关闭计数器
	SysTick->VAL =0X00;    
}

void USART1_init(){
	
	GPIO_InitTypeDef GPIO_InitStructure;
	//配置串口结构体
	USART_InitTypeDef USART_InitStructure;
	//NVIC结构体
	NVIC_InitTypeDef NVIC_InitStructure;
	// 打开功能复用IO时钟,用于串口通信
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);	
	//使能GPIO硬件时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//使能串口1硬件时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	
	/* 配置PA9和PA10为复用功能模式 */

	//USART1_TX   GPIOA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 				//PA.9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;			//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//初始化GPIOA.9
	   
	//USART1_RX	  GPIOA.10初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;				//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//初始化GPIOA.10  
	
	USART_InitStructure.USART_BaudRate = 9600;
	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(USART1, &USART_InitStructure); //初始化串口1
	
	/* Configure the NVIC Preemption Priority Bits */  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	
	/* Enable the USARTy Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	
	NVIC_Init(&NVIC_InitStructure);
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);		    //配置为接收中断
	USART_Cmd(USART1, ENABLE);  						  	//使能串口1

}


/**
*	配置Gpio PB8为发送 PB9为返回
*/
void GPIOB_init(void){
	GPIO_InitTypeDef GPIO_InitStruct;
	/* GPIOB时钟初始化 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;  			//发送电平引脚
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; 	//GPIO_Mode_Out_PP 推挽输出
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;  			//返回电平引脚
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
}

int32_t sr04_get_destace(){
	int32_t t = 0; //时间 us微秒
	int32_t d = 0; //距离 mm毫米
	PBout(8)=0;

	//向PB8发送高电平
	PBout(8) = 1; 
	//持续运行至少大于10_us
	delay_us(20);
	//向PB8发送低电平
	PBout(8) = 0; 
	//循环等待PB9返回的高电平
	while(PBin(9) == 0){
		t++; //累计1微秒
		delay_us(1);
		if(t >= 1000000){
			//超时返回-1
			return -1;
		}
	}
	//测量高电平时长
	while(PBin(9)){
		t++; //累计9微秒 
		delay_us(9); //声音速度340m/s 9us == 3mm
		if(t >= 1000000){
			//未检测高电平超时返回-2
			return -2;
		}
	}
	//计算距离 距离3mm乘以时间us除以2得出距离
	d=3*t/2;
	return d;
}

int main(void){
	//距离mm
    int32_t d = 0;
	delay_init();
	//串口初始化 TXD->PA9,RXD->PA10 接在ttl转usb记得反接
	USART1_init();
	//HC-SR04传感器相关初始化,使用的基础IO->输出PB8,接收PB9
	GPIOB_init();
	printf("distance:%dmm\r\n", d);
	while(1)
    {
		d = sr04_get_destace();
		if(d > 0){
			//距离大于20mm且小于等于4m才会打印输出
			if(d>=20 && d<=4000){
				printf("distance:%dmm\r\n", d);
			}

		}
		//延迟一秒
		delay_ms(1000);
    }

}
//  "GPIOLIKE51.h"
#ifndef __GPIOLIKE51_H
#define __GPIOLIKE51_H	 

///#include <stm32f10x_lib.h>

//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

#endif

在这里插入图片描述

串口打印配置: STM32重写fputc.

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值