STM32 等精度测频 TIM定时器 分高低频测试

这篇具有很好参考价值的文章主要介绍了STM32 等精度测频 TIM定时器 分高低频测试。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

记录一下STM32稍显艰难的学习过程、、

使用的STM32开发板:微雪的Open407Z

相关资料:Open407Z-C - Waveshare Wiki

MCU型号:STM32F407ZE

本次想要实现一个单片机学习中很普遍也很简单的测频功能,但是实操起来还得进行很多定时器的以及中断的相关操作。。

/****以下为仅使用一个定时器进行捕获的代码,效果较差,可略过****/

首先想到的是用一个定时器进行输入捕获进行测频。本人想偷懒,于是沿用MSP430的那一套逻辑。(MSP430相关部分详细见下链接)

MSP430G2553 频率、占空比、脉冲宽度测量_Krism0912的博客-CSDN博客_msp430测量频率

但是实际效果并不理想,测量的误差非常大,尽管如此,仍然放出一部分代码供参考。

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
		
 if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)== GPIO_PIN_SET)
			{
				if(Forward_Posedge_Flag)//First rising edge captured
				{
					TIM3->CNT=0;
					Forward_Posedge_Flag = 0;
				}
				else if(Forward_Posedge_Flag ==0 && Negedge_Flag==1) 
                                                //Second rising edge captured
				{
						HAL_TIM_Base_Stop_IT(&htim3);
						HAL_TIM_IC_Stop_IT(&htim3, TIM_CHANNEL_2);
					
						Posedge_data=TIM3->CCR2;
					
						Posedge_data=Posedge_data+50000*(num1+num2);
						Negedge_data = Negedge_data+ 50000*num1;
						fre = 2000000.0 / Posedge_data ;
						duty_cycle = ((double)Negedge_data )/ ((double)Posedge_data);
						pulse_width = ( (double)Negedge_data) / 2.0 ; //unit:us

						LCD_Display();
						HAL_Delay(800);
					
						Parameter_Init();


						HAL_TIM_Base_Start_IT(&htim3);
						HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
				}
			}
			else // Falling Edge was captured
			{
					if(Forward_Posedge_Flag==0 && Negedge_Flag==0)
					{
							Negedge_data = TIM3->CCR2;
							Negedge_Flag = 1;
					}
			}
}

通过设置TIM3的CHANNEL2进行输入信号的双边沿捕获,以期计算频率和占空比。

上述代码中判断上升沿和下降沿,在if中用的判断语句是

HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)== GPIO_PIN_SET

感觉实际上STM32的寄存器里面应该有捕获信号极性的相关寄存器位,但是我暂时没找到。

测量结果不太理想,10kHz会测得10200Hz之类。

P.S信号源升级了,精度绝对没有问题。

无奈,尝试使用等精度测频法。

/******************************以下为等精度测频法**************************/

等精度测频法以前试过在FPGA和MSP430上试过一段时间(见以前的博客),但是这次还是打算从零开始配置。

本次使用的等精度测频法的时序逻辑如下:

(1)在捕捉到一个输入信号上升沿后开启测量闸门(软件闸门);

(2)开启后测量一段时间的信号,且自定义测量的最短时间,该时间硬件闸门控制;

(3)硬件闸门时间到后,硬件闸门关闭,但相关计数器仍继续工作,测量继续,直至捕获到下一个输入信号上升沿后,结束测量并锁存数据;

(4)测量结束后计算相关数据,重新初始化各个参数,准备进行下一次测量。

等精度测量法最为重要的就是一定要使测量时间为被测信号的周期的整数倍,这样才能保证精度。如此一来,实际的测量时间将与实际输入信号的频率有关,更多相关细节网上有很多,这里不再说了。

最终测量将会获得标准信号计数值Nx和被测信号计数值Nb,由此算得实际信号频率。

参考以上步骤,选取STM32定时器资源:

