本章继续要前三章的基础上加入超声波模块,引入测距的功能,方便在后期开发超声波跟随与超声波避障。同时利用蓝牙模块,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 */}
}