stm32驱动HC_SR04超声波测距模块

         代码采用外部中断方式进行时间采样,采集的时间加以转换就是超声波模块测得的的距离值。

 引脚接线:VCC--3.3V或5V电源

GND--接地线

TRIG--触发控制信号输入(PA6)

ECHO--回响信号输出(PA7)

时序图:

基本工作原理:

(1)采用IO口TRIG触发测距,给最少10us的高电平信号;

(2)模块自动发送8个40kHz的方波,自动检测是否有信号返回;

(3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续时间就是超声波从发射到返回的时间。

测距公式=高电平时间(us)/58 ,单位cm。

超声波模块初始化代码如下:

void Ultrasonic_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
    EXTI_InitTypeDef EXTI_InitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
  
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource7);
	
	EXTI_InitStruct.EXTI_Line=EXTI_Line7;
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising_Falling;
	EXTI_Init(&EXTI_InitStruct);
	

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	NVIC_InitStruct.NVIC_IRQChannel=EXTI9_5_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStruct);
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

	
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period=1000-1;  //1MS
	TIM_TimeBaseInitStruct.TIM_Prescaler=72-1;
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	
	NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVIC_InitStruct);
	
	TIM_Cmd(TIM2,DISABLE);
	
}

我配置PA6为TRIG引脚,IO模式为推挽输出;PA7引脚作为接受引脚ECHO,IO模式为浮空输入,开启定时器2中断和PA7引脚的外部中断来实现记录高电平时间,需特别注意的地方是,定时器配置的为1ms执行一次中断;

超声波模块起始信号:

void Ulstasonic_Startup(void)
{
    GPIO_SetBits(GPIOA,GPIO_Pin_6);
    delay_us(20);
    GPIO_ResetBits(GPIOA,GPIO_Pin_6);
}

我们使用软件方式让TRIG引脚输出20us的高电平,作为超声波测距的触发信号;

中断代码如下:

void EXTI9_5_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line7)==SET)
    {
        if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)==1)
        {
            TIM2_Counter=0;
            TIM_SetCounter(TIM2,0);
            TIM_Cmd(TIM2,ENABLE);
        }
        if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)==0)
        {
            TIM_Cmd(TIM2,DISABLE);
            distance=(TIM2_Counter*1000+TIM_GetCounter(TIM2))/58; //单位cm
        } 
    }        
        EXTI_ClearITPendingBit(EXTI_Line7);
}

void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
    {
        TIM2_Counter++;
    }
    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}

PA7外部中断配置为上升下降沿触发,当PA7检测电平变化时,判断PA7的电平状态为1时,开启定时器2的时钟,时钟开始计时,直到下一次下降沿到来关闭时钟,同时计算定时器记的值(TIM2_Counter,单位为ms)和定时器内还未更新的cnt的值(us),最后将时间单位统一成us计算超声波测得距离;

测距代码:

u32 distance_sum=0;
u16 distance_max=0;
u16 distance_min=9999;
u16 distance_counter=0;
u16 distance_average;

u16 Get_distance(void)
{
    Ulstasonic_Startup();
    if(distance<distance_min)   distance_min=distance;
    if(distance>distance_max)   distance_max=distance;
    distance_sum+=distance;
    distance_counter++;
    if(distance_counter==12)
    {
        distance_average=(distance_sum-distance_max-distance_min)/(distance_counter-2);
        distance_sum=0;
        distance_max=0;
        distance_min=9999;
        distance_counter=0;
    }
    return distance_average;
}

此代码是对最后测距结果进行处理,若读者不太能理解可以看博主历史博客,有详细讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值