完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
【实验原理】
一、HC-SR04超声波传感器简介 超声波传感器是利用检测采集超声波的形式来获得环境信息的传感器。通常用于测距、定位等具体应用场景。超声波是一种弹性介质中的机械波,通常其振动频率为几十KHz到几十MHz(人体能听到的声音频率在20Hz到20KHz)。相比与人耳能听到的声波,超声波具有频率高、波长小、绕射现象小等特点,其传播的方向性强,因此可以用来检测一个固定方向上的距离信息。 本实验采用HC-SR04超声波测距模块,该模块在空气中的测量范围为20mm到4000mm,其测量精度达到3mm。HC-SR04超声波测距模块的硬件实物图如图1.1所示,该模块主要包涵超声波发射器、超声波接收器和外围控制威廉希尔官方网站 。在威廉希尔官方网站 板上一共引出4根引脚,对映于图1.1模块摆设的方向,其接口从左到右分别为VCC(+5V)、Trig(触发信号输入)、Echo(回响信号输出)、GND。 二、工作原理 在外部威廉希尔官方网站 正常供电的情况下,外部采集威廉希尔官方网站 通过给该模块的Trig引脚上输入一个长为10us至20us的高电平信号,以开启一次采集。在模块接收到方波的输入后,超声波发射器会向正前方自动发射8个40KHz的声波信号,于此同时,回响信号的输出端会从低电平跳转为高电平。发射出去的超声波经过前方障碍物的反射,产生相同频率的反射回波,超声波接收器接受到反射回波后,回响信号输出端会从高电平跳转为低电平。对于外部采集威廉希尔官方网站 ,需要利用定时器采集回响信号为高电平的总时长T秒,然后根据声音在空气中的传播速度344米/秒计算出模块到障碍物之间的距离D=T*344/2米。 STM32芯片中集成了强大的定时器模块,其工作状态主要有以下几种模式:输入捕获模式、PWM输入模式、强制输出模式、输出比较模式、PWM模式、单脉冲模式等。在本实验中需要用到的是定时器模块的输入捕获模式。当定时器工作在输入捕获模式下时,当芯片检测到ICx信号引脚上相应的跳变沿后,定时器会将当前的数值锁存在TIMx_CCRx(捕获/比较寄存器)中,同时,在TIMx_SR寄存器中相应的CCxIF标志位被置‘1’,若预先配置使能了中断操作,则同时会响应中断函数。 三、硬件连接和相关库函数介绍 图2 硬件连接示意图 TIM_TimeBaseInitTypeDef结构体参数的配置如下: typedef struct { uint16_t TIM_Prescaler; // 预分频器 uint16_t TIM_CounterMode; // 计数模式 uint32_t TIM_Period; // 定时器周期 uint16_t TIM_ClockDivision; // 时钟分频 uint8_t TIM_RepetitionCounter; // 重复计算器 } TIM_TimeBaseInitTypeDef; (1) TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定TIMx_PSC 寄存器的值。可设置范围为 0 至 65535,实现 1 至 65536 分频。 (2) TIM_CounterMode:定时器计数方式,可是在为向上计数、向下计数以及三种中心对齐模式。基本定时器只能是向上计数,即 TIMx_CNT 只能从 0 开始递增,并且无需初始化。 (3) TIM_Period:定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为 0 至 65535。 (4) TIM_ClockDivision:时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能,不用设置。 (5) TIM_RepetitionCounter:重复计数器,属于高级控制寄存器专用寄存器位,利用它可以非常容易控制输出 PWM 的个数。这里不用设置。 四、软件流程图 本实验中使用到的库文件有:oled.c显示屏库函数、sys.c系统库函数、delay.c延时库函数。实验的流程示意图如图3所示: 【实验环境】 硬件设备 双轮自平衡机器人。如图4所示,在平衡车背面中间安装了HC-SR04超声波测距模块。 ST-Link下载器(包含USB线与下载线)。如图5所示。 操作系统: Windows7/8/10,32bit/64bit 软件环境 Keil 5 实验场地 为了直观感受测距效果,试验场地最好设有平整无遮挡墙面。 【实验步骤】 第一步 配置工程环境 打开已经建立好的工程模板,在新建立的工程模板中已经添加五个文件夹,分别命名为USER、HARDWARE、SYSTEM、CORE、FWLib文件夹,如图6所示。其中USER文件夹存放的是主函数,HARDWARE文件夹存放的是本实验对应的硬件设备函数,SYSTEM存放的是本课程所有实验通用的函数,CORE文件夹存放的是启动文件,FWLib文件夹存放的是底层驱动函数。 图6 工程模板对应的文件夹 在HARDWARE文件夹下新建两个文件,分别为timer.c和timer.h。分别存放定时器行数的函数文件和头文件,如图7所示。 图7 在HARDWARE文件夹下建立tiner.c与timer.h文件 第二步 编写定时器函数,完成定时器的配置和启用 打开程序中的timer.c文件,首先将timer.h文件包含进来。其次对TIM3_Cap_Init 函数进行编写,选择要使用的时钟,输入捕获的引脚及其参数,并初始化定时器中断。 #include “timer.h” /**************************************************************** 函数功能:定时器3通道3输入捕获初始化 入口参数:arr::自动重载值 psc:时钟预分频数 返回值:无 ****************************************************************/ TIM_ICInitTypeDef TIM3_ICInitStructure; void TIM3_Cap_Init(u16 arr,u16 psc) { //初始化结构体 GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; //(1) TIM时钟使能, GPIO 时钟使能 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //使能GPIO 时钟 //(2) GPIO 端口模式设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PBO输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //(3)初始化定时器3(TIM3) TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重载值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TimeBaseStructure中指定的参数初始化TIMx的时间基数单位 //(4)初始化TIM3输入捕获参数 TIM3_ICInitStructure.TIM_Channel = TIM_Channel_3; //CC1S=03选择输入端 TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获 TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置不分频 TIM3_ICInitStructure.TIM_ICFilter = 0x00; //配置输入滤波器,不滤波 TIM_ICInit(TIM3, &TIM3_ICInitStructure); //(5)中断分组初始化 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级,2级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级,0级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器 //(6) 使能捕获和更新中断 TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC3,ENABLE); //允许更新中断,允许CC3IE捕获中断 //(7) 使能定时器 TIM_Cmd(TIM3, ENABLE); //使能定时器3 } 编写超声波中断脉宽读取中断函数 void TIM3_IRQHandler(void) { u16 tsr; tsr=TIM3-》SR; if((TIM3CH3_CAPTURE_STA&0X80)==0) //还未成功捕获 { if(tsr&0X01) //溢出 { if(TIM3CH3_CAPTURE_STA&0X40) //已经捕获到高电平 { if((TIM3CH3_CAPTURE_STA&0X3F)==0X3F) //高电平过长 { TIM3CH3_CAPTURE_STA|=0X80; //标记成功捕获一次 TIM3CH3_CAPTURE_VAL=0XFFFF; }else TIM3CH3_CAPTURE_STA++; } } if(tsr&0x08) //发生捕获事件 { if(TIM3CH3_CAPTURE_STA&0X40) //捕获到一个下降沿 { TIM3CH3_CAPTURE_STA|=0X80; //标记成功捕获一次高电平脉宽 TIM3CH3_CAPTURE_VAL=TIM3-》CCR3; //获取当前的捕获值 TIM3-》CCER&=~(1《《9); //CC1P=0 设置为上升沿捕获 } else //第一次捕获到上升沿 { TIM3CH3_CAPTURE_STA=0; //清空 TIM3CH3_CAPTURE_VAL=0; TIM3CH3_CAPTURE_STA|=0X40; //标记捕获到了上升沿 TIM3-》CNT=0; //计数器清空 TIM3-》CCER|=1《《9; //CC1P=1 设置为下降沿捕获 } } } TIM3-》SR=0; //清除中断标志位 } (5)编写超声波接受回波函数,计算距离 /************************************************************* 函数功能:超声波接收回波函数 入口参数: 无 返回值: 无 *************************************************************/ // TIM3CH3_CAPTURE_STA与TIM3CH3_CAPTURE_VAL; 为定时器库里预定义变量,分别指代TIM3通道3的捕获状态寄存器和计时器捕获时间寄存器 void Read_Distane(void) { PBout(1)=1; delay_us(15); PBout(1)=0; if(TIM3CH3_CAPTURE_STA&0X80) //成功捕获到一次高电平 { Distance=TIM3CH3_CAPTURE_STA&0X3F; Distance*=65536; //溢出时间总和 Distance+=TIM3CH3_CAPTURE_VAL; //得到总的高电平时间 Distance=Distance*170/1000; TIM3CH3_CAPTURE_STA=0; //开启下一次捕获 } } (6)打开timer.h,编写函数声明 #ifndef __TIMER_H #define __TIMER_H #include 《sys.h》 void TIM3_Cap_Init(u16 arr,u16 psc); void Read_Distane(void); void TIM3_IRQHandler(void); #endif 第三步 编写main.c文件 (7)将工程编译需要用到的头文件包含进来,并预定义显示函数和全局变量。 #include “timer.h” //包含定时器函数头文件 #include “sys.h” //包含系统头文件 #include “stm32f10x.h” //包含系统寄存器定义声明的头文件 void oled_show(void); u32 Distance; //超声波测距变量 (8)在主函数中调用延时函数、显示函数和定时器函数的初始化函数。 int main(void) { delay_init(); //延时函数初始化 OLED_Init(); //OLED初始化 TIM3_Cap_Init(0XFFFF,72-1); //超声波初始化 (9)定义主循环,在主循环中调用超声波读取函数和显示函数 while(1) { Read_Distane(); oled_show(); delay_ms(500); } (10)编写OLED显示函数 void oled_show(void) { OLED_ShowString(00,20,“Distance”); OLED_ShowNumber(95,20,Distance,4,12); //=刷新==========// OLED_Refresh_Gram(); } 第四步 编译并下载,观察实验现象 (11)本实验采用仿真器为STLink V2,将仿真器与小车相连,注意正负极不要接反,如图8所示。 图8仿真器与下载线连接图 (12)编译程序:点击如图9所示的编译按键。 图1.9 Keil编译环境下的编译按键 当编译完成后,如果没有问题,Build Output栏会出现无错误、无警告的提示,如图10所示。 图10 编译通过后Build Output栏提示信息 (13)下载程序:点击如图所示的下载按键,程序就会下载到STM32的芯片中。下载按键如图11所示。 图11 Keil编译环境下的下载按键 (14)观察实验现象,OLED显示屏上显示出当前超声波传感器测量的距离信息,改变超声波传感器与墙面的距离,观察数值的变化。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1792 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1626 浏览 1 评论
1094 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
732 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1682 浏览 2 评论
1943浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
740浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
577浏览 3评论
600浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
562浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 12:24 , Processed in 0.918847 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号