stm32使用hc-sr04进行超声波测距并在串口输出

HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可高达23mm。模块包括超声波发射器、接收器与控制电路
该模块引出四个接口:

VCC和GND为供电端,VCC接5V,GND必须和单片机共地(很重要,给单片机提供一个低电平参考,否则接下来的通信会错乱而导致读取到的数值无规律)
TRIG和ECHO为通信端,TRIG是触发控制信号输入,ECHO是回响信号输出
时钟配置:
在这里插入图片描述

分配trig引脚和按键控制输入,echo引脚我们通过tim计数器的ch1分配
在这里插入图片描述

设置定时器2并开启中断,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
为了能够进行GPIO中断,我们需要配置PA6引脚
在这里插入图片描述
在这里插入图片描述

超声波时序图
在这里插入图片描述

1.发送大于10us的触发信号。
2.检测超声波发出信号时产生的高电平。
3.检测超声波接收到信号时产生的低电平
显示超声波测出的距离,我这里就直接使用串口助手显示了
为了能够用输入电平控制测距的开启或者关闭,我们这里设置当输入为高电平时中断测距,再次输入高电平时重新测距。
main函数代码

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
	int a1=0;
	int p1=0;
	int time=0;
	int con=1;
	int resu=0;
	int good_en=0;
	p=&p1;
	timer=&time;
	control=&con;
	result=&resu;
	good=&good_en;
	int count=0;
	int user_num=1;
  /* USER CODE END 2 */
    int resu_arr[3];
		HAL_Delay(3000);
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {   if(count<3)
		{    if(a1<3)
			a1++;
			else a1=0;
			if(*control)  
	{	GetSR04Range(a1,p,result,good);
		if(*result==1)
		{  resu_arr[count]=1;
		count=count+1;}
	else	if(*timer>0&&*timer<20009)
			*timer=*timer+1;
		else{
			*timer=0;
			if(*good)
			*result=3;
			else *result=2;
			resu_arr[count]=*result;
			count=3;
			resu_arr[2]=*result;
	}
	}
		HAL_Delay(1200);}
		else {//printf("s1=%d,s2=%d,s3=%d\r\n",resu_arr[0],resu_arr[1],resu_arr[2]);
		
		
			printf("%d,%d%d.00200",resu_arr[2],user_num/10,user_num%10);
	count=0;
		user_num++;}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

可以看到这里主要调用了GetSR04Range函数,它在驱动文件SR04.C文件中:
进行多次连续测量,直到满足下列两个条件中的一个:

  • 检测到障碍物,此时result设为1,记录本次打分结果
  • 累计测量时间超过20000毫秒未检测到障碍物。此时:
  • 如果good为1(表明前面多次测量距离大,离障碍物远),result设为3,表示通过
  • 否则result设为2,表示未通过

uint32_t GetSR04Range(int a,int * sum,int *result,int *good)
{ 
			uint32_t temp=0;
	float Distance=0;
		TRIG_L();
		HAL_Delay(1);
		TRIG_H();
		HAL_Delay(10);
		TRIG_L();//触发信号控制
	 
		//计算距离
     if(TIM2CH1_CAPTURE_STA&0X80)        //成功捕获到了一次高电平
		{
			temp=TIM2CH1_CAPTURE_STA&0X3F; 
			temp*=65536;		 	    	//溢出时间总和
			temp+=TIM2CH1_CAPTURE_VAL;      //得到总的高电平时间
			Distance=(temp/58);
			if(a<3)
			{
				*sum+=Distance;
			}
			else{			
		float		out=*sum/3;
					if(out<4)
			{
			   *result=1;
				*good=0;
			}
		  else if(out>30)
				*result=1;
			  else if(out>15)
				*good=0;
				else *good=1;
					*sum=0;
			//	printf("out:%.3f cm\r\n",out);  //打印总的高点平时间
			}	
			TIM2CH1_CAPTURE_STA=0;          //开启下一次捕获
			return Distance;
		}	
		
		return 0;
	
}




通过驱动文件我们便可以实现串口读取经过滤波的距离数据,为了能够用GPIO引脚进行中断控制,我们同时还要修改stm32f1xx_it.c文件:

void EXTI9_5_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI9_5_IRQn 0 */
	HAL_Delay(3);//??
  if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6))
  {
		if(*control){
			  HAL_TIM_IC_Stop_IT(&htim2, TIM_CHANNEL_1); //停止定时器中断捕获
      HAL_TIM_IC_DeInit(&htim2);   //停止定时器捕获
		}
		else   //否则开始测距
    {   
      HAL_TIM_IC_Start(&htim2, TIM_CHANNEL_1);  
      HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);  }
    *control=~*control;
  }
  else
  {
    
  }

  /* USER CODE END EXTI9_5_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(key_Pin);
  /* USER CODE BEGIN EXTI9_5_IRQn 1 */

  /* USER CODE END EXTI9_5_IRQn 1 */
}

这样就可以在GPIO6引脚接收到高电平的时候进入中断并且进入判断。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值