一个定时器用于控制闸门信号(最小测量时间),该定时器只需要实现一个定时功能,定时到后进入中断处理事件置位某个flag标志,以在下一个上升沿结束测量;

一个定时器用于计数标准信号Nx,使用输入捕获功能,捕获到一个上升沿时加1即可;

一个定时器用于计数标准信号,这里标准信号来自于内部时钟,故也仅需普通计数器模式即可,也不需要中断。

总配置:

定时器 模式 Prescaler Counter Period Global Interrupt
TIM2 \ 0 0xFFFFFFFF ×
TIM3(CH2) Input capture direct mode 84-1 0
TIM5 \ 8400-1 10000-1

说明:

基于stm32定时器实现频率量高精度测量,stm32,单片机

TIM2的 Counter Period到32位 (2^32-1>4290M),而TIM2的时钟频率最大为84M,计数值完全够用。如果您的位数不够用可以考虑打开Global Interrupt,设置一个总计数器,在溢出中断里加上Period的值即可。

基于stm32定时器实现频率量高精度测量,stm32,单片机

TIM3 CHANNEL2 为输入捕获模式,不需要设置Counter Period,当然 Prescaler也应该可以随便设置一下。输入的极性设置为上升沿(下降沿也同理)。

基于stm32定时器实现频率量高精度测量,stm32,单片机

 TIM5采用最简单的设置,只需对其分频即可。

基于stm32定时器实现频率量高精度测量,stm32,单片机

 考虑到TIM5挂在APB1总线上,时钟频率为84MHz,则分频后硬件闸门频率为:

                                                  84M/8400/10000=1Hz

也就是最小测量时间在这里设置成了1s。您完全可以更改上述参数设置您需要的时长。

接下来是代码部分,main.c见下

/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  *
  * COPYRIGHT(c) 2022 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
#include "tim.h"
#include "gpio.h"
#include "fsmc.h"

/* USER CODE BEGIN Includes */
#include "openx07z_c_lcd.h"
#include "Myfunction.h"
#include "Fre_function.h"
/* USER CODE END Includes */

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

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
 

uint16_t GATE_OPEN,GATE_READY2CLOSE;
uint32_t Nx,Nb;

double fre;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

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

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

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

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_FSMC_Init();
  MX_TIM3_Init();
  MX_TIM2_Init();
  MX_TIM5_Init();

  /* USER CODE BEGIN 2 */
	///LCD SIZE 320*240
  BSP_LCD_Init();
  BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
  BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
  BSP_LCD_SetFont(&Font20);
  BSP_LCD_Clear(LCD_COLOR_WHITE);
  Parameter_Init();
  BSP_LCD_DisplayStringAt(0, 0, (uint8_t *)"Ready to measure", CENTER_MODE );

  HAL_Delay(1000);
	

  HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);    //启动输入捕获
  /* USER CODE END 2 */

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

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Configure the main internal regulator output voltage
    */
  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }

    /**Configure the Systick interrupt time
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USER CODE BEGIN 4 */
//输入中断触发的回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{

	if(!GATE_OPEN) //闸门未开启,捕获到上升沿信号后应该开启闸门以开始测量
	{
		//启动闸门 TIM5 开始计数标准信号
//		HAL_TIM_Base_Start(&htim5);
		__HAL_TIM_CLEAR_IT(&htim5, TIM_IT_UPDATE);
		HAL_TIM_Base_Start_IT(&htim5);
		HAL_TIM_Base_Start(&htim2);
		GATE_OPEN=1;
	}
	else
	{
		//测频中,捕捉到一次信号 输入计数值加1
		Nx++;
	}
	
	if(GATE_OPEN&&GATE_READY2CLOSE)
	{
		//关闭闸门 停止捕捉 
		
		HAL_TIM_Base_Stop(&htim2);
		HAL_TIM_IC_Stop_IT(&htim3, TIM_CHANNEL_2);
		HAL_TIM_Base_Stop_IT(&htim5);
		//锁存Nx Nb数据 计算频率值 LCD显示
		
		Nb=__HAL_TIM_GetCounter(&htim2); //		或者 Nb=TIM2->CNT;
		fre=((double)Nx)/((double)Nb)*84000000.0;
		HAL_Delay(500);
		LCD_Display();
		
		//准备下一次测量
		Parameter_Init();
		__HAL_TIM_SetCounter(&htim2,0);  //注意!!!!!!!计数值不会因为定时器暂停而清零
		HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);    //启动输入捕获
		
	}
	
}   

