6.STM32F407之HAL库——定时器中断

使用STM32CubeMX配置工程+MDKARM编写代码实现定时器中断

  • 一、定时器中断简介
    • 1.中断
    • 2.STM32F407定时器资源
      • 1)基本定时器(TIM6 ~ TIM7)
      • 2)通用定时器(TIM9 ~ TIM14)
      • 3)通用定时器(TIM2 ~ TIM5)
      • 4)高级控制定时器(TIM1 和 TIM8)
  • 二、定时器工作方式
    • 1.计数器模式
    • 2.时钟选择
  • 三、STM32CubeMX配置
  • 四、代码实现
  • 五、参考资料等

一、定时器中断简介

1.中断

  中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
  单片机中的中断类型主要分为外部中断和定时器中断。其中定时器中断又可以细分为很多的类型,比如看门狗中断也是某种类型的定时器中断。定时器中断主要是指内部或者外部时钟计时溢出后产生中断的类型。外部中断是指,接受到某个外部IO信号后直接产生中断的类型。

  
  简单说就是暂停手头的事情,去做另外一件事情(中断事件),等事情(中断事件)搞定了再回头去处理一开始停下来的事情。
  并且中断是可以嵌套的,就是可以套娃。但是中断调用栈是有限的,同时中断源也是有限的,就是说不能够无限的套娃。
  中断具有优先级,高优先级可以打断低优先级,反之则不可以。相当于大领导可以打断小领导,小领导可以打断打工人,反之不行。
  中断会影响主程序的运行,所以要尽量少的使用中断,使用中断时也要减少中断内程序的运行时间,过长时间的中断会影响主程序的运行。

  在STM32中定时器的主要作用是定时(触发定时中断)、输入捕获、输出比较、生成PWM波(这点和51不同,51要自己去写PWM,STM32可以直接生成)、单脉冲输出等功能。

2.STM32F407定时器资源

  在STM32F407中定时器的资源十分的多。大体上可以分为以下几类。

1)基本定时器(TIM6 ~ TIM7)

  16 位自动重载递增计数器(只能递增计数)
  16 位可编程预分频器
  用于触发 DAC 的同步电路(这两个定时器除了用于生成时基之外,还专门用于驱动数模转换器DAC)

2)通用定时器(TIM9 ~ TIM14)

  16 位自动重载递增计数器(只能递增计数)
  16 位可编程预分频器
  都拥有四个通道,可用于输入捕获、输出比较、PWM生成、单脉冲输出

3)通用定时器(TIM2 ~ TIM5)

  TIM3 和 TIM4拥有16位递增、递减和递增/递减自动重载计数器。
  TIM2 和 TIM5拥有32位递增、递减和递增/递减自动重载计数器。
  16 位可编程预分频器
  都拥有四个通道,可用于输入捕获、输出比较、PWM生成、单脉冲输出
  使用外部信号控制定时器且可实现多个定时器互连的同步电路。
  支持定位用增量(正交)编码器和霍尔传感器电路
  外部时钟触发输入或逐周期电流管理。

4)高级控制定时器(TIM1 和 TIM8)

  高级控制定时器(TIM1 和 TIM8)包含一个 16 位自动重载计数器,该计数器由可编程预分
频器驱动。
  此类定时器可用于各种用途,包括测量输入信号的脉冲宽度(输入捕获),或者生成输出波形(输出比较、PWM 和带死区插入的互补 PWM)。
  使用定时器预分频器和 RCC 时钟控制器预分频器,可将脉冲宽度和波形周期从几微秒调制
到几毫秒。
  高级控制定时器(TIM1 和 TIM8)和通用 (TIMx) 定时器彼此完全独立,不共享任何资源。
TIM1 和 TIM8 主要特性
  16 位递增、递减、递增/递减自动重载计数器。
  16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数
介于 1 到 65536 之间。
  4 个独立通道,可用于:输入捕获/输出比较/PWM 生成(边沿和中心对齐模式)/单脉冲模式输出
  带可编程死区的互补输出。
  使用外部信号控制定时器且可实现多个定时器互连的同步电路。
  重复计数器,用于仅在给定数目的计数器周期后更新定时器寄存器。
  用于将定时器的输出信号置于复位状态或已知状态的断路输入。
  中断请求情况:发生如下事件时生成中断/DMA 请求:1.更新:计数器上溢/下溢、计数器初始化(通过软件或内部/外部触发)2.触发事件(计数器启动、停止、初始化或通过内部/外部触发计数)3.输入捕获4.输出比较5.断路输入
  支持定位用增量(正交)编码器和霍尔传感器电路
  外部时钟触发输入或逐周期电流管理。
