当前位置:网站首页>Stm32cubemx learning (5) input capture experiment

Stm32cubemx learning (5) input capture experiment

2022-06-25 08:08:00 Xiaohui_ Super

Personal learning record

One 、 New project

 Insert picture description here

Two 、 Choose chip model

The development board I use is a punctual atom STM32F103ZET6 Core board

 Insert picture description here

3、 ... and 、 Configure clock

The development board is welded with an external crystal oscillator , So I RCC(Reset and Cock Control) Configuration selected Crystal/Ceramic Resonator( Quartz / Ceramic resonator ), When the configuration is complete , Dexter Pinout view The relevant pins in the are marked green .

 Insert picture description here

After the external high-speed clock configuration is completed , Get into Clock Configuration Options , According to the actual situation , Configure the system clock to 72 MHz, The configuration steps are as follows , Finally press enter , The software will automatically adjust the frequency division and frequency doubling parameters .

 Insert picture description here

Four 、 Configure debug mode

ST-Link Namely Serial Wire Debug mode , Be sure to set !!!
I used to use M0 Chip , There is no problem if this mode is not configured , But now this model , If you don't configure Serial Wire Pattern , Once the program is passed ST-Link Burn into the chip , Chips can no longer be ST-Link Identified .( Later I passed STMISP Tool burning program / After erasing, it will return to normal )

 Insert picture description here

5、 ... and 、 Timer ( Input capture ) Parameter configuration

I will TIM2 The passage of 1 Capture the test channel as input ,STM32CubeMX The default configuration will be PA0 Captured as input IO mouth (PA0 It has the multiplexing function , And no re image is required , So automatically PA0 Set to TIM_CH1 Of GPIO), The parameter setting of the timer is shown in the figure below ( The configuration of input capture may not be changed , Default capture rising edge ):

 Insert picture description here

The frequency division coefficient is 72-1, It means 72 frequency division (0 Express 1 frequency division ,1 Express 2 frequency division , And so on ),TIM2 The clock frequency of is 72 MHz( The following figure ,APB1 Timer clocks The clock frequency of is 72MHz,TIM2 Mounted on APB1 On ). Make it 72 After frequency division , Frequency becomes 1MHz, Count per second 1000000 Time . The cycle is set to 1000-1( One less here , Should be Because the minimum count value is 0), Represents a complete timing period of 1000 Times count , Combined with timer counting frequency , The time required for a timer to overflow is 1ms.【 The frequency determines the capture period of the input capture , The timing value is set to 1000 Just for the convenience of calculation 】

 Insert picture description here

Input to capture the interrupt that needs to start the timer , Interrupts are required for both timing overflow and input capture .

 Insert picture description here

6、 ... and 、 Generate Keil engineering

Set up IDE and Project catalogue and name :

 Insert picture description here

Store the code of each peripheral in a different .c /.h In file , Easy to manage ( Otherwise, they will be put in main.c in ).

 Insert picture description here

Here is the generation Keil The project is about TIM2( Input capture ) Initialized code :

/* TIM2 init function */
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 = 72 - 1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1000 - 1;
  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 = 0;
  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 */

}

7、 ... and 、 Where is the interrupt function written

When using the standard library , We write interrupt handling in the bottom interrupt handling function , Such as EXTI0_IRQHandler(), but Hal The library adds a callback function , Will interrupt some necessary operations at the bottom “ hide ” Get up ( Such as clearing the interrupt ).

The order in which interrupts are called is ( With EXTI0 For example ):EXTI0_IRQHandler() —> HAL_GPIO_EXTI_IRQHandler() —> HAL_GPIO_EXTI_Callback().

TIM2 The interrupt service function of is already in stm32f1xx_it.c In the definition of (STM32CubeMX Automatically generated )

/** * @brief This function handles TIM2 global interrupt. */
void TIM2_IRQHandler(void)
{
    
  /* USER CODE BEGIN TIM2_IRQn 0 */

  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&htim2);
  /* USER CODE BEGIN TIM2_IRQn 1 */

  /* USER CODE END TIM2_IRQn 1 */
}

HAL_TIM_IRQHandler() yes HAL The timer of the library is always interrupted , There's a lot of code inside , It's not shown here , All we need to know is —— When TIM2 Count value overflows or other events occur ( Such as capture of rising / Falling edge signal ) when , The system will execute a series of interrupt callback functions , This includes what we will use Count overflow callback function HAL_TIM_PeriodElapsedCallback() and Input capture callback function HAL_TIM_IC_CaptureCallback().

8、 ... and 、 Test examples

The serial port is used in the experiment , Not mentioned in the above configuration , For serial port configuration, please refer to STM32CubeMx Study (2)USART Serial port experiment

The core of my experimental code is the interrupt callback function :

