超声波模块测量距离防碰撞
1.超声波测距: 原理:超声测距其实就是通过单片机控制超声波模块发出一系列超声波,当超声波遇到障碍物时反弹回来,根据声音在空气中的传播速率340m/s,再结合上述所讲的方法求得时间t,应用初高中物理知识,即可求解距离。(驱动超声波模块需要给它一个10-20us高电平) 即 测量距离=(高电平持续时间(340M/S))/2 例子详解:我们算出的高电平时间是以us为单位,因此我们可以把声波传输速度看成大约为340M/S,合34,000CM/S。 即34,000除以1,000,000CM/US。 即为:0.0340CM/US 换种角度:1/(0.0343 CM/US) 即:29.00 US/CM。 这就意味着,每290.0US表示10CM的距离。1厘米就是29.00US。 但是发送后到接收到回波,声音走过的是2倍的距离呀。 所以实际距离就是1厘米,对应58.0US。 即 测量距离=(高电平持续时间/58.0(CM))
2.输入捕获: 基本原理:定时器的输入捕获模式可以用来测量脉冲宽度或者测量频率。除了基本定时器,通用和高级均有输入捕获功能。如图所示:
首先,我们设定定时器工作模式为向上计数模式,图中t1-t2时间间隔就是我们需要测量的脉宽时间(即高电平时间)。测量方法如下:
1: 设定定时器某通道为上升沿捕获,这样在t1时刻,就会捕获到当前值CNT值,然后马上清零,同时设置该通道为下降沿捕获,这样到t2时刻,又发生捕获事件,得到此时的CNT值,记为CCRx2。这样,根据定时器的计数频率可以算出t1-t2的时间,从而得到高电平脉宽。
2:在t1-t2的时间段里,有可能发生N次溢出,我们需要对此进一步处理,防止高电平过长,导致数据不准确。因此,CNT计数的次数等于N*ARR+CCRx2,有了这个计数次数,再乘以 CNT 的计数周期,即可得到 t2-t1 的时间长度,即高电平持续时间。
3.(超声波模块)HC_SRO4 实验中所实验的 HC-SR04超声波模块主要是由两个通用的压电陶瓷超声传感器,并加外围信号处理电路构成的。 1)引脚和原理: 该模块有VCC、GND、Trig和Echo针脚。TRIG是输出和ECHO是输入。 该模块的工作原理为:模块所需要的供电是5V 1.先向TRIG脚输入至少10us的触发信号 2.该模块内部将发出 8 个 40kHz 周期电平并检测回波。 3.一旦检测到有回波信号则ECHO输出高电平回响信号。回响信号的脉冲宽度与所测的距离成正比 4.由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。公式: 距离=高电平时间*声速(340M/S)/2。
2)实现功能:通过超声波模块测距离,并将测试距离显示到串口助手上。 根据工作原理,我们可以选择两种模式驱动 1.采用中断+定时器方式,将ECHO定义为上升沿下降沿都能触发中断,trig触发之后,echo高电平进中断打开定时器,echo低电平关闭定时器并统计定时器计数值 2.采用普通IO+定时器模式,触发之后等待echo响应,响应时打开定时器,直到echo恢复低关闭定时器,获取时间
注1:此模块不宜带电连接,如果要带电连接,则先让模块的 Gnd 端先连接。否则会影响模块工作。 注2:测距时,被测物体的面积不少于0.5平方米且要尽量平整。否则会影响测试结果。
通过上面原理的学习,再通过代码hcsr04.c文件加深理解:
#define HCSR04_PORT GPIOA
#define HCSR04_CLK RCC_APB2Periph_GPIOA
#define HCSR04_TRIG GPIO_Pin_4
#define HCSR04_ECHO GPIO_Pin_0
#define TRIG_Send PAout(4)
#define ECHO_Reci PAin(0)
u16 msHcCount = 0;
extern u16 TIM2CH1_CAPTURE_STA,TIM2CH1_CAPTURE_VAL;
void Hcsr04_Init(u32 arr,u32 psc)
{
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x00;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);
TIM_CtrlPWMOutputs(TIM2,ENABLE);
Hcsr04_NVIC();
TIM_Cmd(TIM2, ENABLE);
}
void Hcsr04_NVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM2_IRQHandler(void)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
if(TIM2CH1_CAPTURE_STA&0X40)
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)
{
TIM2CH1_CAPTURE_STA|=0X80;
TIM2CH1_CAPTURE_VAL=0XFFFF;
}
else
TIM2CH1_CAPTURE_STA++;
}
}
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
if(TIM2CH1_CAPTURE_STA&0X40)
{
TIM2CH1_CAPTURE_STA|=0X80;
TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2);
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);
}else
{
TIM2CH1_CAPTURE_STA=0;
TIM2CH1_CAPTURE_VAL=0;
TIM_SetCounter(TIM2,0);
TIM2CH1_CAPTURE_STA|=0X40;
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update);
}
|