×
单片机 > 单片机程序设计 > 详情

基于STM32F103的超声波测距

发布时间:2020-05-30 发布时间:
|

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("rn distance2= %.2frn",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,所以实际上在定时器未溢出时就可以满足超声波模块的测量要求,所以不用考虑溢出。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
C8051F020的UART