//  Timer count overflow interrupt processing callback function 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
	if(IC_DONE_FLAG == 0)  //  Incomplete capture 
	{
    
		if(IC_START_FLAG == 1)  //  High level has been captured 
		{
    
			IC_TIMES++;  //  Capture times plus one 
		}
	}
}

// Timer input capture interrupt processing callback function 
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//  Execute when capture interrupt occurs 
{
    
	if(IC_DONE_FLAG == 0)  //  Incomplete capture 
	{
    
		if(IC_START_FLAG == 1)  //  It turned out to be high level , Now capture a falling edge 
		{
    
			IC_VALUE = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);  //  Get capture value 
			TIM_RESET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1);  //  First clear the original settings 
			TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//  Configured for rising edge capture 
			IC_START_FLAG = 0;  //  Flag reset 
			IC_DONE_FLAG = 1;  //  Complete a high level acquisition 
		}
		else  //  Capture has not yet started , Capture the rising edge for the first time 
		{
    
			IC_TIMES = 0;  //  The capture times are cleared 
			IC_VALUE = 0;  //  The capture value is cleared 
			IC_START_FLAG = 1;  //  Set the flag that captures the top edge 
			TIM_RESET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1);  //  First clear the original settings 
			TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//  Configured for falling edge capture 
		}
		__HAL_TIM_SET_COUNTER(htim,0);  //  The timer count value is cleared 
	}
}

complete main.c

/* USER CODE BEGIN Header */
/** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2022 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include <stdio.h>

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

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

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

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

/* USER CODE BEGIN PV */


uint32_t IC_TIMES;  //  Capture times , Company 1ms
uint8_t IC_START_FLAG;  //  Capture start flag ,1: High level captured ;0: High level has not been captured yet 
uint8_t IC_DONE_FLAG;  //  Capture completion flag ,1: A high level acquisition has been completed 
uint16_t IC_VALUE;  //  Enter the capture value of the capture 

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/** * @brief The application entry point. * @retval int */
int main(void)
{
    
  /* USER CODE BEGIN 1 */
	
	uint32_t time = 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_TIM2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);  // Turn on TIM2 Capture channel for 1
  __HAL_TIM_ENABLE_IT(&htim2,TIM_IT_UPDATE);  // Enable update interrupt 
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
		HAL_Delay(10);
		
		if(IC_DONE_FLAG == 1)  //  If a high level acquisition is completed 
		{
    
			IC_DONE_FLAG = 0;  //  Sign clear 
			time = IC_TIMES * 1000;  //  The pulse time is the number of acquisition  * 1000us
			time += IC_VALUE;  //  Plus capture time ( Less than 1ms Part of )
			printf("High level: %d us\n", time);
		}
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/** * @brief System Clock Configuration * @retval None */
void SystemClock_Config(void)
{
    
  RCC_OscInitTypeDef RCC_OscInitStruct = {
    0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {
    0};

  /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses 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_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

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

/* USER CODE BEGIN 4 */


//  Timer count overflow interrupt processing callback function 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
	if(IC_DONE_FLAG == 0)  //  Incomplete capture 
	{
    
		if(IC_START_FLAG == 1)  //  High level has been captured 
		{
    
			IC_TIMES++;  //  Capture times plus one 
		}
	}
}

// Timer input capture interrupt processing callback function 
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//  Execute when capture interrupt occurs 
{
    
	if(IC_DONE_FLAG == 0)  //  Incomplete capture 
	{
    
		if(IC_START_FLAG == 1)  //  It turned out to be high level , Now capture a falling edge 
		{
    
			IC_VALUE = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);  //  Get capture value 
			TIM_RESET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1);  //  First clear the original settings 
			TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//  Configured for rising edge capture 
			IC_START_FLAG = 0;  //  Flag reset 
			IC_DONE_FLAG = 1;  //  Complete a high level acquisition 
		}
		else  //  Capture has not yet started , Capture the rising edge for the first time 
		{
    
			IC_TIMES = 0;  //  The capture times are cleared 
			IC_VALUE = 0;  //  The capture value is cleared 
			IC_START_FLAG = 1;  //  Set the flag that captures the top edge 
			TIM_RESET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1);  //  First clear the original settings 
			TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//  Configured for falling edge capture 
		}
		__HAL_TIM_SET_COUNTER(htim,0);  //  The timer count value is cleared 
	}
}
/* USER CODE END 4 */

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

#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 /* USE_FULL_ASSERT */


Experimental results :

PA0 It corresponds to a key on my development board , When touched ( Not pressed ) When this key is pressed , The serial port will keep printing some useless high-level duration , The duration of these useless pulses is very close to , All are 10ms about , It indicates that the duration of the jitter level of the key is about 10ms.

When you press and hold the key , Let go again , It will print the time when the key is pressed , For example, the data in the two red circles in the following figure , The first high level duration is 4.35s, The duration of the second high level is 1.59s.

 Insert picture description here

原网站

版权声明
本文为[Xiaohui_ Super]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/176/202206250637342177.html