STM32 HAL库-定时器中断

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


STM32 关闭所有中断

关闭或开启所有中断;代码如下:

__set_PRIMASK(1);//关总中断

__set_PRIMASK(0);//开总中断

一、STM32F407定时器介绍

STM32F407 有众多的定时器,其中包括 2 个基本定时器(TIM6 和 TIM7)、10 个通用定时
器(TIM2 ~ TIM5、TIM9 ~TIM14)、2 个高级控制定时器(TIM1 和 TIM8),这些定时器彼此完
全独立,不共享任何资源。
hal库定时器中断,嵌入式MCU,stm32,单片机,嵌入式硬件
hal库定时器中断,嵌入式MCU,stm32,单片机,嵌入式硬件

选择定时器,配置时钟源,设置预分频系数,计数模式,设置自动重装载值

定时器计算公式

hal库定时器中断,嵌入式MCU,stm32,单片机,嵌入式硬件

不过一般情况下定时时间都是毫秒级别。
时钟频率是84Mhz这里进行84分频,就是1Mhz,也就是每秒10的6次方个脉冲。而重装载值是1000,每秒可以触发1000个中断,也就是定时时间是1ms。

PSC = 84 -1 = 83;
ARR = 1000 -1 = 999;

二、CubeMX配置定时器

详见正点原子视频教程

三、基本定时器中断配置流程

1)开启定时器时钟

HAL 中定时器使能是通过宏定义标识符来实现对相关寄存器操作的,方法如下:
__HAL_RCC_TIMx_CLK_ENABLE(); /* x=1~14 */

2)初始化定时器参数,设置自动重装值,分频系数,计数方式等

定时器的初始化参数是通过定时器初始化函数 HAL_TIM_Base_Init 实现的。
注意:该函数会调用:HAL_TIM_Base_MspInit 函数,我们可以通过后者存放定时器时钟
和中断等初始化的代码。

3)使能定时器更新中断,开启定时器计数,配置定时器中断优先级

通过 HAL_TIM_Base_Start_IT 函数使能定时器更新中断和开启定时器计数。

通过 HAL_NVIC_EnableIRQ 函数使能定时器中断,通过 HAL_NVIC_SetPriority 函数设置
中断优先级。

4)编写中断服务函数(主要是重写回调函数,覆盖原来的)

定时器中断服务函数为:TIMx_IRQHandler 等,当发生中断的时候,程序就会执行中断服
务函数。
HAL 库提供了一个定时器中断公共处理函数 HAL_TIM_IRQHandler,该函数又会调用HAL_TIM_PeriodElapsedCallback 等一些回调函数,需要用户根据中断类型选择重定义对应的中
断回调函数来处理中断程序。

注意:

1、中断处理最好写在回调函数里面。

往往不止一种情况触发同一个中断,各个情况都有对应回调函数,库函数会去检查相关标志位并调用对应的回调函数,这样就不需要我们自己去检查中断标志来确定中断来源以及清除标志位,比如上面的中断程序可以写在void HAL_TIM_PeriodElapsedCallback里面。
库的回调函数都有__weak修饰,我们可以自己定义回调函数。

2、时钟与它的中断使能可以用函数HAL_TIM_Base_Start_IT()。

四、参考资料

这篇文章介绍的非常不错: 【STM32】基于HAL库的中断详细学习

1 HAL库的中断处理

1.1 HAL 库的中断封装

在上一节中我们介绍了中断的处理过程:当中断发生时,处理器暂停当前程序,根据中断类型号在中断向量表中查找中断服务程序的入口地址,进而执行中断服务程序。执行完成后,返回断点处执行原程序。虽然上述的操作大部分是由硬件完成,但是在针对具体外设的中断处理中,还需要用户完成以下的编程步骤:

① 设置中断触发条件。如外部中断的边沿触发,定时器更新中断的时间间隔。

② 设置中断优先等级。系统中存在多个中断时,需要根据任务的紧迫程度,设置不同的中断优先级。

③ 使能外设的某个中断。微控制器片内集成的外设一般都有多个中断源,这些中断源的使能由外设的寄存器控制。例如,串口通信的发送数据寄存器空中断TXE和发送完成中断TC的使能,就是由串口控制寄存器CR1中的TXEIE位和TCIE位控制。