/**
  * @brief  Period elapsed callback in non blocking mode
  * @param  htim: TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	//TIM5溢出, 1s测量时间到,下一个输入信号上升沿将结束测量
		if(TIM5 == htim->Instance)
    {
			GATE_READY2CLOSE=1;
    }

}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler */
  /* User can add his own implementation to report the HAL error return state */
  while(1) 
  {
  }
  /* USER CODE END Error_Handler */
}

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

/**
  * @}
  */

/**
  * @}
*/

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

完完全全按照自己设想的逻辑写代码即可,并不复杂。

有一点稍微注意一下:停止TIM2获取Nb值后需要将CNT值清零,因为HAL_TIM_Base_Stop(&htim2); 并不会清零该值。

/********************下面部分与测频无关,不看也可*********************/

计划用LCD显示数据。

对于320*240的TFT液晶显示器,官方资料里有很多函数可以拿来直接用,全在openx07z_c_lcd.c文件里。而且根据其中基本函数,也可以自己造一些简单的功能函数。

比如在指定位置显示一个指定位数的双精度浮点数:

void BSP_LCD_Show_double(uint16_t x,uint16_t y,double f,int n);

#include "stm32f4xx_hal.h"
#include "openx07z_c_lcd.h"
#include "Myfunction.h"
#include "../Fonts/fonts.h"

extern LCD_DrawPropTypeDef DrawProp;

//x,y是坐标;f是要显示的数字,n是展示的小数位数 
void BSP_LCD_Show_double(uint16_t x,uint16_t y,double f,int n)
{
    unsigned int temp,i,j;
    uint16_t num[10];  //预留的存储空间,不够时更改即可
	  uint16_t size;
	
// 按我自己的喜好调整的字符间隔。可更改。 
		switch(DrawProp.pFont->Width)
		{
			case 17:case 14:case 11:size=DrawProp.pFont->Width -3; break; //Font24,Font20,Font16
			case 7: size=DrawProp.pFont->Width -2; break;  //Font12;
			case 5: size=DrawProp.pFont->Width; break;  //Font8;
			default:size=DrawProp.pFont->Width;
		}
        temp = (int)f;
        if(temp!=0)
        {
            for(i=0;temp!=0;i++)      //计算整数位数
                temp /=10;
            temp = (int)f;
					
            for(j=i;j>0;j--)
            {
                num[j] = temp%10+'0';
                temp /=10;
            }
						
            for(j=1;j<=i;j++)           //依次展示
            {
                BSP_LCD_DisplayChar(x,y,num[j]); 
								x+=size;
            }
        }
        else
        {
            BSP_LCD_DisplayChar(x,y,'0'); 
				   	x+=size;
        }


        BSP_LCD_DisplayChar(x,y,'.'); x+=size;   

        f -=(int)f;
        for(i=0;i<n;i++)
        {
            f*=10;
            BSP_LCD_DisplayChar(x,y,(int)f+'0'); x+=size;  
            f-=(int)f;
        }
}

当然上述功能也可以直接通过sprintf函数实现,想怎么用就怎么用。 

/****************************下面是测试效果*********************************/

0.5Hz

基于stm32定时器实现频率量高精度测量,stm32,单片机

1Hz

基于stm32定时器实现频率量高精度测量,stm32,单片机

 50kHz  500kHz