TIM1 和 TIM8 功能
  时基单元包括:● 计数器寄存器 (TIMx_CNT)● 预分频器寄存器 (TIMx_PSC)● 自动重载寄存器 (TIMx_ARR)● 重复计数器寄存器 (TIMx_RCR)
  预分频器可对计数器时钟频率进行分频,分频系数介于 1 和 65536 之间。该预分频器基于TIMx_PSC 寄存器中的 16 位寄存器所控制的 16 位计数器。由于该控制寄存器具有缓冲功能,因此可对预分频器进行实时更改。而新的预分频比将在下一更新事件发生时被采用。
  设置预分频寄存器后,计数器由预分频器输出 CK_CNT 提供时钟。计数器将在 TIMx_CR1 寄存器的 CEN 位置 1 时刻的一个时钟周期后开始计数。
  自动重载寄存器是预装载的。对自动重载寄存器执行写入或读取操作时会访问预装载寄存
器。预装载寄存器的内容既可以直接传送到影子寄存器,也可以在每次发生更新事件 (UEV) 时传送到影子寄存器,这取决于 TIMx_CR1 寄存器中的自动重载预装载使能位 (ARPE)。当计数器达到上溢值(或者在递减计数时达到下溢值)并且 TIMx_CR1 寄存器中的 UDIS 位为 0 时,将发送更新事件。该更新事件也可由软件产生。
  影子寄存器:影子寄存器是ARM的一个特点。通过引入影子寄存器,指令可以重复使用相同的寄存器编码,但是在不同模式下,这些编码对应不同的物理寄存器。
  如果不理解也不影响编程,如果想深入了解可以看看手册和这个帖子:http://www.openedv.com/posts/list/38720.htm 个人觉得解释的不错

二、定时器工作方式

1.计数器模式

1)递增计数
  所有定时器都有递增计数模式
  在递增计数模式下,计数器从 0 计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0 开始计数并生成计数器上溢事件。

2)递减计数
  TIM1~TIM5、TIM8
  在递减计数模式下,计数器从自动重载值(TIMx_ARR 寄存器的内容)开始递减计数到 0, 然后重新从自动重载值开始计数并生成计数器下溢事件。
3)中心对齐模式(递增/递减计数)
  TIM1~TIM5、TIM8
  在中心对齐模式下,计数器从 0 开始计数到自动重载值(TIMx_ARR 寄存器的内容)-1, 生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从0 开始重新计数。
  此模式下无法写入方向位(TIMx_CR1 寄存器中的 DIR 位)。而是由硬件更新并指示当前计数器方向。
  每次发生计数器上溢和下溢时都会生成更新事件,或将 TIMx_EGR 寄存器中的 UG 位置 1(通过软件或使用从模式控制器)也可以生成更新事件。这种情况下,计数器以及预分频器计数器将重新从 0 开始计数。

2.时钟选择

1)内部时钟 (CK_INT):所有定时器。
2)外部时钟模式 1:外部输入引脚:TIM1、2、3、4、5、8、9、12
3)外部时钟模式 2:外部触发输入 ETR:TIM1、2、3、4、8
4)外部触发输入 (ITRx):使用一个定时器作为另一定时器的预分频器,例如,可将定时器1 配置为定时器 2 的预分频器。:TIM1、2、3、4、5、8、9、12

三、STM32CubeMX配置

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

计算公式
定时计算公式
不过一般情况下定时时间都是毫秒级别。
时钟频率是84Mhz这里进行84分频,就是1Mhz,也就是每秒10的6次方个脉冲。而重装载值是10000,每秒可以触发100个中断,也就是定时时间是10ms。
6.STM32F407之HAL库——定时器中断_第1张图片
然后要设置中断向量表
6.STM32F407之HAL库——定时器中断_第2张图片
接着点击GENERATE CODE生成代码。

四、代码实现

功能:实现LED0每秒翻转,LED1每10秒翻转

编写中断回调函数

这一点和标准库不同,标准库要我们自己编写中断程序,而HAL库在HAL_XXX_IRQHandler这一类的函数里面帮我们完成了,只需要自己在回调函数中加上应用程序就可以。

//定时器开启的时候记得设置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;
			}
		}
	}

}

在主函数中启动时基

	__HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE ); //清除IT标志位
	HAL_TIM_Base_Start_IT(&htim3);             //启动时基

五、参考资料等

  《STM32F4xx中文参考手册》
  感谢各位的浏览。鄙人水平有限,很多地方写的感觉差强人意,如果有不对的地方欢迎指正。

你可能感兴趣的:(#,stm32,单片机,arm)