什么是定时器中断函数 【STM32】一下_TimeBaseInitTypeDef_Int_Init

首先我们看一下文件timer.c中控制定时器中断的源码:

#include"timer.h"
#include"led.h"
//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3
voidTIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //①时钟TIM3使能
//定时器TIM3初始化
TIM_TimeBaseStructure. TIM_Period = arr;//设置自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1; //设置时钟分割
TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;  //TIM向上计数
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //②初始化TIM3
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );//③允许更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel =TIM3_IRQn;  //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;  //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 3;  //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //④初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE);  //⑤使能TIM3
}
//定时器3中断服务程序⑥
voidTIM3_IRQHandler(void)   //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update  ); //清除TIM3更新中断标志
LED1=!LED1;
}
}

前两行是头文件的声明。我们将在这里忽略它。我们今天主要讲的是函数TIM3_Int_Init()。

这个函数的前两行构造了两个结构体,我们右击它们,Go To Definition看看这两个结构体是如何定义的:

typedef struct
{
u16 TIM_Period;
u16 TIM_Prescaler;
u8 TIM_ClockDivision;
u16 TIM_CounterMode;
} TIM_TimeBaseInitTypeDef;

typedef struct
{
u8 NVIC_IRQChannel;
u8 NVIC_IRQChannelPreemptionPriority;
u8 NVIC_IRQChannelSubPriority;
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;

如果您在阅读了以上内容后理解了以上内容,则不必阅读以下内容。如果你还处于迷茫状态,可以继续阅读。

首先我们看一下结构体TIM_TimeBaseInitTypeDef的各个成员

**TIM_Period**

TIM_Period 设置在下一次更新事件时加载的活动自动重载寄存器周期的值。它的值必须在 0x0000 和 0xFFFF 之间。 (以0x开头表示这是一个十六进制数。在C语言中,0xFFFF表示该数字的后十六位全为1。如果数字类型是short,则表示-1,如果是int类型的数字,则表示 65535。)

**TIM_Prescaler**

TIM_Prescaler 设置用作 TIMx 时钟频率除数的预分频器值。它的值必须在 0x0000 和 0xFFFF 之间。

TIM_ClockDivision

TIM_ClockDivision 设置时钟分频。

分别为无分频、2分频、4分频。

TIM_CounterMode

TIM_CounterMode 选择计数器模式。该参数的取值如下表所示。

一般来说,TIM_Period 是一个周期内计算的次数。成员的数据类型应该是int,所以这里它的取值范围是0-65535,TIM_Prescaler决定了一个周期需要的定时器。时间。

现在我们看源码,可以发现他让TIM_Period = arr;TIM_Prescaler =psc,因为arr和psc是传参数,传过来的值是4999和7199。所以arr=4999,psc =7199.由此可知,这个定时器的一个周期需要计数5000次(因为它是从0开始的)。这时候我们的定时器一个周期的时间就可以计算出来了。计算公式为:

Tout=((arr+1)*(psc+1))/Tclk

地点:

Tclk:TIM3的输入时钟频率(单位为Mhz),从源码顶部注释可以看出,这里的时钟选择是APB1的2倍,APB1为36M,所以输入时钟TIM3的频率为72Mhz,即Tclk =72.

Tout:TIM3溢出时间(单位是us),从上面的数据我们可以计算出Tout=((arr+1)*(psc+1))/Tclk=500000us=500ms。即a循环时间为 500ms。

接下来我们将时钟分频设置为TIM_CKD_DIV1或者0。计数方式是向上计数,其实这里倒数也没问题。

这样,我们调用函数TIM_TimeBaseInit()来初始化定时器TIM3.

TIM_TimeBaseInitTypeDef的结构到这里解释完了。

现在我们来看第二个结构体:NVIC_InitTypeDef 的成员

NVIC_IRQChannel

此参数用于启用或禁用指定的IRQ通道。

NVIC_IRQChannelPreemptionPriority

该参数设置成员NVIC_IRQChannel中的抢占优先级

NVIC_IRQChannelSubPriority

该参数设置成员NVIC_IRQChannel中的slave优先级,

**NVIC_IRQChannelCmd

**

该参数指定成员NVIC_IRQChannel中定义的IRQ通道是启用还是禁用。此参数的值为 ENABLE 或 DISABLE。

NVIC_IRQChannel可以取的值这里就不详细解释了,但是可以在很多资料中找到。这里我只是想解释一下抢占和从属优先级。

第一优先级决定了CPU响应的顺序(STM32中0优先级最高)。举个简单的例子什么是定时器中断函数,比如有人给你打电话什么是定时器中断函数,优先级为0,如果有人在QQ上给你发消息,优先级为1。级别,当有人打电话给你,同时发QQ消息,那么你必须先接电话,即使在QQ聊天的时候有人打电话给你,你也要先接电话,然后把聊天放在一边。

从属优先级是第一优先级相同时比较的优先级。例如,如果同时发生一个优先级为 1 的事件,则优先执行从属优先级较高的行为。

现在,我的time.c中的代码基本解释完了,现在我们来看看main.c中的源码:

int main(void)
{        
     delay_init();     //延时函数初始化
     NVIC_Configuration();      //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
     LED_Init();                        //初始化与LED连接的硬件接口
TIM3_Int_Init(4999,7199);  //10Khz的计数频率,计数5000为500ms
     while(1)
     {
              LED0=!LED            
              delay_ms(200);                    
     }
}

这里的代码很简单,最重要的是理解NVIC_Configuration()函数。我们去定义看看:

NVIC_PriorityGroupConfig()中的参数值如下:

NVIC_PriorityGroup|NVIC_IRQChannel 的抢占优先级|NVIC_IRQChannel 的从属优先级|说明

——|—————————-| ——————————

NVIC_PriorityGroup_0|0|0-15|第一优先级0,从优先级4开始

NVIC_PriorityGroup_1|0-1|0-7|优先级 1 优先,优先级 3 优先

NVIC_PriorityGroup_2|0-3|0-3|第一优先级 2,第二优先级 2

NVIC_PriorityGroup_3|0-7|0-1|第一个优先级 3,从优先级 1 开始

NVIC_PriorityGroup_4|0-15|0|第一优先级 4

这里的意思是将某一组事件分组。分组后,给每个组优先级,然后在同一组中划分优先级。至于后面介绍的位,是因为Cortex-M3允许更多中断源较少时,使用较少的寄存器位来指定中断源的优先级,所以STM32将指定中断优先级的寄存器位减少到4位这4个寄存器位的分组方法如下:

Group 0:所有 4 位用于指定响应优先级

Group 1:最高1位用于指定抢占优先级,最低3位用于指定响应优先级

Group 2:最高2位用于指定抢占优先级,最低2位用于指定响应优先级

Group 3:最高3位用于指定抢占优先级,最低1位用于指定响应优先级

第 4 组:所有 4 位用于指定抢占式优先级

您可以通过调用STM32固件库中的函数来选择使用哪种优先级分组方式。该函数的参数如下:

NVIC_PriorityGroup_0 => 选择组 0

NVIC_PriorityGroup_1 => 选择组 1

NVIC_PriorityGroup_2 => 选择第 2 组

NVIC_PriorityGroup_3 => 选择第 3 组

NVIC_PriorityGroup_4 => 选择第 4 组

在main.c中我们设置NVIC中断组2:2位抢占优先级,2位响应优先级

在timer.c中,TIM3中断的抢占优先级设置为0级,次要优先级设置为3级。

笔记就写到这里了,其余的都比较基础,这里就不多解释了。

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论