IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32应用(五)基于输入捕获的超声波HC-SR04模块使用 -> 正文阅读

[嵌入式]STM32应用(五)基于输入捕获的超声波HC-SR04模块使用

1.输入捕获

原子哥的输入捕获实验

1.1 输入捕获原理

输入捕获模式可以用来测量脉冲宽度或者测量频率。 我们以测量脉宽为例,用一个简图来说明输入捕获的原理,如图:
在这里插入图片描述
输入捕获测量高电平脉宽的原理,假定定时器工作在向上计数模式,图中 t1~t2 时间,就是我们需要测量的高电平时间。
测量方法如下:首先设置定时器通道 x 为上升沿捕获,这样,t1 时刻,就会捕获到当前的 CNT 值,然后立即清零 CNT,并设置通道 x为下降沿捕获,这样到 t2 时刻,又会发生捕获事件,得到此时的 CNT 值,记为 CCRx2。 这样,根据定时器的计数频率,我们就可以算出 t1~t2 的时间,从而得到高电平脉宽。
在 t1~t2 之间,可能产生 N 次定时器溢出,这就要求我们对定时器溢出,做处理,防止高电平太长,导致数据不准确。如图所示, t1~t2之间, CNT计数的次数等于: N*ARR+CCRx2,有了这个计数次数,再乘以 CNT 的计数周期,即可得到 t2-t1 的时间长度,即高电平持续时间。

1.2 摘自【STM32】HAL库 STM32CubeMX教程八—定时器输入捕获

链接摘自【STM32】HAL库 STM32CubeMX教程八—定时器输入捕获

输入捕获的工作流程(对应CubeMx的四个选项)
在这里插入图片描述

1.设置输入捕获滤波器
STM32在很多功能中都提供了滤波器,滤波器的功能简单来说就是多次检测视为一次有效,达到滤波效果,
数字滤波器由一个事件计数器组成,假设我们是检测高电平,滤波N次,那么记录到N个事件后计数器会产生一个输出的跳变。也就是说连续N次采样检测,如果都是高电平,则说明这是一个有效的电平信号,这样便可以过滤掉那些因为某些而干扰产生的一些信号
输入捕获滤波器IC1F[3:0],这个用于设置采样频率和数字滤波器长度。其中:fCK_INT是定时器的输入频率,fDTS是根据TIMx_CR1的CKD[1:0]的设置来确定的。
2.设置输入捕获极性
设置具体为那种捕获事件
可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获
3.设置输入捕获映射关系
STM32为了更好的优化使用,TIMx_CH1通道1捕捉到的信号可以传输到IC1,TIMx_CH1捕捉到的信号也可以连接到IC2,TIMx_CH2捕捉到的信号也可以连接到IC2,也可以连接到IC2

在这里插入图片描述
4.设置输入捕获分频器
设置每N个事件触发一次捕获,可以设置为1/2/4/8次检测到电平变化才触发捕获

1.3 原理总结

STM32F4 的输入捕获,简单的说就是通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值( TIMx_CNT)存放到对应的通道的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。

1.4 配置工程和编写代码

在这里插入图片描述

这里我们选择TIM5的通道1

预分频系数为71
计数时钟频率就是 72MHz/(71+1) = 1MHz 此时1us计数一次
自动加载值设置为16bit最大值
上升沿捕获
不分频
滤波值为8
同时在NVIC一栏使能TIM5的中断

开启串口1。
在这里插入图片描述

/* USER CODE BEGIN PV */
uint32_t capture_Buf[3] = {0};   //存放计数值
uint8_t capture_Cnt = 0;    //状态标志位
uint32_t high_time;   //高电平时间
/* USER CODE END PV */
//while中函数
switch (capture_Cnt)
{
	case 0:
		capture_Cnt++;
		__HAL_TIM_SET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
		HAL_TIM_IC_Start_IT(&htim5, TIM_CHANNEL_1);	//启动输入捕获       
		break;
	case 3:
		high_time = capture_Buf[1]- capture_Buf[0];    //高电平时间
		HAL_UART_Transmit(&huart1, (uint8_t *)high_time, 1, 0xffff);   //发送高电平时间
		HAL_Delay(1000);   //延时1S
		capture_Cnt = 0;  //清空标志位
		break;
}