④ 判断中断源。对于有多个中断源的外设,进入中断服务程序后,需要根据中断标志来判断具体发生了哪一种中断。

⑤ 清除中断标志。发生中断后,相应的中断标志位置位,以便MCU查询。这些中断标志要注意及时清除,避免重复进入中断。

⑥ 编写程序。用户根据实际项目的需求来编写中断发生时应该执行的操作。

在上述的六个中断编程步骤中,借助CubeMX软件可以通过图形化的设置方式完成前三个步骤,而后三个步骤可以借助HAL库提供的接口函数进一步简化。

在HAL库中,将中断的处理过程进行了重新的封装,主要有以下几点:

1.统一定义了各个外设的中断通用处理所两数HAL_PPP_IRQHandler()(PPP代表外设名称)。

2.在中断通用处理函数HAL_PPP_IRQHandler()中完成中断标志的判断和清除。

3.将中断中需要执行的操作以回调函数的形式提供给用户,回调函数由中断通用处理函数调用。

回调函数是一个通过函数指针调用的函数。如果把一个函数的指针(即函数的地址)作为另一个函数的参数时,当这个指针被用来调用其所指向的函数时,这个被调用的函数就称为回调函数。

我们通过一个例子来进一步说明回调函数的概念。假设有三个函数:Func1、Func2和 Func3。函数Func1调用函数Func2,同时将函数Func3作为形参传递给Func2,此时,Fun1 可以看作是应用层函数,Func2可以看作是中间层函数,Func3则称为回调函数。

在实际的程序设计中,回调函数一般位于用户程序中,和主程序同属于应用层,而回调函数的调用方通常是第三方提供的库函数。回调函数的执行,相当于从库函数调用应用层的函数,因此称为回调。

回调函数一般用于执行具体的操作,需要用户根据实际项目的需求来编写。无法封装到第三方的库函数里面。因此,库函数提供一个函数指针作为入口参数,主程序将回调函数像参数一样传入库函数。这样一来,只要改变传进库函数的参数,就可以实现不同的功能,并且不需要修改库函数的代码,确保了应用层和库函数的解耦。

以中断服务程序的处理为例:判断中断源,清除中断标志这些流程对任何一个中断都相同的。但是,某一个中断发生之后执行什么具体的操作,却各不相同。比如,1s的定时中断到了,是开启一个指示灯,还是使蜂鸣器鸣响,都由用户根据实际项目的需求来编写。因此,HAL库将中断中需要执行的操作以回调函数的形式提供给用户,简化了中断服务程序的设计。

HAL库在设计回调函数的时候,采用了更为巧妙的方法:在需要使用回调函数的地方,预定义了一个默认的回调函数,该函数的属性设计为“weak”,函数内部不执行任何操作。weak属性的函数表示:如果该函数没有在其他文件中定义,则使用该函数;如果用户在其他地方定义了该函数,则使用用户定义的函数。当用户需要使用回调函数时,可以在应用程序中重新定义一个同名的回调函数,在函数中实现具体的操作。这样,编译器在编译的时候,就会选择用户重新定义的回调函数。

在利用CubeMX软件生成的MDK工程中,与中断处理相关的文件一共有两个:

1.启动文件:startup_stm32fxxx.s (xxx表示芯片型号)

在启动文件中,创建了中断向量表,并预先为每一个中断编写了中断服务程序。这些断服务程序的内部都是死循环,不执行任何具体操作,其目的只是为了初始化中断向量表。中断服务程序的属性设置为“weak”,用户可以在用户文件中重新定义一个同名函数作为实际执行的中断服务程序。

2.中断服务程序文件:stm32fxxx_it.c (xxx表示芯片型号)

中断服务程序文件用于存放各个中断实际执行的中断服务程序,这些中断服务程序可以分成两个部分:

第一部分是Cortex-M内核处理器的异常处理程序,包括不可屏蔽中断(NMI)类型错误(HardFault)以及系统节拍定时器中断(Systick)等。

第二部分是微控制器片内外设的中断服务程序。在使用CubeMX软件进行初始化配置时,如果使能了某一个外设的中断功能,那么在生成代码时,对应外设的中断服务程序将会自动添加到stm32fxxx_it.c文件中,在中断服务程序中再调用该外设所对应的中断通用处理函数HAL_PPP_IRQHandler()。