测试的频率范围:0.5Hz-500kHz

测量误差在0.02% (万分之二)左右 

/**************************************END**********************************/

/********************************更新**********************************/

/***************************高频测量部分***************************/

  上述等精度测频方法,由于使用了定时器的捕获功能,捕获到输入信号上升沿时需要进入中断将Nx的值进行加一操作,而本身进入中断进行处理就会需要执行大量语句,进而耗费大量的时间和资源,从而当频率过高时,需要进入中断的次数过多,无法完成测频功能,如上所述,上限约为500kHz。

今日有幸了解到,将待测信号作为外部时钟输入,可以在不进入中断的情况下对其进行计数,有机会测量更高的频率。

首先先看看该方法能否测高频。

将TIM3原有的的输入捕获设置进行更改,并将其从模式设置为外部输入时钟模式1

基于stm32定时器实现频率量高精度测量,stm32,单片机

基于stm32定时器实现频率量高精度测量,stm32,单片机 具体设置:不分频(Prescaler=0);

                   CounterPeriod设置为0xFFFF(65535);

                    上升沿触发;

此外,输入通道将为TIM3的CHANNEL_1;

基于stm32定时器实现频率量高精度测量,stm32,单片机

上图来自:DS8626: Arm® Cortex®-M4 32b MCU+FPU, 210DMIPS, up to 1MB Flash/192+4KB RAM, USB OTG HS/FS, Ethernet, 17 TIMs, 3 ADCs, 15 comm. interfaces & camera

Pinouts and pin description 部分 

基于stm32定时器实现频率量高精度测量,stm32,单片机

 上图来自:RM0090 中文参考手册 通用定时器框图

剩余两个定时器仍保持原样,不做更改(即TIM2:计数基频值Nb,TIM5控制闸门时间为1s)。

由于是高频,实际采样时间完全可以设置为1s。

比如:高频时1秒计数值Nx约为500k,等精度测频会延长测频时间至测量完整的整数个待测信号整个周期,实际测频时间可能为1s*(1+1/500k)。高频时完全可以忽略该差别。但是低频就不可以咯(1Hz输入可能得测2秒)。

回到高频测量,如上所述,在TIM5的中断里即可结束整个测频过程并开始计算。这样完全抛弃了等精度测频的方法

完整代码:

/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  *
  * COPYRIGHT(c) 2022 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
#include "tim.h"
#include "gpio.h"
#include "fsmc.h"

/* USER CODE BEGIN Includes */
#include "openx07z_c_lcd.h"
#include "Myfunction.h"
#include "Fre_function.h"
/* USER CODE END Includes */

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

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
 
uint32_t Nx,Nb;

double fre;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

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

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

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

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_FSMC_Init();
  MX_TIM2_Init();
  MX_TIM5_Init();
  MX_TIM3_Init();

  /* USER CODE BEGIN 2 */
	__HAL_TIM_CLEAR_IT(&htim5, TIM_IT_UPDATE);
	__HAL_TIM_CLEAR_IT(&htim3, TIM_IT_UPDATE);
    BSP_LCD_Init();
    BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
    BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
	BSP_LCD_SetFont(&Font20);
    BSP_LCD_Clear(LCD_COLOR_WHITE);
	Parameter_Init();
	BSP_LCD_DisplayStringAt(0, 0, (uint8_t *)"Ready to measure", CENTER_MODE );
	HAL_Delay(1000);
	

//  HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);    //启动输入捕获
	HAL_TIM_Base_Start_IT(&htim5);
	HAL_TIM_Base_Start_IT(&htim3);
	HAL_TIM_Base_Start(&htim2);
  /* USER CODE END 2 */

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

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Configure the main internal regulator output voltage
    */
  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }

    /**Configure the Systick interrupt time
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USER CODE BEGIN 4 */


