STM32定时器的分类及中断原理

发布时间:2023-06-13  

本文主要介绍常规定时器中的TIM3,实现定时器中断的功能。STM32定时器的分类在其中一篇文章中已经介绍过,本文主要内容主要介绍定时器的基础功能-定时器中断,对于STM32定时器分类简单复习一下。


一、STM32定时器的分类


1.1 按照内核、外核、特定、常规分为4大类:

1)内核定时器:Systick

2)外设定时器:特定应用定时器+常规定时器

3)特定应用定时器:LPTIM,RTC,WTD,HRTIM

4)常规定时器:基本定时器TIM6&TIM7)、通用定时器(TIM2TIM5,TIM9TIM14)、高级定时器(TIM1&TIM8)


1.2 CPU时序

此处我们提一下学习单片机原理的课程时,提到的几个CPU时序。

振荡周期:为单片机提供定时信号的振荡源的周期。

状态周期:1个状态周期=2个振荡周期

机器周期:1个机器周期=6个状态周期=12个振荡周期

指令周期:完成1条指令所占用的全部时间,以机器周期为单位。

以12MHz外接晶振为例

振荡周期=1/12us,相当于1/12*10^6,所以单位为us;

状态周期=1/6us

机器周期=1us

指令周期=1~4us

STM32共有14组常规定时器,其实也可以称为计数器,定时器/计数器的工作过程是自动完成的,不需要CPU的参与,互相独立,执行不同的任务,可以增加单片机的效率。


二、定时器中断原理

2.1 何为定时器中断:定时器中断是由单片机中的定时器溢出而申请的中断。

提到中断,必须满足几个要素: 中断源, 中断请求 , 中断优先级。 使CPU发生中断的事件称为中断源,中断源向CPU发出中断请求,CPU暂时中断原来执行的事件A转去执行事件B,事件B处理完成后继续返回原先中断的位置(该过程称为中断返回,原先中断的地方称为断点),继续执行原先的事件。

2.2 中断流程可以用下图表示:

图片

图片

2.3 中断优先级

在这篇文章里,介绍了STM32中的 中断优先级分组、中断优先级(抢占优先级&响应优先级)、嵌套向量中断控制器NVIC等概念,那么我们定时器中断也必须满足这个规则---定时器中断也要用NVIC来设置其中断组别、抢占优先级、响应优先级。

STM32中断分组有5种

图片

#define NVIC_PriorityGroup_0 ((uint32_t)0x700)

/*!< 0 bits for pre-emption priority 4 bits for subpriority */

#define NVIC_PriorityGroup_1 ((uint32_t)0x600)

/*!< 1 bits for pre-emption priority 3 bits for subpriority */

#define NVIC_PriorityGroup_2 ((uint32_t)0x500)

/*!< 2 bits for pre-emption priority 2 bits for subpriority */

#define NVIC_PriorityGroup_3 ((uint32_t)0x400)

/*!< 3 bits for pre-emption priority1 bits for subpriority */

#define NVIC_PriorityGroup_4 ((uint32_t)0x300)

/*!< 4 bits for pre-emption priority 0 bits for subpriority */

在函数中要调用

void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)

实现对某一个中断的中断分组和优先级配置。

与定时器配置紧密相关的就是自动重装载计数器(CNT)和预分频器(PSC),初始化定时器就是对定时器的CNT、PSC进行设置。下面介绍一下与本文密切相关的几个通用定时器的寄存器

三、定时器相关寄存器及中断编程

3.1****定时器相关寄存器

3.1.1 控制寄存器TIMx_CR1

图片

位0 CEN:计数器使能,0:禁止计数器,1,使能计数器

注意:只有事先通过软件将CEN位置去,才可以使用外部时钟、门控模式、编码器模式,而触发模式可以通过硬件自动将CEN置1;在单脉冲模式下,当发生更新事件时会自动将CEN位清零。

本实验中,我们只用到了TIMx_CR1的最低位,也就是计数器使能位,该位必须置1,才能让定时器开始计数。

3.1.2 DMA中断使能寄存器 TIMx_DIER

图片

位0 UIE:更新中断使能,0:禁止更新中断,1:使能更新中断

TIMx_DIER是一个16bit的寄存器,对于要实现的中断试验,我们仅关心第0bit,因为定时器中断实验要用到定时器的更新中断,所以将该位置为1,表示允许更新时间所产生的中断。

3.1.3预分频寄存器TIMx_PSC

