STM32超声波模块测距控制舵机

参考:stm32 超声波模块 原理 实现测距 +舵机使用
作者:点灯小哥
发布时间: 2021-03-10 19:37:16
网址:https://blog.csdn.net/weixin_46016743/article/details/114643703

目录

  • 效果展示
  • 超声波传感器原理
  • 超声波测距编程步骤
  • 代码编写

效果展示

超声波传感器原理

STM32超声波模块测距控制舵机_第1张图片
STM32超声波模块测距控制舵机_第2张图片

超声波测距编程步骤

要配置三个结构体
STM32超声波模块测距控制舵机_第3张图片

代码编写

HC_SR04.c

#include "stm32f10x.h"                  // Device header
#include "SysTick.h"
#include "HC_SR04.h"
 
extern uint16_t mscount = 0;   //extern 让main函数也能使用这里这个

 
void HC_SR04(void)
{
     
		GPIO_InitTypeDef GPIO_HC_SR04init;       //1.配置GPIO引脚结构体 Trig PB11 Echo PB10
		TIM_TimeBaseInitTypeDef TIM_HC_SR04init; //2.配置定时器结构体
	    NVIC_InitTypeDef NVIC_HC_SR04init;       //3.配置定时器中断结构体
	
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	
														  	//rcc.h
	    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//4.开启时钟(定时器,GPIO  在APB2总线上)
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
 
		//Trig PB11  发送
		GPIO_HC_SR04init.GPIO_Mode  = GPIO_Mode_Out_PP; //推挽输出
		GPIO_HC_SR04init.GPIO_Pin   =	GPIO_Pin_11;	
		GPIO_HC_SR04init.GPIO_Speed = GPIO_Speed_50MHz;
	    GPIO_Init( GPIOB, &GPIO_HC_SR04init );
	
		//Echo PB10  接收
		GPIO_HC_SR04init.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入  只要求高电平 高低电平直接检测
		GPIO_HC_SR04init.GPIO_Pin  = GPIO_Pin_10;
		GPIO_Init( GPIOB, &GPIO_HC_SR04init );
	
		TIM_HC_SR04init.TIM_ClockDivision  = TIM_CKD_DIV1;//分频系数1 不分频 还是72MHz
		TIM_HC_SR04init.TIM_CounterMode    = TIM_CounterMode_Up;//向上计数
		TIM_HC_SR04init.TIM_Period         = 100 - 1 ; //1us
		TIM_HC_SR04init.TIM_Prescaler      = 72 - 1 ;  //72M   这两个相乘7200/72 000 000 = 1us
		TIM_TimeBaseInit( TIM4, &TIM_HC_SR04init);
 	    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);//IT就是中断 定时器中断  TIM_IT_Update是允许溢出/更新?
		TIM_Cmd( TIM4, DISABLE );  //定时器先关闭  等着测量距离时再打开  下面给出打开定时器函数
	
		NVIC_HC_SR04init.NVIC_IRQChannel = TIM4_IRQn;// 通道  中断源是定时器4
		NVIC_HC_SR04init.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级 给的最高的
		NVIC_HC_SR04init.NVIC_IRQChannelSubPriority = 0;//子优先级
		NVIC_HC_SR04init.NVIC_IRQChannelCmd = ENABLE;//
		NVIC_Init(&NVIC_HC_SR04init);
 
	
}
//打开定时器4
void Open_tim4(void)	
{
     
		TIM_SetCounter( TIM4,  0);//开启计数器计数  从0开始
		mscount = 0;             //需要计算高电平5次数值 取平均值  防止一次算的距离不精准
		TIM_Cmd( TIM4, ENABLE );  //定时器使能 打开了
 
}

//关闭定时器4
void Close_tim4(void)
{
     
		TIM_Cmd( TIM4, DISABLE );  //关闭
}


//定时器中断服务函数  函数名不能改动
void TIM4_IRQHandler(void)
{
     
	 if ( TIM_GetITStatus(TIM4,  TIM_IT_Update) != RESET)     //判断是否发生中断
	 {
     
				TIM_ClearITPendingBit(TIM4, TIM_IT_Update);   //清楚中断的标记位
				mscount++; //记录发生的中断次数 为了取5次测量计算提高精度
				           //定时器中断一次就是1us
 
	 
	 }
 
}

//获取定时器计数器的值   得到Echo高电平的时间
int GetEcho_time(void)
{
     
		uint32_t t = 0;
		t = mscount * 1000;   //发生了多少次中断 *1000  得到时间(一次中断就是1us)
		t += TIM_GetCounter(TIM4);//获取定时器计数值     {这两行没看懂 感觉重复了?}
		TIM4->CNT = 0;//代表向上增的寄存器(向上向下计数 前面章节有讲) 要置零 重装载
		ms_delay(50);//系统库延时函数
	
		return t;
 
}

//获取超声波测距距离
float GetLength(void)
{
     
	int i = 0;
	uint16_t t = 0;
	float length = 0;
	float sum = 0;
	
	while(i != 5)//算5次 提高计算精度
	{
     
		TRIG_Send(1);
		us_delay(20);//硬件模块要求发送高电平时间大于10us
		TRIG_Send(0);//此时超声波开始工作了
		
		while(ECHO_Reci == 0);
				Open_tim4();
				i=i+1;
		while(ECHO_Reci == 1);//ECHO从低电平到高开始  计算高电平持续时间就能换算出距离
				t = GetEcho_time();//计算ECHO高电平持续时间
				length =((float) t / 58.0);
				sum = sum +length;
		
	}
		length = sum / 5.0;
		return length;
 
}

HC_SR04.h

#ifndef _HC_SR04_H   //条件编译  为了防止重复编译 
#define _HC_SR04_H
 
#include "stm32f10x.h"                  // Device header

void HC_SR04(void);
void Open_tim4(void);
void Close_tim4(void);
int GetEcho_time(void);
float GetLength(void);
 
#define ECHO_Reci    	GPIO_ReadInputDataBit( GPIOB, GPIO_Pin_10)
 

//为真就给Trig发送高电平 
#define TRIG_Send(a)  if(a) \
											GPIO_SetBits(GPIOB, GPIO_Pin_11); \
											else \
											GPIO_ResetBits(GPIOB, GPIO_Pin_11)
 
#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "usart.h"
#include "led.h"
#include "tim.h"
#include "motor.h"
#include "SysTick.h"
#include "HC_SR04.h"//记得添加路径
 

 
void delay(uint16_t time)
{
     
		uint16_t i = 0;
		while(time--)
		{
     
			i=12000;
			while(i--);
		}
}
 
 
int main(void)
{
     
		int pwmval = 195;

		float Length = 0;
		HC_SR04();
		Usart_Init();
		motor_config();
 
	while(1)
	{
     
				int pwmval = 155;


				Length = GetLength();
				printf("%.3f\r\n",Length);//之前重定向print函数  串口打印输出距离 串口小助手就能看到打印的距离了
				//3位小数
				ms_delay(500);
			
				//再加一个距离判断  将之前写的舵机部分加进来即可控制舵机
				if(Length < 5)
				{
     
					for(pwmval = 195; pwmval >= 195;pwmval -=15 )
					{
     
							TIM_SetCompare2( TIM3,  pwmval);   //5. 配置PWM比较值 占空比
							delay(1000)}
				}
				else if (Length > 5)
				{
     
						TIM_SetCompare2( TIM3,  pwmval-20);  //让舵机回去
				}

	}
}

你可能感兴趣的:(STM32)