/**
  * @brief  Period elapsed callback in non blocking mode
  * @param  htim: TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	//规定1s测量时间到
		if(TIM5 == htim->Instance)
    {
			
			HAL_TIM_Base_Stop_IT(&htim5);
			HAL_TIM_Base_Stop_IT(&htim3);
			HAL_TIM_Base_Stop(&htim2);
			Nx+=TIM3->CNT;
			Nb=TIM2->CNT;
			fre=((double)Nx)/((double)Nb)*84000000.0;
			LCD_Display();			
	        Parameter_Init();
	  	__HAL_TIM_SetCounter(&htim2,0);  //注意!!!!!!!计数值不会因为定时器暂停而清零
		__HAL_TIM_SetCounter(&htim3,0);  //注意!!!!!!!计数值不会因为定时器暂停而清零

			
			HAL_TIM_Base_Start_IT(&htim5);
			HAL_TIM_Base_Start_IT(&htim3);
			HAL_TIM_Base_Start(&htim2);
    }
		else if(TIM3 == htim->Instance)
    {
			Nx+=0xFFFF;
    }

}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler */
  /* User can add his own implementation to report the HAL error return state */
  while(1) 
  {
  }
  /* USER CODE END Error_Handler */
}

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

/**
  * @}
  */

/**
  * @}
*/

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

说明:

1.TIM3是16位的,高频计数Nx时可能不够值,所以在TIM3的溢出中断里及时更新Nx的值(虽然还是进中断了,但是次数变成了原来的1/65535,测试情况完全可以接受)。对于此,如果您使用TIM2,那么32位计数将完全够用。

2.开头带BSP的函数以及LCD_Display()仍然是LCD显示相关函数,可以不用care。

3.不要忘记开NVIC全局中断!!

测试效果还可以,不放图了,下面一起放。

/************************上述两种方法结合************************/

如上所述,高频部分测低频不准,低频部分测不了高频。既然做了以上工作,遂想方设法将其结合。

有一点小小说一下:咱们不可能说低频测试的时候效果OK,高频不行了,把输入信号手动换到高频的输入引脚去,之后测低频又换回来。这种比较麻烦,而且一般设计会避免这种问题。

所以,等精度测频时TIM3的输入捕获将为CHANNEL_1,与高频测量保持一致,这样信号输入口将保持为PA6,不用换。

说是结合,但是我们看到高低频测量TIM3的配置完全不一样,就不像稍微改一个Prescaler或者CNT的值那样简单。

作者偷懒(其实是不会自己一点点设置),遂将高频部分的TIM3初始化函数复制了过来。,放到tim.c中当作用户函数用。 

基于stm32定时器实现频率量高精度测量,stm32,单片机

本来以为这样估计不行,但是居然可以。。接下来补上一些高低频率测量模式的转换逻辑就可以了。

转换逻辑很简单:给一个判断条件,抛弃当前测频结果,停止当前所有的计时器,重新配置TIM3引脚,重开计时器即可。

我设置的是10000Hz以上认为是高频,用高频方法,否则低频,用等精度测频法。

/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  *
  * COPYRIGHT(c) 2022 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
#include "tim.h"
#include "gpio.h"
#include "fsmc.h"

/* USER CODE BEGIN Includes */
#include "openx07z_c_lcd.h"
#include "Myfunction.h"
#include "Fre_function.h"
/* USER CODE END Includes */

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

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
 