注意:中断服务程序的函数名在中断向量表中已经由ST公司预先规定,用户必须按照这个规定的函数名来编写中断服务程序。发生中断时,中断服务程序才能被正确调用。

1.2 外部中断处理流程

下面我们以GPIO引脚触发的外部中断为例,来详细分析一下HAL库的中断处理流程。假设芯片型号为STM32F411,设置引脚PC0和PC13为外部中断功能(即PC0和PC13与对应的外部中断线EXTI0和EXTI13相连),并使能对应的外部中断。当引脚PC0或PC13出现电平变化时,将触发外部中断,具体的执行过程如下:

1. 查找中断向量表,跳转到中断服务程序

微控制器暂停当前程序的执行,根据中断向量表跳转到EXTIO_IRQHandler()(外部中断线0的中断服务程序)或者EXTI15 10_IRQHandler()(外部中断线10~15的中断服务程序)执行,具体执行哪一个中断服务程序由中断发生的先后顺序及中断的优先级决定。启动文件startup_stm32f411xe.s的中断向量表中预先定义了外部中断线所对应的中断服务程序,如表所示。这些定义的函数都加入了weak属性。
hal库定时器中断,嵌入式MCU,stm32,单片机,嵌入式硬件
2.执行中断服务程序

启动文件startup_stm32f411xe.s中定义的中断服务程序默认为死循环,不执行任何具体操作。由于这些函数定义为weak属性,因此用户可以在stm32f4xx_it.c文件中重新定义与该函数同名的中断服务程序。当中断发发生时,将执行在stm32f4xx_it.c文件中重新定义的中断服务程序。

我们在CubeMX软件中使能外部中断线发的中断功能后,将在stm32f4xx_it.c文件中自动添加相关的外部中断服务程序,具体代码支如程序清单所示。

/*
* @brief This function handles EXTI line0 interrupt.
*/
void EXTI0_IRQHandler(void) // 外部中断线日的中断服务程序 
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); // 调用外部中断通用处理函数
}
/*
*@brief This function handles EXTI line[15:10] interrupts.
*/
void EXTI15_10_IRQHandler(void) // 外部中断线 10~15 的中断服务程序 
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); // 调用外部中断通用处理函数
}

3. 执行外部中断通用处理函数

进入外部中断服务程序EXTIO_IRQHa andler()或EXTI15_10_IRQHandler()后,都将调用HAL库提供的外部中断通用处理函数数HAL_GPIO_EXTI_IRQHandler()。该函数作为HAL库提供的外部中断接口函数,在stm32f4xx_hal_gpio.c文件中定义。

由于所有通过GPIO引脚触发的外部中断都会调用外部中断通用处理函数,因此在函数内部需要判断本次中断具体是由哪一个GPIO引脚触发的,并清除对应的中断标志最后再调用外部中断回调函数HAL_GPIO_ EXTI_Callback()完成具体的中断处理任务。

外部中断通用处理函数的代码如程序清单所示。

/*
* @brief This function handle s EXTI interrupt request.
* @param GPIO_Pin Specifes the pins connected EXTI line
* @retval None
*/
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin)!= RESET)// 检测对应的中断标志是否置位
{
_HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); // 清除对应的中断标志 
HAL_GPIO_EXTI_Callback(GPIO_Pin); // 调用回调函数执行具体任务 
}
}

4.默认的外部中断回调函数

外部中断回调函数HAL_GPIO_EXTI Callback()用于完成具体的中断处理任务。该函数也是HAL库提供的外部中断接口函数数,在stm32f4xx_hal_gpio.c文件中定义。默认的外部中断回调函数添加了weak属性,函数内部没有任何可执行代码,仅仅有一个避免编译器警告的语句:UNUSED(GPIO_Pin)。

默认的外部中断回调函数的代码如程序清单所示。

/*
* @brief EXTI line detection callbacks.
* @param GPIO_Pin Specifes the pins connected EXTI line
* @retval None
*/
_weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/*NOTE:This function Should not be modifed, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file*/
}

5.执行用户编写的外部中断回调函数

用户需要在main.c文件中重新编写外部中断回调函数HAL_GPIO_EXTI_Callback(),来完成具体的中断处理任务。中断回调函数一般添加在/* USER CODE BEGIN4*/和/* USER CODE END4*/之间。由于所有通过于GPIO引脚触发的外部中断都会调用该回调函数,因此在回调函数内部,需要根据入口参参数GPIO_Pin判断是哪一个GPIO引脚触发的本次外部中断,然后再执行不同的中断处理任务。如果用户设置了多个GPIO引脚产生外部中断,则可以使用switch-case多分支语句进行判断。

