基于STM32——超声波模块US100(串口和电平获取距离)

小白一个,这个作为一个学习记录贴,资料都是各个地方拼接的,如有错漏之处,敬请指正。

一、US100工作原理:

        在发生器的两电极之间外加一个脉冲信号,当外加信号的频率与压电晶片的频率相等时,压电晶片就会发生振动,同时也会带动共振板进行振动,这时就会产生超声波,这就是超声波发生器的发送端;但是如果发生器的两电极之间没有外加脉冲信号,而共振板又接收到了发射的超声波时,就会迫使压电晶片发生振动,然后产生的机械能转换为电信号,这就是超声波发生器的接收端。

        US-100超声波测距模块可以实现2cm~4.5m的非接触测距功能,拥有对2.4~5.5V的宽电压输入范围,静态功耗低于2mA,自带温度传感器对距离结果进行校正,同时具有GPIO,串口等多种通讯方式,内带看门狗,工作稳定可靠。

注:上面的图都截至商家给的产品介绍,最后会打包一起发出来,详细的就不多写了,有需要的自己去看看。

二、电平触发测距

2.1 电平触发工作原理

        在模块上点之间拔掉跳线帽,使模块处于电平模式。

        电平触发测距的时序图:

        根据时序图可以知道,在Trig引脚输入一个10us的高电平,系统会发出8个40kHz的脉冲,然后检测回波信号。当检测到回波信号后,模块还要对温度进行测量,根据当前温度对测距结果进行校正。将校正结果在Echo输出。

        在此模式下,模块将距离值转化为340m/s时的时间值的两倍,通过Echo端输出一高电平,可根据此高电平时间来计算距离值:(高电平时间*340m/s)/2。

        注:温度校正模块自己进行的,不用自己在校正。

2.2 硬件接线

        这里使用的是stm32最小系统板来接的,某宝都买的到的。拿到US-100,将Trig引脚接到PA9,Echo引脚接到PA10,电源和接地就随便接了。然后我接了一个小屏幕,用来观察数据,学过 江协科技的stm32教程 的就很熟悉了,这里屏幕的接线是和江协科技的一样的,不会接的可以看看视频。有面包板的同学可以接面包板,我没有所以不接了。

2.3 程序实现

        屏幕显示函数是借鉴江协科技的,不会使用可以去看看视频。我就直接拿模版来写了

        引脚初始化:

void US100_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;					//TRIG引脚
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;	
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_10;					//ECHO引脚
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;	
	GPIO_Init(GPIOA,&GPIO_InitStructure);	
	
	
}

配置定时器函数:

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

	TIM_InternalClockConfig(TIM2);//选择内部时钟

	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1;//分频
	TIM_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period= 50000-1;						
//自动重装载寄存器ARR. 20us记一个数
	TIM_TimeBaseStructure.TIM_Prescaler= 14400-1;					
//预分频寄存器PSC,用于得到需要的频率72MHz/(PSC+1)
	TIM_TimeBaseStructure.TIM_RepetitionCounter= 0;     
//高级定时器输出比较
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);			
	
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	
	TIM_Cmd(TIM2,DISABLE);	
	
}

计算距离:

uint16_t US100_Test(void)
{
	uint16_t count;
	int16_t distance;
	TIM_Cmd(TIM2,ENABLE);
	
	GPIO_SetBits(GPIOA,GPIO_Pin_9);
//让TRIG引脚置高10us以上,发出脉冲
	Delay_us(15);
	GPIO_ResetBits(GPIOA,GPIO_Pin_9);
	
	while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_10) == 0);
 //等待接受反射回来的超声波。
	TIM_SetCounter(TIM2,0);																
//管脚置高时将定时器重零开始计数
	while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_10) == 1);	
//等待管脚变为底电平
	TIM_Cmd(TIM2,DISABLE);																
//停止计数
	count=TIM_GetCounter(TIM2);														
//读取定时器的数值
	
	distance=34*count;																		//根据公式(高电平时间*340m/s)/2 。																												//一个数计时为20us,带进去就得到这样了。20us得到0.68mm比测量精度小就行
	return distance;
}

主函数:

int main(void)
{
	int a=0;
	OLED_Init();
	
	US100_Init();
	Timer_Init();
	
	while (1)
	{	   
		a=US100_Test();
	  OLED_ShowString(1, 1, "dis");
		OLED_ShowNum(2, 1,a/10, 3);
		OLED_ShowChar(2,4,'.');
		OLED_ShowNum(2, 5,a%10, 1);
		OLED_ShowString(2, 6, "cm");	
		
	}
}

电平的代码基本就是这样,完整代码在文章最后会给出。

2.4 实际效果

        记住使用电平获得距离要把跳线帽取下来。电平读取的数据跳来跳去的,精度不是很行,可能是我代码不够完善,交给你们去完善了,不过大致思路就是这样的。

 三、串口触发测距

