【STM32开发之寄存器版】(六)-通用定时器中断

一、前言

STM32定时器分类

STM32103ZET6具备8个定时器TIMx(x = 1,2,...,8)。其中,TIM1和TIM8为高级定时器,TIM2-TIM6为通用定时器,TIM6和TIM7为基本定时器,本文将以TIM3通用定时器为例,分析STM32定时器工作的底层寄存器原理。

STM32通用定时器简介

STM32的通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成。使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。每个定时器都是完全独立的,没有互相共享任何资源。它们可以一起同步操作。它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)。

本文DEMO目标

本次DEMO将使用STM32F103ZET6的定时器TIM3实现DS1的翻转(定时器中断),在主函数用DS0的翻转来提示程序正在运行。

二、通用定时器的主要功能

通用TIMx (TIM2、TIM3、TIM4和TIM5)定时器功能包括:
● 16位向上、向下、向上/向下自动装载计数器
● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为 1~65536 之间的任意 数值
● 4个独立通道:
─ 输入捕获
─ 输出比较
─ PWM生成(边缘或中间对齐模式)
─ 单脉冲模式输出
● 使用外部信号控制定时器和定时器互连的同步电路
● 如下事件发生时产生中断/DMA:
─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
─ 输入捕获
─ 输出比较
● 支持针对定位的增量(正交)编码器和霍尔传感器电路
● 触发输入作为外部时钟或者按周期的电流管理

三、时钟树解析

定时器的时钟来源一共有以下4个:

  • 内部时钟(CK_INT)
  • 外部时钟模式 1:外部输入脚(TIx)
  • 外部时钟模式 2:外部触发输入(ETR)
  • 内部触发输入(ITRx):使用 A 定时器作为 B 定时器的预分频器(A 为 B 提供时钟)。

这些时钟,具体选择哪个可以通过 TIMx_SMCR寄存器的相关位来设置。这里的 CK_INT时钟是从 APB1 倍频的来的,除非 APB1 的时钟分频数设置为 1,否则通用定时器 TIMx 的时钟是 APB1 时钟的 2 倍,当 APB1 的时钟不分频的时候,通用定时器 TIMx 的时钟就等于 APB1的时钟。

本文选用CK_INT作为定时器时钟来源。
系统时钟为72MHz,AHB不分频,APB1后最大频率为36MHz,故APB1作2分频,故TIM3的时钟是APB1时钟的2倍,即TIM3CLK=72MHz。具体时钟树解析如下所示:

四、寄存器介绍

对通用定时器TIM3的控制主要涉及以下寄存器:

寄存器 作用
TIMx_CR1 控制寄存器1
TIMx_DIER DMA/中断使能寄存器
TIMx_PSC 预分频器
TIMx_SMCR 从模式控制寄存器
TIMx_CNT 计数器
TIMx_ARR 自动重装载寄存器
TIMx_SR 状态寄存器

下面将对这些寄存器进行一一介绍。

4.1 TIMx_CR1控制寄存器1

《STM32中文手册》对TIMx_CR1寄存器的描述如下:

我们仅需要关注其第7位和第0位,第7位为自动重装载允许位,具体作用见4.6节。第0位为计数器的使能位,该位必须置1,才能让定时器开始计数

4.2 TIMx_DIER DMA/中断使能寄存器

《STM32中文手册》对TIMx_DIER寄存器的描述如下:

我们仅需关注其第0位,该位为允许更新中断位,该位需要置1,才能允许更新事件所产生的中断。

4.3 TIMx_PSC预分频器

《STM32中文手册》对TIMx_PSC寄存器的描述如下:

该寄存器用于设计时钟分频,然后提供给计数器,作为计数器的时钟,该寄存器中值的范围是0-65535,按照公式fCK_CNT=fCK_PSC/(PSC[15:0]+1)。分频系数的范围为1-65536,按照前文对时钟树的解析,这里的fCK_PSC为72MHz。

4.4 TIMx_SMCR从模式控制寄存器

《STM32中文手册》对TIMx_SMCR寄存器的描述如下:

我们仅需关注该寄存器的位[2:0],即SMS从模式选择,将其设置为000,即关闭从模式,此时如果CEN=1,则预分频器直接由内部时钟驱动(CK_INT)。由于该寄存器的复位值为0X0000,故无需更改此寄存器的值。

4.5 TIMx_CNT计数器

《STM32中文手册》对TIMx_CNT寄存器的描述如下:

该寄存器是定时器的计数器,该寄存器存储了当前定时器的计数值。定时器的超时时间由下式计算:

Time = CNT / fCK_CNT

其中:

Time为超时时间,CNT为TIMx_CNT的计数值,fCK_CNT为定时器预分频频率。

