STM32 Cubemax(九) ——利用输入捕获中断实现超声波测距

STM32 Cubemax(九) ——利用捕获中断实现超声波测距


前言

因为要实现一下卡尔曼滤波,所以这次先写一下超声波,顺便重温一下输入捕获中断。

一、超声波模块原理

在这里插入图片描述
但凡在网上搜过超声波这个模块的,对这个图都不陌生,简单的说就是想得到超声波的数据,包含以下几个步骤。
1.发送大于10us的触发信号。
2.检测超声波发出信号时产生的高电平。
3.检测超声波接收到信号时产生的低电平

而我们就是通过后两步,即去检测处因为超声波产生的高电平的时间,从而来得到距离信息的。而输入捕获的作用就是用来去捕获高电平或者低电平的持续时间的
在这里插入图片描述
我们的编程就是根据上图来实现的。

二、Cubmax配置

1.配置定时器输入捕获
在这里插入图片描述
本实验板子为F407,分频系数选择84-1,则计数精度达到1us。100000为溢出上限
—————————————————————————————————————————————

2.配置触发引脚
此引脚即为用来产生20us的高电平来触发超声波。
在这里插入图片描述
—————————————————————————————————————————————

3.开一个60ms的定时器,来在固以一定的频率触发超声波。在这里插入图片描述
————————————————————————————————————————————
4.开相应的中断
在这里插入图片描述

三、代码

一,我们老样子,先创建一个有关超声波的参数的结构体和定义一些参数,以及结构体的初始化函数。

#define CPU_FREQUENCY_MHZ    168		// F407主频,用来写20us延时函数
#define Trig(state) HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1, (GPIO_PinState)(state))  //触发引脚
#define RELOADVALUE 100000	//重装载值

typedef struct
{
    
    
	float distance;						//计算出来的距离
	uint8_t loop_num;					//溢出次数
	uint32_t rising_time;				//捕获上升沿的时间
	uint32_t falling_time;				//捕获下降沿的时间
	uint8_t capture_state;				//当前捕获的状态
	uint32_t time;						//计算出来的时间
}Supersonic;

初始化函数,在main.c中调用

void Supersonic_Init()
{
    
    
		supersonic.distance = 0;
		supersonic.rising_time = 0;
		supersonic.falling_time = 0;
		supersonic.capture_state = 0;
		supersonic.time = 0;
		supersonic.loop_num = 0;
	
		HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);	 //开启捕获中断
		HAL_TIM_Base_Start_IT(&htim3);				 //开启60ms中断
		__HAL_TIM_ENABLE_IT(&htim2,TIM_IT_UPDATE);	 //开启溢出中断
}

二,编写20us延时函数和触发函数


//延时函数,这个直接抄就行
void delay_us(__IO uint32_t delay)
{
    
    
    int last, curr, val;
    int temp;

    while (delay != 0)
    {
    
    
        temp = delay > 900 ? 900 : delay;
        last = SysTick->VAL;
        curr = last - CPU_FREQUENCY_MHZ * temp;
        if (curr >= 0)
        {
    
    
            do
            {
    
    
                val = SysTick->VAL;
            }
            while ((val < last) && (val >= curr));
        }
        else
        {
    
    
            curr += CPU_FREQUENCY_MHZ * 1000;
            do
            {
    
    
                val = SysTick->VAL;
            }
            while ((val <= last) || (val > curr));
        }
        delay -= temp;
    }
}

//20us的高电平
void Supersonic_Start()
{
    
    
		Trig(0);
		delay_us(20);
		Trig(1);
}

三,编写输入捕获中断以及更新中断

//重写输入捕获中断
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    
    
	if(htim->Instance == htim2.Instance)
	{
    
    
			if(supersonic.capture_state == 0) 		//如果当前状态为捕获高电平																							
			{
    
    
				supersonic.rising_time = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2);	//上升沿的时间								
				__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_FALLING);	//开始捕获低电平
				HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);	 																								//重新开启输入捕获中断
				
				supersonic.capture_state = 1;		//将状态改为捕获低电平																												
			}
			else if(supersonic.capture_state == 1)		//如果当前状态为捕获低电平																									
			{
    
    
				supersonic.falling_time = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2);				//获得下降沿的时间
				__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING);			//恢复为捕获高电平
				HAL_TIM_IC_Stop_IT(&htim2, TIM_CHANNEL_2);																									//停止输入捕获,等触发信号开始再开启
			
				supersonic.time = supersonic.falling_time + supersonic.loop_num * RELOADVALUE - supersonic.rising_time;	
				supersonic.distance = (float)supersonic.time*340/(2*10000);	//转换为cm为单位
				//清空状态
				supersonic.loop_num = 0;
				supersonic.capture_state = 0;

			}
		}
		
}

//在更新中断中,我们要处理溢出中断和定时器60ms中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
    
		if(htim->Instance ==	htim3.Instance)	//60ms
		{
    
    
				if(supersonic.capture_state == 0) 		//此时是初始状态
				{
    
    
						Supersonic_Start();
						HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);	//记得开启捕获中断
				}
		}
		if(htim->Instance == htim2.Instance)	//溢出中断
		{
    
    
				if(supersonic.capture_state == 1)	//此时是在捕获低电平
				{
    
    
							supersonic.loop_num++;	
				}
		}
		
}

—————————————————————————————————————————————

实验结果

我这里将测得的距离值,打印处理做成表格。
在这里插入图片描述
可以看到,超声波测量过程中噪声是挺多的,这就需要我们使用一些滤波方法来进行处理。

总结

根据我们的结果,我们将使用卡尔曼滤波来处理超声波数据,来看看结果如何。
STM32 Cubemax(十) ——利用一阶卡尔曼滤波处理超声波数据

猜你喜欢

转载自blog.csdn.net/lzzzzzzm/article/details/119538532