网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事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)**