基于STM32F103的超声波测距

基于STM32F103的超声波测距


1.前言:这是自己的第一篇博客,关于超声波测距的程序自己之前写过一个。今天再写的时候忙活了一天但一直卡在了一个奇怪的地方,后来发现是自己手里这个德飞莱STM32F103ZET6的大板上的5V引脚根本无法输出5V(测试后发现5V引脚的电压只有2.8V),我手里这个HY-SRF05超声波模块的工作电压为5V,所以模块的电压一直不足,才导致了程序烧写进去也没现象。后来外接5V后测距正常。

注:我是用ST-LINK直接连的开发板,ST-LINK上的电源口连着3.3V,我自己怀疑是这个原因,即ST-LINK连接到开发板上的电源只有3.3V,所以开发板上的5V电源口无法输出标定的5V。用J-LINK连接开发板我没试过,所以会不会出现这个问题我不清楚。


2.正篇:用STM32的输入捕获模式来完成超声波测距

我自己写这个的时候是参照“STM32中文参考手册_V10来”完成,手册里讲得已经很详细了。
代码的核心部分如下所示:
//PA2-发送触发脉冲
//PA0-接收回响信号
void TIM2_TRIG(void)//触发信号,大于10us的高电平,周期最好大于60ms
{
TRIG_H;
Delay_us(15);
TRIG_L;
Delay_us(60000);
}
void TIM2_Initi(uint16_t Period,uint16_t Prescaler)//65534,71
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef         NVIC_InitStructure;
Flag=1;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//PA0-TIM2 CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//PA2-TIM2-CH2
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //

TIM_TimeBaseStructure.TIM_Prescaler = Prescaler; //
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//
TIM_TimeBaseStructure.TIM_Period = Period;        //
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;    //
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);

TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;//TIM2 CH1
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//IC1-TI1
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);

TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;//TIM2 CH2
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Falling;//
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_IndirectTI;//IC2-TI1
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);


TIM_SelectInputTrigger(TIM2,TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);

TIM_ITConfig(TIM2,TIM_IT_CC1|TIM_IT_CC2,ENABLE);//
TIM_SetCounter(TIM2,0);
TIM_Cmd(TIM2, ENABLE);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;      //
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            
NVIC_Init(&NVIC_InitStructure);
}
//接着是中断函数,捕获到上升沿时定时器从零开启计时,下降沿时取出定时器里的数便是声波往返的时间
void TIM2_IRQHandler(void)
{

if(TIM_GetITStatus(TIM2, TIM_IT_CC1) == SET)//检测到上升沿


if(Flag!=1)
{
ICAP1value = TIM_GetCapture1(TIM2);//计这个值其实是没有意义的
Flag=1;
distance2=((ICAP2value/2.0)*0.34)/10.0;//距离计算单位cm,声波速度340m/s,即0.34mm/us
printf("\r\n distance2= %.2f\r\n",distance2);
}

TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
}
else if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET)//检测到下降沿

Flag=0;
ICAP2value = TIM_GetCapture2(TIM2);
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
}


}

3.补充说明

有人说要不要考虑定时器溢出的问题,我认为是不用的,我用的模块最远可以测到5m,我的时钟频率为1MHz,即周期为1us,我的自动重载值为65535,上面计算过声波速度为0.34mm/us,65535*0.34=22.28m,也就是说定时器溢出时所能测得的距离22.28m大于模块的极限距离5m,所以实际上在定时器未溢出时就可以满足超声波模块的测量要求,所以不用考虑溢出。

最后,这是自己的博客处女作,水平有限,所以以上所讲的如有纰漏,还望大家批评指正,一起交流进步!

你可能感兴趣的:(单片机)