2024年最全STM32CubeMX 学习(5)输入捕获实验_stm32cubemx输入捕获,字节跳动大数据开发架构师学习笔记

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

/\*\*
 \* @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() 是 HAL 库的定时器总中断,里面代码很多,这里不展示,我们只需要知道一点——当 TIM2 计数值溢出或发生其他事件(如捕获到上升/下降沿信号)时,系统会执行一系列的中断回调函数,其中包括我们将要用到的 计数溢出回调函数HAL_TIM_PeriodElapsedCallback() 和 输入捕获回调函数HAL_TIM_IC_CaptureCallback()

八、测试示例

实验中用到了串口,上文配置中没提及,串口配置可以参考 STM32CubeMx 学习(2)USART 串口实验

我的实验代码的核心部分为中断回调函数:

// 定时器计数溢出中断处理回调函数
void HAL\_TIM\_PeriodElapsedCallback(TIM_HandleTypeDef \*htim)
{
	if(IC_DONE_FLAG == 0)  // 未完成捕获
	{
		if(IC_START_FLAG == 1)  // 已经捕获到了高电平
		{
			IC_TIMES++;  // 捕获次数加一
		}
	}
}

//定时器输入捕获中断处理回调函数
void HAL\_TIM\_IC\_CaptureCallback(TIM_HandleTypeDef \*htim)// 捕获中断发生时执行
{
	if(IC_DONE_FLAG == 0)  // 未完成捕获
	{
		if(IC_START_FLAG == 1)  // 原来是高电平,现在捕获到一个下降沿
		{
			IC_VALUE = HAL\_TIM\_ReadCapturedValue(htim, TIM_CHANNEL_1);  // 获取捕获值
			TIM\_RESET\_CAPTUREPOLARITY(htim,TIM_CHANNEL_1);  // 先清除原来的设置
			TIM\_SET\_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);// 配置为上升沿捕获
			IC_START_FLAG = 0;  // 标志复位
			IC_DONE_FLAG = 1;  // 完成一次高电平捕获
		}
		else  // 捕获还未开始,第一次捕获到上升沿
		{
			IC_TIMES = 0;  // 捕获次数清零
			IC_VALUE = 0;  // 捕获值清零
			IC_START_FLAG = 1;  // 设置捕获到了上边沿的标志
			TIM\_RESET\_CAPTUREPOLARITY(htim,TIM_CHANNEL_1);  // 先清除原来的设置
			TIM\_SET\_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);// 配置为下降沿捕获
		}
		\_\_HAL\_TIM\_SET\_COUNTER(htim,0);  // 定时器计数值清零
	}
}

完整 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;  // 捕获次数,单位1ms
uint8\_t IC_START_FLAG;  // 捕获开始标志,1:已捕获到高电平;0:还没有捕获到高电平
uint8\_t IC_DONE_FLAG;  // 捕获完成标志,1:已完成一次高电平捕获
uint16\_t IC_VALUE;  // 输入捕获的捕获值

/\* 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);  //开启TIM2的捕获通道1
  \_\_HAL\_TIM\_ENABLE\_IT(&htim2,TIM_IT_UPDATE);  //使能更新中断
	
  /\* USER CODE END 2 \*/

  /\* Infinite loop \*/
  /\* USER CODE BEGIN WHILE \*/
  while (1)
  {
		HAL\_Delay(10);
		
		if(IC_DONE_FLAG == 1)  // 如果完成一次高电平捕获
		{
			IC_DONE_FLAG = 0;  // 标志清零
			time = IC_TIMES \* 1000;  // 脉冲时间为捕获次数 \* 1000us
			time += IC_VALUE;  // 加上捕获时间(小于1ms的部分)
			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 \*/


// 定时器计数溢出中断处理回调函数
void HAL\_TIM\_PeriodElapsedCallback(TIM_HandleTypeDef \*htim)
{
	if(IC_DONE_FLAG == 0)  // 未完成捕获
	{
		if(IC_START_FLAG == 1)  // 已经捕获到了高电平
		{
			IC_TIMES++;  // 捕获次数加一
		}
	}
}

//定时器输入捕获中断处理回调函数
void HAL\_TIM\_IC\_CaptureCallback(TIM_HandleTypeDef \*htim)// 捕获中断发生时执行
{
	if(IC_DONE_FLAG == 0)  // 未完成捕获
	{
		if(IC_START_FLAG == 1)  // 原来是高电平,现在捕获到一个下降沿
		{
			IC_VALUE = HAL\_TIM\_ReadCapturedValue(htim, TIM_CHANNEL_1);  // 获取捕获值
			TIM\_RESET\_CAPTUREPOLARITY(htim,TIM_CHANNEL_1);  // 先清除原来的设置
			TIM\_SET\_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);// 配置为上升沿捕获
			IC_START_FLAG = 0;  // 标志复位
			IC_DONE_FLAG = 1;  // 完成一次高电平捕获
		}
		else  // 捕获还未开始,第一次捕获到上升沿
		{
			IC_TIMES = 0;  // 捕获次数清零
			IC_VALUE = 0;  // 捕获值清零
			IC_START_FLAG = 1;  // 设置捕获到了上边沿的标志
			TIM\_RESET\_CAPTUREPOLARITY(htim,TIM_CHANNEL_1);  // 先清除原来的设置
			TIM\_SET\_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);// 配置为下降沿捕获
		}
		\_\_HAL\_TIM\_SET\_COUNTER(htim,0);  // 定时器计数值清零
	}
}
/\* 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
 \*/


![img](https://img-blog.csdnimg.cn/img_convert/61d5884af4f4fad02afe4d9e11caa7d3.png)
![img](https://img-blog.csdnimg.cn/img_convert/ae169d9fce9fafc749a02dbbe4a1584c.png)
![img](https://img-blog.csdnimg.cn/img_convert/553f0c54b20a5c66fdc71afb758d9645.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

片转存中...(img-9Nsk2WlO-1714896878770)]
[外链图片转存中...(img-enXo30wj-1714896878770)]
[外链图片转存中...(img-3KyR5XzW-1714896878770)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值