图片

位0:15 PSC:预分频器值。(范围是0~65535)

表示计数器时钟频率CK_INT 等于Fck_psc/(PSC[15:0]+1).PSC包含在每次发生更新事件时要装载到实际预分频器寄存器的值。(84MHz的CK_INT,那计数器的时钟频率为84/(PSC[15:0]+1)MHz,计数器时钟的取值范围为(0.00128~84)MHz,那么计数器时钟周期为0.012us(84MHz)~781us(0.001MHz);

这个地方要注意:预分频值=实际分频值-1,如果要设定实际分频值为8400(定时器的工作频率为10kHz),那我们设定预分频值为8399

也再复习一下定时器的时钟知识:

1.STM32总的有3种时钟源,分为 内部时钟、外部时钟、锁相环倍频输出时钟,包含LSI,LSE,HSI,HSE等;

2.系统时钟为168MHz,其他时钟都是通过分频(系统时钟除以一个分频系数)给系统的各板块使用;

3.看下图三个红色框的部分,系统时钟(以F407系列为例)是168MHZ,通过设置不同的分频值给AHB总线,看第一个红框,可以设置为1.2...512,然后AHB总线再分频给APB分线,看第二个红框,再次分频的值可以为1.2.4.8.16,上面的是直接分频过后给APBx外设时钟使用,我们重点看第二根线,注意第三个红框,如果APBx的分频值设置为1,那么APBx的定时器时钟的时钟频率设置为与APB一样,如果是其他的数字,那么设置为APB的时钟频率的两倍。通过查手册知道两个基本定时器的时钟频率都归属于APB线上的,且APB1和APB2的分频系数都不为1(可以通过中找到配置),因此基本定时器的时钟频率已经确定。

图片

看下面这张图,在文件system.stm324fxx.c中可以找到,

第一行表示系统时钟来源是HSE,之前提过,它是高速外部时钟,由外部晶振产生,第二三行表示系统时钟设置为168MHZ(由外部时钟HSE倍频实现,具体这里不深究),第四五六行,分别表示AHB,APB1,APB2的分频系数,即分别设置为168MHZ,42MHZ,84MHZ。

注意,如前所述APB1的分频值为4,不为1,故其包含的基本定时器模块的时钟频率需乘2,即42×2为84MHZ。由此我们得知基本定时器的时钟源为84MHZ。

图片

1)内部时钟(CK_INT)

2)外部时钟模式1:外部输入引脚(TIx)

3)外部时钟模式2:外部触发输入(ETR)用于TIM2.TIM3.TIM4

4)内部触发输入(ITRx),使用定时器A作为B定时器的预分频(A为B提供时钟)

这些时钟,具体选择哪个可以通过TIMx_SMCR寄存器的相关位来设置,CK_INT时钟是从APB1倍频来的,除非APB1的时钟分频数设置为1,否则通用定时器TIMx的时钟是APB1时钟的2倍,当APB1时钟不分频时,通用定时器的时钟就等于APB1的时钟,这里还要注意的就是高级定时器以及TIM9~TIM11的时钟是来自APB2。

3.1.4 TIMx_CNT计数器

图片

位15:0 CNT[15:0]:计数器值,该寄存器存储了当前寄存器的计数值。范围为065535,可以计时的范围是051s(假定是分频PSC设为65535,计数器时钟频率是84/65536MHz,每个时钟脉冲周期为781us)

3.1.5自动重载寄存器(TIMx_ARR)

图片

位15:0 ARR[15:0]:自动重载值。

ARR是要装载到实际自动重载寄存器的值。需要注意,该寄存器在物理上实际对应着2个寄存器,一个是程序员可以直接配置的,另外一个是程序员看不到的,这个看不到的寄存器叫影子寄存器,在《STM32F4xx中文参考手册》里面有提到,事实上真正起作用的是影子寄存器,根据TIMx_CR1寄存器中的APRE位的设置:APRE=0,预装载寄存器的内容可以随时传送到影子寄存器,此时两者是连通的;而APRE=1时,每一次更新事件(UEV)时,才能把预装载寄存器ARR的内容传送到影子寄存器。

3.1.6状态寄存器(TIMx_SR)

图片