uint16_t GATE_OPEN,GATE_READY2CLOSE;
uint32_t Nx,Nb;
uint8_t Fre_State=LOW_FREQUENCY;
double fre;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

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

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

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

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_FSMC_Init();
  MX_TIM2_Init();
  MX_TIM5_Init();
  MX_TIM3_Init();

  /* USER CODE BEGIN 2 */
    BSP_LCD_Init();
    BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
    BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
	BSP_LCD_SetFont(&Font20);
    BSP_LCD_Clear(LCD_COLOR_WHITE);
	Parameter_Init();
	BSP_LCD_DisplayStringAt(0, 0, (uint8_t *)"Ready to measure", CENTER_MODE );
	BSP_LCD_DisplayStringAt(0, 100, (uint8_t *)"INPUT PIN:PA6", CENTER_MODE );
	HAL_Delay(1000);
	
    HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);    //启动输入捕获
  /* USER CODE END 2 */

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

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Configure the main internal regulator output voltage
    */
  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }

    /**Configure the Systick interrupt time
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USER CODE BEGIN 4 */
//输入中断触发的回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{

	if(!GATE_OPEN)
	{
		//启动闸门 TIM5 开始计数标准信号
		__HAL_TIM_CLEAR_IT(&htim5, TIM_IT_UPDATE);
		HAL_TIM_Base_Start_IT(&htim5);
		HAL_TIM_Base_Start(&htim2);
		GATE_OPEN=1;
	}
	else
	{
		//测频中,捕捉到一次信号 输入计数值加1
		Nx++;
		if(Nx>20000)  
		{
			HAL_TIM_Base_Stop(&htim2);
			HAL_TIM_IC_Stop_IT(&htim3, TIM_CHANNEL_1);
			HAL_TIM_Base_Stop_IT(&htim5);
			Turn2HIGH_FREQUENCY_MODE();
		}
	}
	
	if(GATE_OPEN&&GATE_READY2CLOSE)
	{
		//关闭闸门 停止捕捉 
		HAL_TIM_Base_Stop(&htim2);
		HAL_TIM_IC_Stop_IT(&htim3, TIM_CHANNEL_1);
		HAL_TIM_Base_Stop_IT(&htim5);
		//锁存Nx Nb数据 计算频率值
		Nb=__HAL_TIM_GetCounter(&htim2); 
		fre=((double)Nx)/((double)Nb)*84000000.0;
		//判断
		if(fre<10000.0)
		{
		  	    // LCD显示
				LCD_Display();
				//准备下一次测量
				Parameter_Init();
				__HAL_TIM_SetCounter(&htim2,0);  //注意!!!!!!!计数值不会因为定时器暂停而清零
				HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);    //启动输入捕获
		}
		else
		{
			Turn2HIGH_FREQUENCY_MODE();
		}
	}
	
}   

/**
  * @brief  Period elapsed callback in non blocking mode
  * @param  htim: TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	//闸门溢出 规定测量时间到
		if(TIM5 == htim->Instance&&Fre_State==LOW_FREQUENCY)
    {
			GATE_READY2CLOSE=1;
    }
		else if(TIM5 == htim->Instance&&Fre_State==HIGH_FREQUENCY)
    {
			HAL_TIM_Base_Stop_IT(&htim5);
			HAL_TIM_Base_Stop_IT(&htim3);
			HAL_TIM_Base_Stop(&htim2);
			Nx+=TIM3->CNT;
			Nb=TIM2->CNT;
	    	fre=((double)Nx)/((double)Nb)*84000000.0;
			if(Nx>=10000.0)
			{
			  LCD_Display();
	          Parameter_Init();
	  	      __HAL_TIM_SetCounter(&htim2,0);  
			  __HAL_TIM_SetCounter(&htim3,0); 

			  HAL_TIM_Base_Start_IT(&htim5);
			  HAL_TIM_Base_Start_IT(&htim3);
			  HAL_TIM_Base_Start(&htim2);
			}
			else
			{
				Turn2LOW_FREQUENCY_MODE();
			}
    }
		
		else if(TIM3 == htim->Instance&&Fre_State==HIGH_FREQUENCY)
    {
			Nx+=0xFFFF;
    }

}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler */
  /* User can add his own implementation to report the HAL error return state */
  while(1) 
  {
  }
  /* USER CODE END Error_Handler */
}

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

/**
  * @}
  */

/**
  * @}
*/

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

说明:

1.设置了变量Fre_State作为当前高频模式和低频模式的标志。