/* USER CODE BEGIN 4 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	
	if(TIM5 == htim->Instance)//定时器5的中断
	{
		switch(capture_Cnt){
			case 1:
				capture_Buf[0] = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);//获取当前的捕获值.
				__HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);  //设置为下降沿捕获
				capture_Cnt++;
				break;
			case 2:
				capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);//获取当前的捕获值.
				HAL_TIM_IC_Stop_IT(&htim5,TIM_CHANNEL_1); //停止捕获   或者: __HAL_TIM_DISABLE(&htim5);
				capture_Cnt++;    
		}	
	}
}
/* USER CODE END 4 */

1.5 原理分析和现象观察

1.原理分析:
代码逻辑:摘自【STM32】HAL库 STM32CubeMX教程八—定时器输入捕获

硬件逻辑:
定时器5的输入捕获通道一对应的GPIO是PA0-WKUP。
在这里插入图片描述

而开关摁下后,是一个上升沿。松开时,是一个下降沿,结合代码逻辑,很容易理解。测试的是摁键摁下的时间。
在这里插入图片描述

在这里插入图片描述
按下KEY_UP。

在这里插入图片描述

1.6 输入捕获函数补充

在这里插入图片描述

1.7 代码分享

输入捕获实验 提取码:3ozl

2.超声波HC-SR04模块

参考博客:STM32CubeMX | 39-使用硬件定时器获取超声波模块数据(HC-SR04)

2.1 基本工作原理

HC-SR04超声波测距模块可提供2cm- 400cm的非接触式距离感测功能,测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。
基本工作原理:
(1)采用I0口TRIG触发测距,给最少10us的高电平信呈。
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过I0口ECHO输出- -一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离= (高电平时间*声速(340M/S))/2;
在这里插入图片描述
知道d和L,勾股定理就能算出S。

2.2 实物图和接线

在这里插入图片描述

void HC_SR04_Init(hc_sr04_device_t *hc_sr04_device)
{
    // the gpio and tim is initialized in main
  hc_sr04_device1.trig_port = GPIOB;
  hc_sr04_device1.trig_pin  = GPIO_PIN_8;
  hc_sr04_device1.echo_port = GPIOB;
  hc_sr04_device1.echo_pin  = GPIO_PIN_9;
  hc_sr04_device1.tim       = &htim2;
}

这里我设置的Trig和Echo分别为PB8,PB9。

HC-SR04超声波模块STM32
VCC5V(必须是5V)
GNDGND
Trig触发控制信号输入PB8
Echo回响信号输出PB9

2.3 超声波时序图

在这里插入图片描述
以上时序图表明你只需要提供一一个 10uS以上脉冲触发信号,该模块内部将发出8个40kHz周期电平并检测回波。一旦检测到有回波信号则输出回响信号。
回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。公式: uS/58=厘米或者uS/148=英寸;或是:距离=高电平时间*声速(340M/S) /2;建议测量周期为60ms以上,以防止发射信号对回响信号的影响。

2.4 配置工程

1.配置GPIO

1)配置两个普通的GPIO,一个配置为输出模式,用于连接模块的Trig引脚,触发一次测距,这里我配置为PB8,另一个配置为输入模式(浮空),用于连接模块的Echo引脚,接收echo信号,这里我配置为PB9。

在这里插入图片描述
2.配置通用定时器TIM2

接下来开始配置TIM2,首先选择TIM2,我们的目的是每1us计数一次 ,所以定时器的频率需要在1Mhz, 时钟源选择内部时钟:

在这里插入图片描述
3.配置时钟树

STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz即可:

在这里插入图片描述

2.5 编写代码和分享

2.5.1printf重定向

#include "stdio.h"

int fputc(int c,FILE *stream)
{
	uint8_t ch[1]={c};
	HAL_UART_Transmit(&huart1,ch,1,0xFFFF);
	return c;
}

2.5.2 添加us级延时函数

一种Cortex-M内核中的精确延时方法
在这里插入图片描述

2.5.3 编写驱动

参考博客

int HC_SR04_Measure(hc_sr04_device_t *hc_sr04_device)
{
    uint32_t tick_us;
    
    HC_SRO4_Mutex_Pend();
    
    HC_SR04_Start(hc_sr04_device);
    
    __HAL_TIM_SetCounter(hc_sr04_device->tim, 0);
    
    /* waitting for start of the high level through echo pin */
    while (HAL_GPIO_ReadPin(hc_sr04_device->echo_port, hc_sr04_device->echo_pin) == GPIO_PIN_RESET);

    /* start the tim and enable the interrupt */
    HAL_TIM_Base_Start(hc_sr04_device->tim);
    
    /* waitting for end of the high level through echo pin */
    while (HAL_GPIO_ReadPin(hc_sr04_device->echo_port, hc_sr04_device->echo_pin) == GPIO_PIN_SET);
    
    /* stop the tim */
    HAL_TIM_Base_Stop(hc_sr04_device->tim);
    
    /* get the time of high level */
    tick_us = __HAL_TIM_GetCounter(hc_sr04_device->tim);
    
    /* calc distance in unit cm */
    hc_sr04_device->distance = (double)(tick_us/1000000.0) * 340.0 / 2.0 *100.0;
    
    HC_SRO4_Mutex_Post();
    
     return 0;
}

这个是利用定时器来实现计时的。并在while中不断执行Measure。

2.5.4测试结果

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
int ret;
extern hc_sr04_device_t hc_sr04_device1;
/* USER CODE END PV */

  /* USER CODE BEGIN 2 */
  HC_SR04_Init(&hc_sr04_device1);
 /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		ret = HC_SR04_Measure(&hc_sr04_device1);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

在监视窗口中可以看到distance的数据。单位是cm。
在这里插入图片描述
代码分享 提取码:x6sx

2.6 注意事项

1、此模块不宜带电连接,若要带电连接,则先让模块的GND端先连接,否则会影响
模块的正常工作。
2、测距时,被测物体的面积不少于0.5平方米且平面尽量要求平整,否则影响测量的
结果。

3.基于输入捕获的超声波HC-SR04模块使用

第二部分是利用定时器来实现计时的,并在while中不断执行Measure。而.基于输入捕获的超声波HC-SR04模块使用,使我们摆脱在while中重复测量。原理在输入捕获中已经讲解,直接开始吧!

3.1 配置工程

TIM2配置为10ms计数一次,看清时钟主频。
在这里插入图片描述
TIM1的通道1设置为输入捕获,每隔10us捕获一次,看清时钟主频。
在这里插入图片描述
Echo接输入捕获通道的GPIO,即PE9。
在这里插入图片描述

NVIC选项卡打开中断。
在这里插入图片描述
开启GPIO。作为Trig的输出通道,PC6。
在这里插入图片描述

3.2 代码编写

修改宏定义中的时钟主频和GPIO。

#define CPU_FREQUENCY_MHZ    168		// STM32主频 
#define SAMPLENUM 10
#define Trig(state) HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6, (GPIO_PinState)(state))  //触发引脚:改成自己设定的引脚
#define Echo 	HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_9)	//接收信号引脚,改成自己设定的引脚
#define RELOADVALUE 0xffff

详情可观看另一篇博客。(等等更)

3.3 实验观察

打开debug,观察distance。
在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:23:46  更:2021-08-09 10:24:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 1:06:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计