位0 UIF:更新中断标志。

  • 该位在发生更新事件时通过硬件置1,但需要通过软件清零。0:未发生更新,1:更新中断挂起

  • 上溢或者下溢(对于TIM2~TIM5)以及当TIMx_CR1寄存器UDIS=0时,

  • TIMx_CR1中的寄存器中的URS=0且UDIS=0,并且由软件使用TIMx_EGR寄存器中的UG位重新初始化CNT时。TIMx_CR1寄存器中的URS=0&UDIS=0,并且由CNT由触发事件重新初始化。

3.2定时器中断编程

3.2.1编程步骤

1)TIM3时钟使能,通过APB1ENR的第1位来设置TIM3的时钟,APB1的分频系数是4,那么APB1为168/4=42MHz,TIM3时钟是APB1时钟的2倍,等于84MHz.

2)设置TIM3_ARR和TIM3_PSC的值,通过这两个寄存器,设置自动重装值和分频系数,这两个参数加上时钟频率决定了定时器的溢出事件。

3)设置TIM3_DIER允许更新中断。因为我们要使用TIM3的更新中断,所以设置DIER的UIE位为1,使能更新中断

4)允许TIM3工作。设置好定时器参数后,还需要开启定时器,通过TIM3_CR1的CEN位来设置

5)TIM3中断分组设置。配置完定时器后,因为要产生中断,必须要设置NVIC相关寄存器,以使能TIM3中断。

6)编写中断服务函数。在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型,然后执行相关的操作,这里采用的是更新(溢出)中断,所以要关注状态寄存器的SR的最低位,在处理完成之后,将TIM3_SR的最低位写0,来清除该中断标志。

以下是定时器3的中断测试代码

//通用定时器3中断初始化

//时钟选择为APB1的2倍,APB1=42MHz

//arr:自动重载值

//psc:时钟预分频数

//定时器溢出时间:Tout=((arr+1)*(psc+1))/ft

//ft=定时器的工作频率,MHz

void TIM3_Int_Init(u16 arr,u16 psc)

{

RCC->APB1ENR|=1<<1;//TIM3时钟使能    

 TIM3->ARR=arr;  //设定计数器自动重装值 

TIM3->PSC=psc;  //预分频器  

TIM3->DIER|=1<<0;   //允许更新中断  

TIM3->CR1|=0x01;    //使能定时器3

MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2 }

//定时器3中断服务程序   

void TIM3_IRQHandler(void)

{                         

  if(TIM3->SR&0X0001)//溢出中断

  {

    LED1=!LED1;                                          

  }           

  TIM3->SR&=~(1<<0);//清除中断标志位       

}


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    外部中断0/1(2024-08-15)
    总开关     IT0 = 1;//外部中断0出发方式:0为电平、1为下降沿  //定时器的是要启动 } //主函数 void main(void) {     kinson();//寄存......
    } 29  30 void ser_int() interrupt 4                //3定时器1的中断号  1定时器0的中断号 0外部中断1 2外部中断2  4串口中断 31......
    一定有最基本的5个中断中断: 外部中断0(INTO)、外部中断 1(INT1)、外部中断 2(INT2)、外部中断 3(INT3)、定时器 0中断定时器 1 中断定时器 2 中断、串口......
    s3c2440裸机-异常中断(五. irq之定时器中断);之前讲过s3c2440时钟体系,看了时钟体系再来看定时器中断会更好的结合运用所学知识点。 S3c2440共有2种定时器1......
    s3c2440裸机-异常中断5-irq定时器中断;之前讲过s3c2440时钟体系,看了时钟体系再来看定时器中断会更好的结合运用所学知识点。 S3c2440共有2种定时器1.Watchdog看门狗定时器......
    使能位,对应关系如下: IE寄存器 C51中的 8051的 的使能位 中断号 中断源 -------------------------------- IE.0 0 外部中断0 IE.1 1 定时器0......
    向量 --------------------------- 上电复位 0000H 外部中断0 0003H 定时器0 溢出 000BH 外部中断1 0013H 定时器1 溢出 001BH 串行口中断......
    中断源,多了一个定时器 2 中断),x 即为“中断号”: 上面的程序是定时器 0 的中断服务程序,因此是 interrupt 1;要是想按一个键进行中断,那么就是外部中断,因此......
    的实现相对比较简单,仅需一个函数即可实现TIM1-TIM17定时器的中断更新配置。 33.2.1 定时器中断初始化 实现代码如下: 1.    /*  2......
    行位寻址),定时器0运行控制位TR0便在其中。 启动定时器0,即TR0=1;(在上述GATE=0的前提下) 4.中断服务程序写法 void 函数名() interrupt 中断号 { 中断......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>