4.6 TIMx_ARR自动重装载寄存器

《STM32中文手册》对TIMx_ARR寄存器的描述如下:

该寄存器包含了将要传送至实际的自动重装载寄存器的数值。该寄存器在物理上实际对应着 2 个寄存器。一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器在《STM32中文参考手册》里面被叫做影子寄存器。事实上真正起作用的是影子寄存器。根据 TIMx_CR1寄存器中 APRE 位的设置:APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器,此时 2 者是连通的;而 APRE=1 时,在每一次更新事件(UEV)时,才把预装在寄存器的内容传送到影子寄存器。我们将APRE值设置为0(复位时就是0,不用改)

4.7 TIMx_SR状态寄存器

《STM32中文手册》对TIMx_SR寄存器的描述如下:

我们只关注其第0位,该位为更新中断标记。当计数器 CNT 被重新初始化的时候,产生更新中断标记,通过这个中断标志位,就可以知道产生中断的类型。当该位为1时,表示中断产生,需要在中断服务函数中用软件对该位清0。

五、程序设计

该DEMO程序主要分为三个部分:定时器3初始化程序,定时器3中断服务程序以及轮询主函数。下面进行一一介绍。

5.1 定时器3初始化程序

该部分程序在HARDWARE/timer.c/TIM3_Int_Init(),主要作用是TIM3时钟使能、设置定时器超时值、允许中断更新、使能定时器3,并注册定时器3的中断,具体代码如下所示:

cpp 复制代码
//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
	RCC->APB1ENR|=1<<1;	//TIM3时钟使能    
 	TIM3->ARR=arr;  	//设定计数器自动重装值//刚好1ms    
	TIM3->PSC=psc;  	//预分频器7200,得到10Khz的计数时钟		  
	TIM3->DIER|=1<<0;   //允许更新中断	  
	TIM3->CR1|=0x01;    //使能定时器3
  	MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2									 
}

5.2 定时器3中断服务程序

该部分程序在HARDWARE/timer.c/TIM3_IRQHandler(),主要作用是在定时器3中断溢出时进行LED1电平翻转,并清除SR寄存器中的中断标志位。具体代码如下所示:

cpp 复制代码
//定时器3中断服务程序	 
void TIM3_IRQHandler(void)
{ 		    		  			    
	if(TIM3->SR&0X0001)//溢出中断
	{
		LED1=!LED1;			    				   				     	    	
	}				   
	TIM3->SR&=~(1<<0);//清除中断标志位 	    
}

5.3 轮询主函数

该部分程序在USER/test.c,主要作用是初始化定时器3(设置超时时间为500ms),在主循环函数中不断反转LED0电平,以示程序运行。具体代码如下所示:

cpp 复制代码
#include "sys.h"
#include "delay.h"
#include "usart.h" 
#include "led.h" 
#include "timer.h" 

int main(void)
{					   
	Stm32_Clock_Init(9);	//系统时钟设置
	uart_init(72,115200); 	//串口初始化为115200
	delay_init(72);	   	 	//延时初始化 
	LED_Init();		  		//初始化与LED连接的硬件接口
 	TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数5K次为500ms  
   	while(1)
	{
		LED0=!LED0;
		delay_ms(200);		   
	}	
}	 

六、上机测试

将程序烧录至STM32F103ZET6,可见LED1按照500ms进行翻转(定时器中断),LED0按照200ms闪烁(轮询主函数)。具体效果如下所示:

至此完成通用定时器3中断DEMO!

相关推荐
嵌新程2 小时前
day06(单片机高级)PCB设计
单片机·嵌入式硬件·pcb
stm 学习ing2 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
LateBloomer7776 小时前
FreeRTOS——信号量
笔记·stm32·学习·freertos
wenchm6 小时前
细说STM32单片机DMA中断收发RTC实时时间并改善其鲁棒性的另一种方法
stm32·单片机·嵌入式硬件
编码追梦人7 小时前
如何实现单片机的安全启动和安全固件更新
单片机
电子工程师UP学堂8 小时前
电子应用设计方案-16:智能闹钟系统方案设计
单片机·嵌入式硬件
飞凌嵌入式8 小时前
飞凌嵌入式T113-i开发板RISC-V核的实时应用方案
人工智能·嵌入式硬件·嵌入式·risc-v·飞凌嵌入式
blessing。。9 小时前
I2C学习
linux·单片机·嵌入式硬件·嵌入式
嵌新程11 小时前
day03(单片机高级)RTOS
stm32·单片机·嵌入式硬件·freertos·rtos·u575
Lin20123011 小时前
STM32 Keil5 attribute 关键字的用法
stm32·单片机·嵌入式硬件