这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 使用Timer的输入捕获实现超声波测量

共1条 1/1 1 跳转至

使用Timer的输入捕获实现超声波测量

院士
2026-02-17 23:24:40   被打赏 50 分(兑奖)     打赏

今天帖子的主题是Timer的输入捕获的一个典型应用。实例来源为超声波测距模块HC SR-04的测距应用。

超声波测距模块HC SR-04(下文简写SR-04)是我们在DIY时常用的一个测距模块,其稳定,可靠,价格便宜都是它的优势,当然,它还有其它一些特性,这里不做过多介绍,请参看论坛网友keyboard007的帖子《NUCLEO-U083RC学习历程36+使用超声波模块制作实现测量距离》https://forum.eepw.com.cn/thread/393964/1。从其帖子里面可以学习整个超声波测距模块实现过程,本文仅改进其测量SR-04的高电平的实现。

从网友keyboard007的帖子里面测距公式

距离(m)=高电平持续时间(s)*声速(340m/s)/2

我们得出来以下有关SR-04的测距精度的计算,即1秒为170米,1ms => 17mm,1us => 0.017mm。考虑到SR-04的测量精度,如果把高电平的计量精度定位在us级,则完全满足SR-04的精度。为了后期的分频与计算方便,我们先简单按Timer输入捕获的tick的间隔为1us,即我们可以简单的理解10个tcik数值对应测距为0.17mm。

对于SR-04的精度我们确认完毕,我们再来看看其最大量程。按帖子内容,可以知道SR-04的如果超过最大量程其高电平为33ms。如上所取值,如果一个tick为1us,则如果按16位计数器设置下65535计数溢出后应为65ms左右,满足我们测量33ms的需求。故,我们将Timer的tick的周期暂定为1us。

在梳理完成SR-04的原理后,我们再来看看STM32H503的性能。STM32H503为ST公司推出的一颗基于ARM公司Cortex-M33 32位RISC内核的高性能微控制器,工作频率高达250MHz。Cortex-M33核心具有一个单精度浮点单元(FPU),支持所有Arm单精度数据处理指令和所有数据类型。Cortex-M33核心还实现了一整套DSP(数字信号处理)指令和内存保护单元(MPU),增强了应用程序的安全性。该设备嵌入高速存储器(128kbytes的双bank闪存和32kbytes的SRAM),以及连接到3个APB总线、3个AHB总线和32位多AHB总线矩阵的大量增强型I/ o和外设。该器件具有多种针对嵌入式闪存和SRAM的保护机制:安全生命周期管理、写保护和隐藏保护区域。

该设备嵌入了几个增强安全性的外设:一个哈希硬件加速器和一个真正的随机数发生器。该设备提供主动篡改检测,并对瞬态和环境扰动攻击提供保护。

该器件提供一个快速的12位ADC,两个DAC通道,一个运放,一个比较器,一个低功耗RTC,一个32位通用定时器,一个16位PWM定时器专用于电机控制,一个16位通用定时器,两个16位基本定时器和两个16位低功耗定时器。该设备还具有标准和先进的通信接口,如:2个I²C, 2个i3c与I²C共享,3个spi与muxed全双工I2S, 3个USARTs和1个低功耗UART, 1个FDCAN, 1个USB全速。

STM32H503的TIM2为通用定时器,其具有32位的自助装载寄存器和32位分频器。几乎可以得到任意频率的输入和输出。而我们今天也是使用TIM2来做为频率捕获的输入测量Timer。我们使用STM32CubeMX图形化配置工具软件来配置TIM2。如下图所示:

timer_capture.jpg

配置完成Timer2的配置参数,我们再来看看我们的实现方案:

timer_capture02.jpg

我们要测量的高电平时间长度就是T1到T2的时长。我们配置定时器工作在递增计数模式,首先设置定时器通道为上升沿捕获,这样在T1时刻上升沿到来时,就会发生捕获事件。这里我们还会打开捕获中断,所以捕获事件发生就意味着捕获中断也会发生。在捕获中断里将计数器值清零,再设置通道为下降沿捕获,这样T2时刻下降沿到来时,就也会发生捕获事件和捕获中断。捕获事件发生时,计数器的值会被锁存到捕获/比较寄存器CCR1寄存器中。那么在捕获中断里,我们读取捕获/比较寄存器就可以获取到高电平脉冲时间内,计数器计数的个数,从而可以算出高电平脉冲的时间。

TIM2的初始化配置如下:

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 249;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 4294967295;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 3;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

我们仍然需要在Tim2的中断回调函数里面重新配置TIM2的触发电平为下降沿触发。这部分代码与上升沿代码相同,这里不再重复上传。

由于在上升沿边沿触发时,我们清空了TIM2的计数器的值,故在下降沿触发的时候其计数值即为高电平的tick数值。我们只需要将其回读出来,并代入上一章的公式即可计算出来超声波距离的数值。

实验代码就这么完成了吗?

如果我们仅仅是做个实验,一个DIY,上述代码可以完成,提交代码了。但我们仍然要多思考一下。上面的应用场景是是假设定时器没有溢出为前提的。实际上,t1到2时间段,定时器可能会产生N次溢出,这就需要我们对定时器溢出做相应的处理,防止高电平太长,导致测量出错。

在t1到t2时间段,假设定时器溢出N次,那么高电平脉冲时间内,计数器计数的个数计算方法为:N*(ARR+1)+CCRx2,CCRx2表示t2时间点,捕获/比较寄存器的值。经过计算得到高电平脉宽时间内计数器计数个数后,用这个个数乘以计数器的计数周期,就可得到高电平持续的时间。就是输入捕获测量高电平脉宽时间的整个过程。

写在最后

读到这里,细心的网友,或者正在复刻的网友会发现,其实STM32H503的输入捕获功能支持双边沿触发功能。我们只需要在触发中断里面回读一下边沿状态即可完成对应的事件处理,而不再需要重新配置TIM2的触发方式。这里我的目的在于对于普通MCU来说,其仅有边沿触发时,需要经过上述处理过程,如果有双边沿触发,我们就直接使用硬件的双边沿触发即可。简单才是可靠,越复杂,越容易出错。

最后,祝各位网友们马年吉祥!









关键词: Timer     输入     捕获     超声波    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]