少女祈祷中...

定时中断

EXIT

EXTI(External Interrupt)是一种外部中断功能,它允许微控制器(MCU)响应外部事件或信号。外部中断是一种重要的硬件特性,它使得微控制器能够在特定事件发生时立即采取行动,而无需持续轮询或检查外部引脚的状态,从而提高了系统的效率和响应速度。 外部中断通常由微控制器的某个输入引脚触发。当这个引脚的电平变化(例如,从低电平变为高电平,或从高电平变为低电平)或达到某个特定的电平持续时间时,EXTI会生成一个中断请求。微控制器的中断控制器接收到这个请求后,如果相应的中断使能位已经被设置,就会触发一个中断服务例程(ISR),执行预定义的中断处理代码。

在配置EXTI时,开发者需要指定以下参数:

中断引脚:选择哪个GPIO(通用输入输出)引脚作为外部中断的输入。

触发模式

上边沿:指的是数字信号从低电平(0)跳变到高电平(1)的瞬间。

下降沿:数字信号从高电平(1)跳变到低电平(0)的瞬间。

双边沿:双边沿意味着无论信号是从低到高还是从高到低,任何一种跳变都会触发中断或事件处理。

中断优先级:根据需要处理中断的紧迫性,设置中断的优先级。 中断使能:启用或禁用外部中断功能。

TIM定时器

输入捕获

输出比较

编码器接口

主从触发模式

image.png

基本定时器

预分频器:对输入的基准频率提前进行一个分频的操作。

计数器:对预分频的计数时钟进行计数,计数时钟每来一个上升沿,计数器+1(0~65535)

自动重装寄存器:存的是写入的计数目标,当计数值等于自动重装值,那就是计时时间到,产生中断信号清零计数器。

更新中断:通往NVIC

更新事件:不会触发中断,但会触发内部其他电路工作。

image.png

通用定时器

向上计数模式

向下计数模式

中央对齐模式

image.png

定时中断基本结构

image.png

第一步,开启RCC时钟

第二步,选择时基单元的时钟源(对于定时中断选择内部时钟模式)

第三步,配置时基单元

第四步,配置输出中断控制,允许更新中断输出到NVIC

第五步,配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级

第六步,使能计数器

配置所用到的库函数

(1)恢复缺省配置

Tim.h第1054

1
TIM_DeInit(TIM_TypeDef* TIMx);

(2)时基单元初始

Tim.h第1055

1
TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

(3)把结构体变量赋默认值

Tim.h第1063

1
TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

(4)使能计数器(对应运行控制)

(计数器的种类,使能/失能)

Tim.h第1067

1
TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

(5)使能中断输出信号

Tim.h第1069

(选择定时器,选择中断输出,使能/失能)

1
TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

(6)时基单元的时钟选择部分

选择内部时钟模式

1
TIM_InternalClockConfig(TIM_TypeDef* TIMx);

ITRx-外部时钟模式1

1
TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);

(选择定时器类型,选择TIx某个引脚,输入的极性,输入的滤波器)

TIx捕获通道-外部时钟模式

1
TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);

ETR外部时钟-外部时钟模式1

(选择定时器类型,外部触发预分频器,输入的极性,输入的滤波器)

1
TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);

ETR外部时钟-外部时钟模式2

(选择定时器类型,外部触发预分频器,输入的极性,输入的滤波器)

1
2
TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

单独配置ETR引脚的预分频器,极性,滤波器

1
TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);

(7)单独修改预分频值

1
2
TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);
//(选择定时器类型,要写入的预分频值,写入的模式)

(8)改变计数器的计数模式

1
TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);

(9)自动重装器预装功能配置

1
TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

(10)手动给计数器一个计数值

1
TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

(11)手动给自动重装器一个计数值

1
TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

(12)获取当前计数器的值

1
TIM_GetCounter(TIM_TypeDef* TIMx);

(13)获取当前预分频值的值

1
TIM_GetPrescaler(TIM_TypeDef* TIMx);

(14)获取标志位和清除标志位

1
2
3
4
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

结构体的参数

1
2
3
TIM_TimeBaseInitStructure.TIM_Period=1000-1;//ARR自动重装器的值
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;//PSC预分频器的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//RCC重复计数器的值(高级定时器才有)

image.png

若想定时1s,(定时频率为1HZ“)

对72M进行7200分频,得到10K的计数频率,计10000个数,就是1s

预分频器时序

image.png
CK_PSC:预分频器的输入时钟(选内部时钟一般是72HZ)
CNT_EN:CEN(计数器使能)是控制寄存器1(CR1)中的一个位,位于位0。这个位用于启动或停止定时器的计数器。当CEN位被设置为1时,定时器的计数器开始计数;当它被清零(设置为0)时,计数器停止计数。
CK_NET:计数器时钟

代码

定时中断Timer.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
//开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//配置时钟源
TIM_InternalClockConfig(TIM2);//选择TIM2
//时基单元初始化
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//计时器模式
TIM_TimeBaseInitStructure.TIM_Period=1000-1;//ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;//PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//开启TIM2更新中断

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置NVIC

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
//TIM使能
TIM_Cmd(TIM2, ENABLE);

}

定时器外部时钟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启TIM2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟

/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA0引脚初始化为上拉输入

/*外部时钟配置*/
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F)

/*时基单元初始化*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;//ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;//PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

/*中断输出配置*/
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除定时器更新标志位

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//开启TIM2的更新中断

/*NVIC中断分组*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC为分组2

/*NVIC配置*/
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//选择配置NVIC的TIM2线
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//指定NVIC线路的抢占优先级为2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//指定NVIC线路的响应优先级为1
NVIC_Init(&NVIC_InitStructure); //将结构体变量交给NVIC_Init,配置NVIC外设

/*TIM使能*/
TIM_Cmd(TIM2, ENABLE);//使能TIM2,定时器开始运行
}


uint16_t Timer_GetCounter(void)
{
return TIM_GetCounter(TIM2);//返回定时器TIM2的CNT
}