欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 第四章 基于Freertos智能小车的超声波测距

第四章 基于Freertos智能小车的超声波测距

2025/9/24 0:11:54 来源:https://blog.csdn.net/qq_51457391/article/details/147892790  浏览:    关键词:第四章 基于Freertos智能小车的超声波测距

        本章继续要前三章的基础上加入超声波模块,引入测距的功能,方便在后期开发超声波跟随与超声波避障。同时利用蓝牙模块,stm32计算出距离都会传输到手机APP上进行显示。此外大家可以回顾前几章内容学习制作小车,零基础制作Freertos智能小车

1.模块概述

        此次的模块使用的是HC-SR04,核心功能是通过发射和接收超声波信号,适用于2cm~400cm的中短距离测量。工作电压5V。

2.模块工作原理

        a.采用 IO 口 TRIG 触发测距信号,保持 10-20us 的高电平。
        b.模块会自动发送 8 个 40khz 的方波,发送完成后,ECHO会置为1。
        c.打开单片机的定时器资源进行计时,不断循环等待ECHO何实置0。
        d.ECHO高电平持续的时间就是超波从发射到返回的时间,当ECHO会置为0后,关闭定时器,并读取定时器的计数值。
        e.距离=(声速*时间)/2,声速为342.62m/s

3.程序设计

        引脚使用

        HCSR04_TRIG    PA2
        HCSR04_ECHO     PA3 

        配置定时器

        对于定时器不了解的大家可以参考这篇文章STM32F103的定时器

  • 预分频器 (Prescaler) = 71,将 72MHz 的时钟分频为 1MHz
  • 自动重载值 (Period) = 999,定时器每计数 1000 次产生一次溢出中断
  • 计数频率 = 1MHz,即每个计数周期为 1 微秒 (μs)
  • 定时器溢出周期 = 1000μs = 1ms,即每 1ms 产生一次中断
    #ifndef __HC-SR04_H
    #define __HC-SR04_H	 #include "sys.h"#define ECHO_Reci  PAin(3)
    #define TRIG_Send  PAout(2)
    //超声波硬件接口定义
    //超声波硬件接口定义
    //超声波硬件接口定义
    #define HCSR04_PORT     GPIOA
    #define HCSR04_CLK      RCC_APB2Periph_GPIOA
    #define HCSR04_TRIG     GPIO_Pin_2
    #define HCSR04_ECHO     GPIO_Pin_3void Hcsr04Init();
    float Hcsr04GetLength(void );#endif

#include "stm32f10x.h"                  // Device header
#include "HC-SR04.h"
#include "delay.h"//超声波计数
u16 msHcCount = 0;//定时器3设置
void hcsr04_NVIC()
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;//TIM4定时器中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     NVIC_Init(&NVIC_InitStructure);
}//IO口初始化 及其他初始化
void Hcsr04Init()
{  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;   GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);//GPIO初始化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_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);  GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);    //TIM4时钟使能RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);   //设置定时器预分频系数和周期TIM_TimeBaseStructure.TIM_Period = (1000-1); TIM_TimeBaseStructure.TIM_Prescaler =(72-1); TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);          //清除TIM4的待处理标志位TIM_ClearFlag(TIM4, TIM_FLAG_Update);  //TIM4中断使能TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);    //定时器中断初始化hcsr04_NVIC();//TIM4使能TIM_Cmd(TIM4,DISABLE);     
}//定时器4终中断
void TIM4_IRQHandler(void)  
{//记录返回信号高电平持续的时间if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)  {TIM_ClearITPendingBit(TIM4, TIM_IT_Update  ); msHcCount++;//定时器计数}
}

        启动测量

//打开定时器4
static void OpenTimerForHc()  
{TIM_SetCounter(TIM4,0);//定时器从0开始计数msHcCount = 0;//计数归零TIM_Cmd(TIM4, ENABLE); //使能
}

        关闭计数

//关闭定时器4
static void CloseTimerForHc()    
{TIM_Cmd(TIM4, DISABLE); 
}

        测量并读取时间

//获取定时器4计数器值
u32 GetEchoTimer(void)
{u32 t = 0;t = msHcCount*1000;//将定时器计数转换成时间t += TIM_GetCounter(TIM4);//定时器输入捕获TIM4->CNT = 0;  //清空定时器计数delay_ms(50);//每次测量间隔return t;
}

        推算距离

//通过定时器4计数器值推算距离
float Hcsr04GetLength(void )
{u32 t = 0;int i = 0;float lengthTemp = 0;float sum = 0;while(i!=5)//测量五次{TRIG_Send = 1;      //给TRIG口输出一个高电平,延时20usdelay_us(20); TRIG_Send = 0;while(ECHO_Reci == 0); //等待ECHO口返回高电平信号     OpenTimerForHc();        //ECHO输出高电平之后打开定时器i = i + 1;               while(ECHO_Reci == 1);//用中断接收8个40khz的方波CloseTimerForHc();        //接收完成后关闭定时器t = GetEchoTimer();        //t就是高电平持续的时间lengthTemp = ((float)t*342.62)/2;//lengthTemp = 342.62*t/2;sum = lengthTemp + sum ;}lengthTemp = sum/5.0;//测量五次取平均值return lengthTemp;
}

4.加入主程序逻辑 

        在写好超声波的初始化程序后,就可以加入Freertos中。
        引入头文件,创建超声波测距任务句柄,超声波测距_Task任务实现,设置全局变量,获取超声波的距离,并设置在跟随以及避障模式下生效。

/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "Task.h"
#include "queue.h"
#include "usart.h"//蓝牙/**************************** 任务句柄 ********************************/
/* * 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄* 以后我们要想操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么* 这个句柄可以为NULL。*/
static TaskHandle_t HCSR04_Len_Task_Handle = NULL;/* 超声波测距任务句柄 */
static void HCSR04_Len_Task(void* pvParameters);/* 超声波测距_Task任务实现 *//*获取超声波的距离,只在跟随以及避障模式下生效
*/
float Len = 0.0;/*********************************************************************** @ 函数名  : HCSR04_Len_Task* @ 功能说明: 获取超声波的测试距离,通过@SR04:距离#的方式发给手机APP,在终端上查看距离* @ 参数    :   * @ 返回值  : 无********************************************************************/
static void HCSR04_Len_Task(void* parameter)
{	while (1){if(Mode == 0 || Mode == 2)//仅在跟随模式与避障模式下生效{Len = Hcsr04GetLength();//测距printf("@SR04:%f#",Len);//将距离通过蓝牙传给手机APP}vTaskDelay(500);   /* 延时100个tick */}
}


        
        

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词