2.低频模式下,如果输入频率过高(2M左右),闸门关不了,无法算出频率并重新改成高频模式。Debug的时候发现Nx蹭蹭蹭往上涨,遂只能在捕获语句的Nx++后进行一个判断以改变模式,不然直接卡死。这是为什么作者也不明白。。。= =

3.其他一些函数见下,也许能帮助您理解作者设计的转换流程,当然您也可以自己尝试。

#include "openx07z_c_lcd.h"
#include "Myfunction.h"
#include "tim.h"
#include "Fre_function.h"
extern unsigned int Forward_Posedge_Flag,Negedge_Flag;


extern double fre;
extern uint16_t GATE_OPEN,GATE_READY2CLOSE;
extern uint32_t Nx,Nb;
extern uint8_t Fre_State;
void Parameter_Init(void)
{

	GATE_OPEN=0;
	GATE_READY2CLOSE=0;
	Nx=0;
	Nb=0;
	fre=0.0;
}

void Turn2HIGH_FREQUENCY_MODE(void)
{
		    Fre_State=HIGH_FREQUENCY;
			MX_TIM3_Init_ETR();
			
			Parameter_Init();
	  	   __HAL_TIM_SetCounter(&htim2,0);  
			__HAL_TIM_SetCounter(&htim3,0);  

			HAL_TIM_Base_Start_IT(&htim5);
			HAL_TIM_Base_Start_IT(&htim3);
			HAL_TIM_Base_Start(&htim2);
}


void Turn2LOW_FREQUENCY_MODE(void)
{
		Fre_State=LOW_FREQUENCY;
		Parameter_Init();
	    __HAL_TIM_SetCounter(&htim2,0);  
		MX_TIM3_Init();
		HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);    //启动输入捕获
}

void LCD_Display(void)
{
  		BSP_LCD_SetFont(&Font20);
        BSP_LCD_Clear(LCD_COLOR_WHITE);
	    BSP_LCD_DisplayStringAt(0, 0, (uint8_t *)"Frequency:", LEFT_MODE );
	  if(fre<10000.0)
		{
	    BSP_LCD_Show_double(150,0,fre,4);
		BSP_LCD_DisplayStringAt(280, 0, (uint8_t *)"Hz", LEFT_MODE );
		BSP_LCD_DisplayStringAt(0, 200, (uint8_t *)"LOW FREQUENCY", CENTER_MODE );
		}
		else
		{
			 BSP_LCD_Show_double(150,0,fre/1000,4);
	    	 BSP_LCD_DisplayStringAt(260, 0, (uint8_t *)"kHz", LEFT_MODE );
			 BSP_LCD_DisplayStringAt(0, 200, (uint8_t *)"HIGH FREQUENCY", CENTER_MODE );
		}
	
		BSP_LCD_Show_int(200,60,(int)Nx);
	    BSP_LCD_Show_int(200,120,(int)Nb);
	
		BSP_LCD_SetFont(&Font16);
	    BSP_LCD_DisplayStringAt(0, 30, (uint8_t *)"Input Signal Counter Nx:", LEFT_MODE );
		BSP_LCD_DisplayStringAt(0, 90, (uint8_t *)"Internal Signal Counter Nb:", LEFT_MODE );
	

}

放一些测试结果。。基于stm32定时器实现频率量高精度测量,stm32,单片机

 基于stm32定时器实现频率量高精度测量,stm32,单片机

基于stm32定时器实现频率量高精度测量,stm32,单片机

基于stm32定时器实现频率量高精度测量,stm32,单片机

 基于stm32定时器实现频率量高精度测量,stm32,单片机

目前高频测试到10MHz,低频仍然测试到0.5Hz。

本文代码有点多,有些地方留有一大堆空行,有些甚至还没对齐,但作者懒得改了。。。

感谢您读到这里,祝您生活愉快!文章来源地址https://www.toymoban.com/news/detail-616335.html