外部中断回调函数的示例代码如程序法清单所示。

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
case GPIO_PIN_0: // 引脚 PCO 对应的中断处理任务 
/* GPIO_PIN_0 EXTI handling */
break;
case GPIO_PIN_13:
/*GPIO_PIN_13 EXTI handling */ // 引脚 PC13 对应的中断处理任务 
break;
case GPIO_PIN_X; // 引脚x对应的中断处理任务 
/* GPIO_PIN_X EXTI handling */ 
break;
……
default:
break;
}
}
/* USER CODE END 4 */
 

根据上述的分析,我们可以用下图来更加清晰地展示HAL库的外部中断处理流程。

从下图可以看到,发生外部中断时处理器在中断向量表找到所对应的中断服务程序,在中断服务程序内部调用外部中断通通用处理函数HAL_GPIO_EXTI_IRQHandler( ),最后再调用外部中断回调函数HAL_GP O_EXTICallback()来完成具体的中断处理任务。
hal库定时器中断,嵌入式MCU,stm32,单片机,嵌入式硬件
在HAL库的外部中断处理流程中,外部中断回调函数HAL_GPIO_EXTI_Callback()是放在main.c文件中,作为应用程序的一部分,而它的调用却是由HAL库提供的接口函数触发的,即库函数反过来调用应用层的函类数,因此称为回调函数。

借助CubeMX软件和HAL库,用户的中中断编程步骤大大简化,只需要利用CubeMX软件进行中断的相关配置,包括中断触发条件、中断优先级以及中断使能等,最后在中断回调函数中编写具体的中断处理任务即可。

五、示例

借助CubeMX软件和HAL库,定时器中断调用HAL_TIM_IRQHandler函数,发现它内部是这么实现中断处理的:

由于我们只使用了最基本的定时器更新中断,所以在这个函数里,只会进入TIM Update event这个处理内部,清除中断标志后,还会调用HAL_TIM_PeriodElapsedCallback这个函数。
hal库定时器中断,嵌入式MCU,stm32,单片机,嵌入式硬件
hal库定时器中断,嵌入式MCU,stm32,单片机,嵌入式硬件
而HAL_TIM_PeriodElapsedCallback这个函数是这么实现的:
hal库定时器中断,嵌入式MCU,stm32,单片机,嵌入式硬件
它有一个__weak关键词修饰,函数内部是空的,没做任何处理。

这种有__weak修饰的函数,是可以被用户重写的。HAL_TIM_PeriodElapsedCallback这类函数一般称为回调函数,是留给用户的接口函数,用于给用户重写实现,以加入自己的功能。文章来源地址https://www.toymoban.com/news/detail-822448.html

//定时器开启的时候记得设置CUBE里面的NVIC
uint16_t t3_count;
uint16_t t3_count2;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *hitm)
{
	if(hitm ->Instance ==TIM1)
	{
	}
	if(hitm ->Instance ==TIM3)//定时器3,定时时间10ms
	{
		t3_count++;
		if(t3_count>=100)//1s
		{
			t3_count=0;
			Led0_Toggle;
			t3_count2++;
			if(t3_count2>=10)//10s
			{
				Led1_Toggle;
				t3_count2=0;
			}
		}
	}

}

