STM32使用sr04超声波一收一发测距,可实现空间定位

演示视频

使用的超声波模块

展示效果

 使用的三个模块在不同位置发送超声波,然后接收端得出接收端与三发送端的距离,如果已知三发送端的坐标,根据三个距离值即可计算出接收端的坐标。

发送端用的一个stm32来控制,发送与接收的同步信号使用的红外,接收端接收到红外信号后开启1us的定时器计时,发送端每个超声波模块发送间隔40ms(避免间隔时间太短,声波反射干扰)。

这里需要用逻辑分析仪或者示波器来查看发送和接收的时间差,进行微调,以及消除某些干扰信号。

红外模块

接收端没有使用模块的echo引脚,因为模块本身有抗干扰措施,如果没有使用trig发送,echo是不会返回信号的,如果要直接获取接收到的信号,可连接图中的引脚 

 各信号时序

 

 接收到的超声波信号是40k的矩形波,需要注意其他干扰信号

红外信号从发送到接收的时间基本保持一致,并且每次红外发送完成后就发送超声波,我们就在接收端掐准时间,从接收到红外信号固定一个延时,到发送超声波就开始计时,直到接收到超声波信号即可停止。定时器计数值*计数周期即可算得时间,再乘上声速即可算得距离。

发送端实现代码:

标准库

        TIM_Cmd(TIM3, ENABLE);
		TIM3->CNT=0;//开始计时

		TIM_Cmd(TIM2, ENABLE);
		TIM_SetCompare2(TIM2,13);//红外发送信号,38khz
	
		while(TIM3->CNT<500);
		TIM_SetCompare2(TIM2,0);//停止发送,发送不能太长,也不能太短,
        //太长没必要,太短会发送不成功
	
		GPIO_WriteBit(GPIOB,GPIO_Pin_0,Bit_SET);//超声波模块1发送引脚,trig
	
		TIM3->CNT=0;
		while(TIM3->CNT<15);
		GPIO_WriteBit(GPIOB,GPIO_Pin_0,Bit_RESET);//15us后关闭,要超过10us
		TIM3->CNT=0;
		while(TIM3->CNT<40000);//等待40ms
	
		GPIO_WriteBit(GPIOB,GPIO_Pin_1,Bit_SET);//超声波模块1发送引脚,trig
		TIM3->CNT=0;
		while(TIM3->CNT<15);
		GPIO_WriteBit(GPIOB,GPIO_Pin_1,Bit_RESET);//15us后关闭
		TIM3->CNT=0;
		while(TIM3->CNT<40000);
		
		LED3=1;
		TIM3->CNT=0;
		while(TIM3->CNT<15);
		LED3=0;
		TIM3->CNT=0;
		while(TIM3->CNT<40000);
	
		TIM_Cmd(TIM3, DISABLE);

hal库

        htim2.Instance->ARR=26-1;//设置频率为38k,具体看芯片时钟
		htim2.Instance->CNT=0;
		htim2.Instance->CCR4=0;
		HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);
		HAL_TIM_Base_Start(&htim3);//开启计时,周期为1us
		__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,13);//给红外发送模块38khz
		
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<500);//实际情况可修改发送时长
		
		htim2.Instance->CCR4=0;//停止红外信号
		HAL_TIM_Base_Stop(&htim3);
		//ir_send
		
		
		
		HAL_TIM_Base_Start(&htim3);
		HAL_GPIO_WritePin(trig4_GPIO_Port,trig4_Pin,GPIO_PIN_SET);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<15);
		HAL_GPIO_WritePin(trig4_GPIO_Port,trig4_Pin,GPIO_PIN_RESET);
		HAL_TIM_Base_Stop(&htim3);//15us高电平发送

		HAL_TIM_Base_Start(&htim3);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<40000);//等待40us
		HAL_TIM_Base_Stop(&htim3);
		
		
		HAL_TIM_Base_Start(&htim3);
		HAL_GPIO_WritePin(trig2_GPIO_Port,trig2_Pin,GPIO_PIN_SET);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<15);
		HAL_GPIO_WritePin(trig2_GPIO_Port,trig2_Pin,GPIO_PIN_RESET);
		HAL_TIM_Base_Stop(&htim3);//15us高电平发送

		HAL_TIM_Base_Start(&htim3);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<40000);//等待40us
		HAL_TIM_Base_Stop(&htim3);
		

接收

标准库

void EXTI15_10_IRQHandler(void)//中断处理红外同步信号
{
	//读取GPIO14中断线的状态
	if(EXTI_GetITStatus(EXTI_Line10) == SET)
	{
		EXTI_ClearITPendingBit(EXTI_Line10);
		get_dis();
		
		
	}
}
unsigned char i_get=0;
extern int dis_1,dis_2,dis_3;
int count_temp=0;
int t_assist[2]={-30,-1950};//后两个模块接收计时校准参数
void get_dis()
{
		
		t_count=0;
	    int i, j, N;
		i_get=0;
		
		TIM_Cmd(TIM2, ENABLE);
		TIM2->CNT=0;
		while(TIM2->CNT<270);//计时校准延时,实际可能需要用示波器或者逻辑分析仪查看

		start_listen:
		TIM2->CNT=0;//开始计时
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==Bit_SET&&TIM2->CNT<10000);//持续高电平等待低电平脉冲,也就是滤除干扰
		sr04_dis[i_get]=TIM2->CNT;
		TIM2->CNT=0;
		goon://这里goto语句是两个及以上的发送模块时需要
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==Bit_RESET)//记录低电平脉冲时间
		if(TIM2->CNT>10||TIM2->CNT<4) goto goon;//过低或过高都重计
		
		sr04_dis[i_get]+=(TIM2->CNT>20000)? 20000:TIM2->CNT;
		t_count=sr04_dis[i_get];
		sr04_dis[i_get]-=7;
		i_get++;
		
		TIM2->CNT=0;
		while(TIM2->CNT<(40000-t_count-t_assist[i_get-1]));//等待40ms
		if(i_get<3) goto start_listen;
		end:
		;
}

 hal库,这个有问题,还没有修改,可参考标准库的代码修改

float get_dis()
{
	i_get=0;

	t_count=0;
	 int i, j, N;
	while(i_get++<5)
	{
		HAL_TIM_Base_Start(&htim3);
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_SET);
		htim3.Instance->CNT=0;
		while(htim3.Instance->CNT<15);
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_RESET);
		
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_RESET&&htim3.Instance->CNT<65000);
		htim3.Instance->CNT=0;
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET);
		HAL_TIM_Base_Stop(&htim3);
		t_count+=(htim3.Instance->CNT>35000)? 35000:htim3.Instance->CNT;
		HAL_Delay(20);
	}

	sr04_dis=t_count/5.0;
	return sr04_dis;
	
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

山间朝暮-CanEve

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

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

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

打赏作者

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

抵扣说明:

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

余额充值