到了这里,关于STM32 等精度测频 TIM定时器 分高低频测试的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32--TIM定时器(1)

    STM32的TIM(定时器)是一种非常常用的外设,用于实现各种定时和计数功能。 它是基于时钟信号进行计数,并在计数值达到设定值时触发中断,执行相应的操作 。 一般来说,STM32中有三类定时器: 在我们这款STM32F03C9T6有4种定时器资源: TIM1,TIM2,TIM3,TIM4 ; 对于定时器,类型越

    2024年02月12日
    浏览(39)
  • STM32--TIM定时器(2)

    输出比较,简称OC(Output Compare) 。 输出比较的原理是, 当定时器计数值与比较值相等或者满足某种特定条件时,比较通道会产生一个输出信号,这个输出信号可以用来触发外部事件,如控制其他外设的操作,或者驱动外部电路 。 在每个高级定时器和通用定时器都拥有4个输

    2024年02月13日
    浏览(43)
  • STM32--TIM定时器(3)

    输入捕获IC(Input Capture),是处理器捕获外部输入信号的功能 。基于定时器抓取输入信号指定触发方式之间的长度。通过输入捕获功能,我们可以测量脉冲宽度和测量频率。 在每个高级定时器和通用器都有 4个 输入捕获通道。 当通道输入引脚出现指定电平跳变时,当前CNT的值

    2024年02月12日
    浏览(42)
  • STM32中TIM定时器定时功能详解(适用基本,通用,高级定时器)

    定时器有高级定时器、通用定时器、基本定时器三种类型。具体功能如下。 上面是每种定时器所具有的功能。 我们可以看到每种定时器都有一个定时功能,(可能是名字的由来吧)。当然,每个定时器都可以来使用定时功能,但是我们往往在基本定时器和通用定时器上面使用

    2024年01月19日
    浏览(59)
  • 【STM32】学习笔记(TIM定时器)

    定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发

    2024年02月09日
    浏览(40)
  • STM32配置TIM定时器计数

    定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中断功能,而且还包含内外时钟源的选择、输入捕获、输出比较、编码器接口、主从触

    2024年02月05日
    浏览(45)
  • STM32笔记----5、TIM定时器

    时基单元:由自动重装载寄存器、预分频器、计数器组成。 来自RCC的TIMxCLK:一般是系统的主频,72MHz。 预分频器(16位):对进来的频率进行分频,写0,不分频,输出72MHz。写1,2分频,输出36MHz。以此类推。 计数器(16位):对预分频器后的计数时钟进行计数。 自动重装载

    2024年01月22日
    浏览(74)
  • STM32定时器(TIM1、TIM2、TIM3、TIM4、TIM5、TIM8)高级定时器+普通定时器,配置使用

    2.1 时钟来源 计数器时钟可以由下列时钟源提供: ·内部时钟(CK_INT) ·外部时钟模式1:外部输入脚(TIx) ·外部时钟模式2:外部触发输入(ETR) ·内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。

    2024年02月02日
    浏览(49)
  • STM32CubeMX教程5 TIM 定时器概述及基本定时器

    开发板(STM32F407G-DISC1) STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 逻辑分析仪nanoDLA 使用STM32CubeMX软件配置STM32F407开发板 使用基本定时器TIM6实现每500ms控制绿灯状态变化一次,基本定时器TIM7实现每1s控制红灯状态变化一次 STM32F407拥有2个基础定时器、

    2024年02月03日
    浏览(88)
  • stm32学习笔记-6TIM定时器

    注:笔记主要参考B站 江科大自化协 教学视频“STM32入门教程-2023持续更新中”。 注:工程及代码文件放在了本人的Github仓库。 定时器是STM32中功能最强大、结构最复杂的一个外设。定时器将包括四部分8小节: 第一部分主要讲定时器基本定时的功能,也就是指定一个时间,让

    2024年02月15日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包