stm32Cubemx:定时器捕获功能实现SR04超声波测距

3 篇文章 1 订阅
1 篇文章 0 订阅

概述

        下面是讲解使用ST MCU中的HAL库来实现,超声波测距的功能。

1、MCU主控:

STM32L052C8T6

2、超声波模块:

SR04

基本工作原理: 
1、采用IO口TRIG触发测距,给至少10us的高电平信号; 
2、模块自动发送8个40khz的方波,自动检测是否有信号返回; 
3、有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;

本模块使用方法简单,一个控制口发一个10US以上的高电平,就可以在接收口等待高电平输出.一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离.如此不断的周期测,即可以得到你移动测量的值。超声波模块时序图如下: 

3、输入捕获简介

输入捕获可以用来测量脉冲宽度或者测量频率。超声波用到的是测量脉宽,这里我以测量脉宽为例,用一个简图来说明输入捕获的原理,如下图: 

如上图所示,就是输入捕获测量高电平脉宽的原理,假定定时器工作在向上计数模式,图中t1-t2时间,就是我们需要测量的高电平时间。测量方法如下:首先设置定时器通道x为上升沿捕获,这样,t1时刻就会捕捉到CNT值,然后立即清零CNT,并设置通道x为下降沿捕获,这样t2时刻又会发生捕获事件,得到此时的CNT值,记为CCRx2。这样,根据定时器的计数频率,我们就可以算出t1-t2的时间,从而得到高电平的脉宽。

在t1-t2之间,可能产生N次定时器溢出,这就要求我们对定时器溢出做处理,防止高电平太长,导致数据不准确。如上图所示,t1-t2之间CNT计数的的次数等于:N*ARR+CRRx2,有了这个计数次数,再乘以CNT的计数周期,即可得到t1-t2的时间长度,即高电平持续时间。

4、STM32CubeMx 配置

1)系统时钟配置(这里不做介绍,前查看以往教程)

 

2)定时器21配置

 

5、代码说明:

 

1)、tim.c文件


/* Includes ------------------------------------------------------------------*/
#include "tim.h"

/* USER CODE BEGIN 0 */
#include "gpio.h"
#include "stdio.h"
 
uint8_t   text_flag = 0;
uint8_t   dis_fm = 0;
uint8_t   Channel1Edge = 0;
uint16_t  Channel1HighTime, Channel1RisingTime, Channel1FallingTime;

/* USER CODE END 0 */

/* USER CODE BEGIN 1 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
  /*防止未使用参数(s)编译警告*/
	UNUSED(htim);
 
	if(htim->Instance == htim21.Instance)
	{
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
		{
			if(Channel1Edge == 0)          //捕获上升沿
			{
				Channel1RisingTime = HAL_TIM_ReadCapturedValue(&htim21, TIM_CHANNEL_1);                         //获取上升沿开始时间点
				__HAL_TIM_SET_CAPTUREPOLARITY(&htim21, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);        //切换捕获极性
				HAL_TIM_IC_Start_IT(&htim21, TIM_CHANNEL_1);     //切换捕获极性后需重新启动
 
				Channel1Edge = 1;          	 //上升沿、下降沿捕获标志位
			}
			else if(Channel1Edge == 1)     //捕获下降沿
			{
				Channel1FallingTime = HAL_TIM_ReadCapturedValue(&htim21, TIM_CHANNEL_1);                       //获取下降沿时间点
				__HAL_TIM_SET_CAPTUREPOLARITY(&htim21, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);        //切换捕获极性
				HAL_TIM_IC_Start_IT(&htim21, TIM_CHANNEL_1);   	 //切换捕获极性后需重新启动
 
				Channel1HighTime = Channel1FallingTime < Channel1RisingTime ? Channel1FallingTime + 0xffff - Channel1RisingTime + 1 : Channel1FallingTime - Channel1RisingTime;
				//高电平持续时间 = 下降沿时间点 - 上升沿时间点
				dis_fm = Channel1HighTime * 17 / 100; //计算超声波测量距离
                printf("dis_fm = %dcm \r\n", dis_fm);
                if(dis_fm<30) Beep_on;
                else  Beep_off;
				//i++;//累加计数
				Channel1Edge = 0;		  			 //一次采集完毕,清零
			}
			HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
		}
	}
}

/* USER CODE END 1 */

3)、main.c文件



/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "task.h"
#include "stdio.h"
/* USER CODE END Includes */



/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */



int main(void)
{
  /* USER CODE BEGIN 1 */
   static uint8_t Flag=0;
  

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_TIM2_Init();
  MX_TIM21_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  Moter_StartPWM();
  	OLED_Init();
	OLED_Clear(); 
	OLED_ShowString(0,0,"www.taxing.com",16);
	OLED_ShowCHinese(0,4,0);//
	OLED_ShowCHinese(16,4,1);//
	OLED_ShowCHinese(32,4,2);//
	OLED_ShowCHinese(48,4,6);//
	OLED_ShowCHinese(0,6,3);//
	OLED_ShowCHinese(16,6,4);//
	OLED_ShowCHinese(32,6,5);//
	OLED_ShowCHinese(48,6,6);//
    HAL_TIM_IC_Start_IT(&htim21, TIM_CHANNEL_1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      #if 0
     if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==1&&Flag==0)
     {
        HAL_Delay(100);
        if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==1)
        {
           Car_Track();
           Flag=1;
        }
     }

    else
    {
       Moter_off();
    }
    #endif
  
    Trig_On;
    HAL_Delay(1);
    Trig_Off;
 
  HAL_Delay(100);
  
  }

  /* USER CODE END 3 */
}

别忘了打开定时器21的总中断哦

基本配置完成,打开串口助手即可看到打印距离信息

 

 

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值