到了这里,关于STM32 HAL库-定时器中断的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • STM32HAL库定时器中断、按键中断、串口中断、按键消抖和低通滤波算法详解

    本文将详细介绍STM32HAL库中的定时器中断、按键中断、串口中断的使用方法,以及按键消抖和低通滤波算法的实现。希望能对您的STM32开发提供帮助。 目录 1. 定时器中断 2. 按键中断 3. 串口中断 4. 按键消抖 5. 低通滤波算法 一、定时器中断 定时器中断是STM32开发中常用的一种

    2024年02月15日
    浏览(49)
  • 【HAL库】STM32CubeMX开发----非阻塞延时实验----SysTick(滴答定时器)中断

    STM32CubeMX 下载和安装 详细教程 【HAL库】STM32CubeMX开发----STM32F103/F207/F407----目录 HAL库 有自带的 ms级 延时函数: HAL_Delay(); 缺点: 这是 阻塞延时 方式,就是延时期间,什么都不能干,这样很浪费资源。 这篇文章主要介绍,利用 SysTick(滴答定时器)中断 实现 非阻塞延时 的实验

    2024年02月16日
    浏览(48)
  • 2.基于正点原子STM32F103的定时器中断实验(HAL库实现)(cubeMX)

      基本上每一款MCU都会配备定时器这个外设,STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。 同样,STM32F1系列的定时器功能也很强大,包括: TIM1和TIM8两个高级定时器; TIM2~TIM5是个通用寄存器; TIM7,TIM8,两个基本定时器。 由于本次实验适用于新手入门

    2023年04月26日
    浏览(159)
  • STM32控制步进电机:基于HAL库定时器中断的闭环步进电机驱动+精准控制脉冲数

    该篇文章中用到的步进电机闭环驱动器为Emm42_V4.0步进电机闭环驱动器。该闭环驱动器自带FOC矢量闭环控制算法,能实现力矩、速度、位置三环控制。 如下图所示,该42步进闭环电机驱动器的A+、A-、B+、B-连接步进电机,通过右侧的使能、脉冲、方向端对步进电机进行驱动控制

    2024年02月01日
    浏览(53)
  • STM32 HAL库 通用定时器介绍及相关应用例程 定时器中断 输出PWM (点亮LED呼吸灯、输出PWM、输入捕获) CubeMX

    (部分图引自于ATK) 前情提要(基本定时器) 点此进入 通用定时器类别 通用定时器和基本定时器相比大致的工作方式是相似的,不过通用定时器比基本定时器多了一些很好用的功能,比如: 外部输入捕获 输出比较 输出PWM 时钟源 CubeMX为我们提供了配置时钟的非常方便的工

    2024年04月15日
    浏览(82)
  • (四) timer+pit(定时器中断)+encoder(编码器)-逐飞TC264库学习(对比STM32 HAL库)

    PIT , 是programmable interval timer 可编程间隔定时器 DSC中的器件 的缩写,所以就是定时器中断,有点像32里的timer(TIMx) 目前看来一共能用通道的有四个 typedef enum // 枚举通道号 {     CCU60_CH0,     CCU60_CH1,     CCU61_CH0,     CCU61_CH1, }pit_index_enum; 因为涉及到中断,为方便设定中断优

    2024年03月15日
    浏览(72)
  • stm32——hal库学习笔记(定时器)

    使用纯软件(CPU死等)的方式实现定时(延时)功能 使用精准的时基,通过硬件的方式,实现定时功能 递增计数模式实例说明 中心对齐模式实例说明 TIM6 和TIM7 控制寄存器 1(TIMx_CR1) TIM6 和TIM7 DMA/中断使能寄存器(TIMx_DIER) TIM6 和TIM7 状态寄存器(TIMx_SR) TIM6 和TIM7 计数器(TIMx_CNT)

    2024年02月21日
    浏览(52)
  • # HAL库STM32常用外设教程(四)—— 定时器 基本定时

    1、STM32F407ZGT6 2、STM32CubeMx软件 3、keil5 内容简述: 通篇文章将涉及以下内容,如有错误,欢迎指出 : 1、基础定时器特性 2、基础定时器的结构和功能 3、基础定时器HAL库驱动程序 (1)CubeMx配置 (2)TIM驱动程序   STM32F407有2个高级控制定时器(TIM1、TIM8)、8个通用定时器和

    2024年02月02日
    浏览(63)
  • 【STM32】HAL库-系统滴答定时器SysTick

    SysTick定时器被捆绑在NVIC中,是一个简单的定时器,对于CM3、CM4内核芯片,都有Systick定时器。Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。 Systick定时器就是系统滴答定时器,一个 24 位的倒计数定时器 ,计到0 时,将从

    2023年04月08日
    浏览(45)
  • STM32 hal库编程定时器计数清零

    1、stm32定时器是有重装载功能的,所以定时器中断不关的话,就不需要计数清零 2、主要是应对单次计时使用,可能因为没有清零导致程序再次运行到相同位置时,中断立即出发,没有完成计时的功能。 顺便加一个读取定时器计数值得函数

    2024年02月03日
    浏览(53)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包