HAL库 TIM计数器及中断开启过程
1、初始化TIM基本计数器参数
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {};
TIM_MasterConfigTypeDef sMasterConfig = {}; htim2.Instance = TIM2;
htim2.Init.Prescaler = -;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = -;
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();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
} }
2、HAL_TIM_Base_Init(&htim2)应用参数基本参数配置
HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
{
/* Check the TIM handle allocation */
if (htim == NULL)
{
return HAL_ERROR;
} /* Check the parameters */
assert_param(IS_TIM_INSTANCE(htim->Instance));
assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); if (htim->State == HAL_TIM_STATE_RESET)
{
/* Allocate lock resource and initialize it */
htim->Lock = HAL_UNLOCKED; #if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
/* Reset interrupt callbacks to legacy weak callbacks */
TIM_ResetCallback(htim); if (htim->Base_MspInitCallback == NULL)
{
htim->Base_MspInitCallback = HAL_TIM_Base_MspInit;
}
/* Init the low level hardware : GPIO, CLOCK, NVIC */
htim->Base_MspInitCallback(htim);
#else
/* Init the low level hardware : GPIO, CLOCK, NVIC */
HAL_TIM_Base_MspInit(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
} /* Set the TIM state */
htim->State = HAL_TIM_STATE_BUSY; /* Set the Time Base configuration */
TIM_Base_SetConfig(htim->Instance, &htim->Init); /* Initialize the TIM state*/
htim->State = HAL_TIM_STATE_READY; return HAL_OK;
}
3、HAL_TIM_Base_MspInit(htim) 初始化中断信息(该函数需要重写,CubeMX在配置生成代码时会自动重写该函数)
/**
* @brief Initializes the TIM Base MSP.
* @param htim TIM Base handle
* @retval None
*/
__weak void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim); /* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIM_Base_MspInit could be implemented in the user file
*/
}
重写实现
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{ if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */ /* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE(); /* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, , );
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspInit 1 */ /* USER CODE END TIM2_MspInit 1 */
}
}
4、使能TIM中断
虽然经过以上配置,TIM的参数信息都已完整应用,但是TIM的中断并没用真正使能.这个地方困扰了我好久(运行没错误,但是计数中断就不触发, 不计数),必需调用以下函数使能中断,串口中断使能也是类似的.
HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *TIM);//开启定时器中断
该函数的调用地点只要是在 HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) 函数之后就行,可以在main.c中也可以在上面的代码之后.
下面的代码存在一个BUG,如果 HAL_TIM_Base_Start_IT 函数调用写在下面的位置,虽然可以使能中断,但会造成MCU上电即触发中断的情况.
HAL_TIM_Base_MspInit调用之后会重新设置寄存器的值,__HAL_TIM_CLEAR_FLAG(tim_baseHandle, TIM_SR_UIF)清理的寄存器被改写.
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{ if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */ /* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE(); /* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, , );
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspInit 1 */
//清理TIM开启时的中断标识
__HAL_TIM_CLEAR_FLAG(tim_baseHandle, TIM_SR_UIF);//添加这条语句解决问题
//htim2.Instance->SR = 0; //这是另一种解决办法
//使能TIM中断
HAL_TIM_Base_Start_IT(tim_baseHandle);
/* USER CODE END TIM2_MspInit 1 */
}
}
正确的做法是在 HAL_TIM_Base_Init(&htim2) 之后使能TIM中断,并清理TIM的更新中断寄存器
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {};
TIM_MasterConfigTypeDef sMasterConfig = {}; htim2.Instance = TIM2;
htim2.Init.Prescaler = -;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = -;
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();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
} //清理TIM开启时的中断标识
__HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE);
//使能TIM中断
HAL_TIM_Base_Start_IT(&htim2);
}
5、计数中断处理
/**
* @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(&htim2)中断函数处理
/**
* @brief This function handles TIM interrupts requests.
* @param htim TIM handle
* @retval None
*/
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{
/* Capture compare 1 event */
if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
{
if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) != RESET)
{
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1; /* Input capture event */
if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->IC_CaptureCallback(htim);
#else
HAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
/* Output compare event */
else
{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->OC_DelayElapsedCallback(htim);
htim->PWM_PulseFinishedCallback(htim);
#else
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
}
........................
........................
/* TIM Update event */
if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
{
if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->PeriodElapsedCallback(htim);
#else
HAL_TIM_PeriodElapsedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
}
........................
........................ }
HAL_TIM_PeriodElapsedCallback(htim);当计数溢出时调用的回调函数,需要用户根据实际需求具体实现
/**
* @brief Period elapsed callback in non-blocking mode
* @param htim TIM handle
* @retval None
*/
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim); /* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIM_PeriodElapsedCallback could be implemented in the user file
*/
}
6、实现计数完成回调函数,调试代码,查看计数器中断效果.
HAL库 TIM计数器及中断开启过程的更多相关文章
- STM32F072从零配置工程-基于HAL库的串口UART中断配置
先上一个采用串口直接传输的Demo: 此处的思路是完全采用HAL库来实现的,核心是运用HAL_UART_Transmit_IT和HAL_UART_Receive_IT两个函数来实现的,可以作为一个De ...
- STM32L0 HAL库 TIM定时1s
STM32L0的定制器资源: 本实验使用TIM6 HSI频率是16Mhz,则单指令周期是1/16Mhz 预分频设置为1600,则每跑1600下,定时器加1,相当于定时器加1的时间是1600*(1/16 ...
- HAL库|神器cubemx的正确打开方式
前言 工欲善其事,必先利其器.HAL库的开发不一定必须使用cubemx,但是使用了cubemx,你绝对不会后悔.基于一些小伙伴对cubemx的使用还有一些疑问,本次小飞哥从新建工程到生成工程,编写应用 ...
- STM32基于HAL库通过DMA读写SDIO
通过STM32CUBEMX生成DMA读写sdio的工程,再读写过程中总会卡死在DMA中断等待读写完成的while中,最终发现while等待的标志在SDIO的中断里置位的,而SDIO中断优先级如果小于或 ...
- 【STM32H7教程】第32章 STM32H7的TIM定时器基础知识和HAL库API
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第32章 STM32H7的TIM定时器基础知识和H ...
- STM32 HAL 库实现乒乓缓存加空闲中断的串口 DMA 收发机制,轻松跑上 2M 波特率
前言 直接储存器访问(Direct Memory Access,DMA),允许一些设备独立地访问数据,而不需要经过 CPU 介入处理.因此在访问大量数据时,使用 DMA 可以节约可观的 CPU 处理时 ...
- (2)STM32使用HAL库操作外部中断——理论讲解
1.中断触发过程 对主程序压栈--把中断服务函数的地址写入到程序计数器(PC)--执行中断服务函数 2.中断向量表 中断服务函数的地址在STM32的手册上的中断向量表中(如下是一部分): 如上表所示, ...
- STM32F407 使用HAL库延时微妙实现方法(附CubeMX配置过程)
STM32F407 使用HAL库延时微妙实现方法(STM32CubeMX配置) 作者 : 李剀出处 : https://www.cnblogs.com/kevin-nancy/p/10696681.h ...
- stm32F4中断分析-HAL库
详细可以参考: STM32使用HAL库操作外部中断——实战操作 https://www.cnblogs.com/wt88/p/9624103.html /** ******************** ...
随机推荐
- libvirt2.0安装
目录 1.libvirt介绍 2.卸载系统自带的libvirt 2.1.查看当前安装的libvirt相关包 2.2.全部卸载掉 3.使用tar包编译安装 3.1.解压缩 3.2.生成Makefile文 ...
- linux支持并发的服务器回射程序实例
实例一:不支持并发,单服务器---单客户端 /************************************************************************* > ...
- 带你手写基于 Spring 的可插拔式 RPC 框架(三)通信协议模块
在写代码之前我们先要想清楚几个问题. 我们的框架到底要实现什么功能? 我们要实现一个远程调用的 RPC 协议. 最终实现效果是什么样的? 我们能像调用本地服务一样调用远程的服务. 怎样实现上面的效果? ...
- bootstrap基础学习【菜单、按钮、导航】(四)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Linux 中文man手册安装
首先需要确认的是有没有安装中文支持,如果没有请安装:#yum groupinstall -y "Chinese Support" 现在下载安装包: wget http://manp ...
- [转]Mybatis之TypeHandler使用教程
Mybatis之TypeHandler使用教程 https://blog.csdn.net/jokemqc/article/details/81326109 深入浅出Mybatis系列(五)---Ty ...
- python的一些知识点
1. 内置函数 iter 2. 可迭代对象与迭代器:
- (十四)springMvc 对 restful 的支持
文章目录 restful 的概念 配置支持 restful 的前端控制器 配置不拦截静态资源 restful 的概念 restful 是一种开发理念: 对 url 进行规范 每个 url 代表一个资源 ...
- P1040 加分二叉树(区间DP)
(点击此处查看原题) 解题思路 题目已经给出了树的中序遍历,因此我的想法是利用中序遍历的特点:若某子树的根结点为k,那么k之前的结点组成这一子树的左子树,k之后的结点组成这一子树的右子树,可以通过不断 ...
- js图片压缩上传
最近公司的移动产品相约app要做一次活动,涉及到图片上传,图片又不能太大,不然用户体验太差,必须先压缩再上传,所以用到了html5的canvas和FileReader,代码先上,小弟前端经验不足,代码 ...