3.1串口触发工作原理

        在模块上电前,首先插上跳线帽,使模块处于串口触发模式。

        串口触发时序图:

        在此模式下只需要在Trig引脚输入0x55(波特率为9600),系统便可发出8个40kHz的脉冲,然后检测回波信号。检测到回波信号后,模块还要检测温度值,根据温度值校正测距结果,将校正数据通过Echo发送回来。输出距离值共两个字节,第一个是距离高8位(Hdate),第二个为距离低8位(Ldate),单位为mm,距离值(Hdate*256+Ldate)mm。

        注:温度校正模块自己进行的,不用自己在校正。

3.2 硬件接线

        硬件接线和电平接线是一样的,这里就不贴图了。

3.3 程序实现

        屏幕显示代码和串口收发都是借鉴江协科技的代码,这里我就作为模版使用了。不会使用可以去看看视频。

        串口配置,这里就不写了,完整代码会给出来的。

void USART1_IRQHandler(void)//串口中断获取返回的数据
{
	static uint8_t a=0;
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		uint8_t RxData = USART_ReceiveData(USART1);
		if(a==0) //获取高位数据
		{
			US100_Date[a]=RxData;
			a++;
		}
		else//获取低位数据
		{
			US100_Date[a]=RxData;
			a=0;
			Serial_RxFlag=1;
		}		
		
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清空中断标志位
	}
}

US-100获取距离函数:

void US100_Init(void)
{
	Serial_Init();	
//串口初始化,这里不介绍了,不懂就去看看江协科技视频吧,在串口接收数据那节。
}

void US100_Cmd(uint8_t Byte)
{
	Serial_SendByte(Byte);
}

uint16_t US100_GetDate(void)
{	
	US100_Cmd(0x55);//发送0x55,触发信号
	uint16_t a ;
	while(Serial_GetRxFlag()==0)//等待获取数据标志位
	{
		a=US100_Date[0]*256+US100_Date[1];		
	}
	Delay_ms(3);
	return a;
}

主函数:

int main(void)
{
	OLED_Init();
	US100_Init();
	 	
	uint16_t a;
	while (1)
	{
		a=US100_GetDate();
		OLED_ShowString(1, 1, "dis");
		OLED_ShowNum(1, 4,a, 5);
		OLED_ShowString(1, 9, "mm");
				
	}	
}

3.4 实际效果

        串口触发记得接跳线帽,串口触发的数据就比较稳定波动也是在模块度(3mm)附近波动,个人还是推荐使用串口,数据比较准确。

        

结尾

        代码都是自己修改写的,比较粗糙,如果觉得写的不好请私信指出,如有侵权,联系删除。

另外US-100是有测量温度功能的,这里就不写了,留着给各位研究吧,其实也不难。

        这里完整代码和模块资料:

        链接:https://pan.baidu.com/s/19mWn7unfgTr31gRz6HUMQA?pwd=ks7o 
        提取码:ks7o

以下是基于STM32F103的超声波模块获取数据的示例程序: ```c #include "stm32f10x.h" #define TRIG_PIN GPIO_Pin_12 // 超声波模块的Trig引脚连接到PA12 #define ECHO_PIN GPIO_Pin_11 // 超声波模块的Echo引脚连接到PA11 void delay_us(uint32_t us) // 延时函数,延时us微秒 { uint32_t i; for(i=0; i<us*8; i++); } int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟 // 配置PA12为输出模式,用于控制超声波模块的Trig引脚 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = TRIG_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置PA11为输入模式,用于接收超声波模块的Echo引脚输出的电平信号 GPIO_InitStructure.GPIO_Pin = ECHO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); while(1) { GPIO_ResetBits(GPIOA, TRIG_PIN); // 将Trig引脚拉低 delay_us(2); // 延时2us GPIO_SetBits(GPIOA, TRIG_PIN); // 将Trig引脚拉高 delay_us(10); // 延时10us GPIO_ResetBits(GPIOA, TRIG_PIN); // 将Trig引脚拉低 uint32_t pulse_start = 0, pulse_end = 0; while(GPIO_ReadInputDataBit(GPIOA, ECHO_PIN) == 0); // 等待Echo引脚的电平从低变高 pulse_start = TIM2->CNT; // 记录计数器的值 while(GPIO_ReadInputDataBit(GPIOA, ECHO_PIN) == 1); // 等待Echo引脚的电平从高变低 pulse_end = TIM2->CNT; // 记录计数器的值 uint32_t pulse_duration = pulse_end - pulse_start; // 计算超声波往返时间 float distance = pulse_duration * 0.017; // 计算距离(声速在空气中约为340m/s,每秒传播约17m) } } ``` 需要注意的是,上述程序中使用了定时器TIM2的计数器来记录Echo引脚电平变化的时间,因此需要在程序中初始化并使能TIM2定时器。此外,还需要根据实际情况调整延时函数delay_us()中的参数,以保证超声波模块的工作正常。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值