STM32超声波模块测距串口输出/通用定时器中断并输出PWM控制舵机/系统定时器延时

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

效果展示

在这里插入图片描述

超声波传感器原理

在这里插入图片描述
在这里插入图片描述

超声波测距编程步骤

要配置三个结构体
在这里插入图片描述

接线

  • Trig:PB11
  • Echo:PB10
  • PB5:连接舵机

代码编写

HC_SR04.h

#ifndef _HC_SR04_H //#ifndef #define #endif  条件编译   为了防止重复编译 
#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);
 
//ECHO读取
#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

超声波HC_SR04.c

#include "stm32f10x.h"                  // Device header
#include "HC_SR04.h"
#include "SysTick.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中断控制器结构体(TIM4定时器)
	
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//中断组1
	
														  	 //rcc.h
	    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//4.开启GPIOB时钟(在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 );
	
		//定时器4的配置
		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中断控制器(TIM4定时器)
		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 );  //关闭
}


//定时器TIM4中断服务函数  函数名不能改动
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  得到时间ms(一次中断就是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);
		Close_tim4();
		t = GetEcho_time();//计算ECHO高电平持续时间就能换算出距离
		length =((float) t / 58.0);
		sum = sum +length;		
	}
	length = sum / 5.0;
	return length; 
}

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函数  串口打印输出距离 串口小助手就能看到打印的距离了
			ms_delay(500);
		
			//再加一个距离判断  将之前写的舵机部分加进来即可控制舵机
			if(Length < 5)
			{
				for(pwmval = 195; pwmval >= 155;pwmval -=15 )//逐步转到位置
				{
						TIM_SetCompare2( TIM3,  pwmval);  //5. 配置PWM比较值 配合重装载值生成占空比
						delay(1000)}
			}
			else if (Length > 5)
			{
					TIM_SetCompare2( TIM3,  pwmval-20);  //让舵机回去
			}
		}
}
  • 16
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行稳方能走远

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值