基本定时器的作用只是仅仅的作为定时器使用,没有输入输出通道。通用定时器具有多路的输出通道,可用于输入捕获和输出比较,也可以用做时基,高级定时器除了通用定时器的功能,还具有刹车。
基本定时器:
可以看出基本定时器的时钟来源为内部时钟APB上,主要由时基单元的构成(PSC,ARR,CNT)
当计数值达到重装载的数值后会产生事件,如果想要产生中断和DMA要做相应的软件(代码)的处理,以及触发DAC的功能, 目前我还没用过触发DAC,后期如果用上了载进行补充,小伙伴们们如果知道的可以告诉我,我会细心的分析。
回顾一下之前的时钟图,如果分频系数不为一的时候,定时器的时钟为240Mhz(这里仅仅只针对H7,其他的可以参考相应的数据手册和参考手册)
从图中可以看出预分频器PSC和重装载的ARR下面有一块阴影的区域:官方叫影子寄存器。不可以直接访问,我们可以把预分频系数写入预分频器寄存器(TIMx_PSC), 但是预分频器寄存器只是起到缓存数据的作用,只有等到更新事件发生时,预分频器寄存器的 值才会被自动写入其影子寄存器中,这时才真正起作用。(自我理解:这两个寄存器是充了VIP,有个保安,当你访问的时候,要有请柬才可以,不能直接访问,请柬到了同意才能访问。开个玩笑)
相关几个重要的寄存器的理解:
控制寄存器CR1:
主要额就是位0:用于禁止和使能计数位。还有位7的ARR是否有缓存的功能的开启。
DMA/中断使能寄存器(TIM_DIER):
状态寄存器(TIM_SR):
其实那么多的寄存器最好的理解的办法是分析代码,看看别人的代码应用在那些地方,
注意:基本定时器中断额模式只有递增,只仅仅适合用做定时用。想要更多的功能还是用通用定时器和高级定时器。
附上一小段代码:(tim6和TIM7的控制LED1和LED2)
TIM.C:
#include "./SYSTEM/TIM6/tim6.h"
#include "./BSP/LED/led.h"
TIM_HandleTypeDef tim6;
TIM_HandleTypeDef tim7;
/**
* @brief 初始化TIM6
* @retval 无
*/
void jiben_tim6_init(uint16_t arr, uint16_t psc)
{
tim6.Instance = BTIM_TIM6_INT; /* 定时器 x */
tim6.Init.Prescaler = psc; /* 预分频 */
tim6.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数器 */
tim6.Init.Period = arr;
HAL_TIM_Base_Init(&tim6);
HAL_TIM_Base_Start_IT(&tim6); /* 使能定时器 x 和定时器 x 更新中断 */
}
/**
* @brief 初始化TIM7
* @retval 无
*/
void jiben_tim7_init(uint16_t arr, uint16_t psc)
{
tim7.Instance = BTIM_TIM7_INT; /* 定时器 x */
tim7.Init.Prescaler = psc; /* 预分频 */
tim7.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数器 */
tim7.Init.Period = arr;
HAL_TIM_Base_Init(&tim7);
HAL_TIM_Base_Start_IT(&tim7); /* 使能定时器 x 和定时器 x 更新中断 */
}
/**
* @brief 定时器 底层驱动,开启时钟,设置中断优先级
此函数会被 HAL_TIM_Base_Init()函数调用
* @param 无
* @retval 无
*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == BTIM_TIM6_INT) /* 定时器6的中断的配置的操纵*/
{
BTIM_TIM6_INT_CLK_ENABLE(); /* 使能 TIMx 时钟 */
/* 设置中断优先级,抢占优先级 1,子优先级 3 */
HAL_NVIC_SetPriority(BTIM_TIM6_INT_IRQn, 1, 3);
HAL_NVIC_EnableIRQ(BTIM_TIM6_INT_IRQn); /* 开启 ITMx 中断 */
}
else if (htim->Instance == BTIM_TIM7_INT) /* 定时器7的中断的配置的操纵*/
{
BTIM_TIM7_INT_CLK_ENABLE(); /* 使能 TIMx 时钟 */
/* 设置中断优先级,抢占优先级 1,子优先级 3 */
HAL_NVIC_SetPriority(BTIM_TIM7_INT_IRQn, 1, 3);
HAL_NVIC_EnableIRQ(BTIM_TIM7_INT_IRQn); /* 开启 ITMx 中断 */
}
}
/**
* @brief 定时器6中断服务函数
* @param 无
* @retval 无
*/
void BTIM_TIM6_INT_IRQHandler(void)
{
HAL_TIM_IRQHandler(&tim6);
}
/**
* @brief 定时器7中断服务函数
* @param 无
* @retval 无
*/
void BTIM_TIM7_INT_IRQHandler(void)
{
HAL_TIM_IRQHandler(&tim7);
}
/**
* @brief 定时器更新中断回调函数
* @param htim:定时器句柄指针
* @retval 无
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == BTIM_TIM6_INT)
{
LED0_TOGGLE();
//LED1_TOGGLE();
}
else if (htim->Instance == BTIM_TIM7_INT)
{
LED1_TOGGLE();
}
}
TIM.H:
#ifndef __TIM6_H
#define __TIM6_H
#include "./SYSTEM/sys/sys.h"
/******************************************************************************************/
/* TIMX 中断定义
* 默认是针对 TIM2~TIM5, TIM12~TIM17.
* 注意: 通过修改这 4 个宏定义,可以支持 TIM1~TIM17 任意一个定时器.
*/
#define BTIM_TIM6_INT TIM6
#define BTIM_TIM6_INT_IRQn TIM6_DAC_IRQn
#define BTIM_TIM6_INT_IRQHandler TIM6_DAC_IRQHandler
#define BTIM_TIM7_INT TIM7
#define BTIM_TIM7_INT_IRQn TIM7_IRQn
#define BTIM_TIM7_INT_IRQHandler TIM7_IRQHandler
/* TIM6 时钟使能 */
#define BTIM_TIM6_INT_CLK_ENABLE() do{ __HAL_RCC_TIM6_CLK_ENABLE(); }while(0)
/* TIM7 时钟使能 */
#define BTIM_TIM7_INT_CLK_ENABLE() do{ __HAL_RCC_TIM7_CLK_ENABLE(); }while(0)
/* TIM6 函数的初始化 */
void jiben_tim6_init(uint16_t arr, uint16_t psc);
void jiben_tim7_init(uint16_t arr, uint16_t psc);
#endif
通用定时器:
话不多说,先上图(看图说话):stm32h750通用定时器的图:
每次看这张图:都会觉得H7的TIM9.TIM10.TIM11怎么没了,F4的芯片上就有,没办法,芯片厂商制造的。
与基本定时器相比,通用定时器不仅仅能定时,还能计数,输入捕获,输出比较,有的还有4个通道,计数模式下还支持三种方式(还怪牛逼的啊!但是和高级的相比还是不行的。)
这个图看着才叫舒服呢:分别包括了时钟源的部分,控制器部分,时基单元,输入捕获,输出比较,对于图中的紫色的部分是输入捕获和输出比较的公用体,
下面来分析:
时钟源:
1
)内部时钟
(CK_INT)
2
)外部时钟模式
1
:外部输入引脚
(TIx)
,
x=1
,
2
(即只能来自于通道
1
或者通道
2
)
3
)外部时钟模式
2
:外部触发输入
(ETR)
4
)内部触发输入
(ITRx)
:使用一个定时器作为另一定时器的预分频器
大多数用的是一和二,二多用来检测编码器来检测小车的转速。
对于时钟模式的选择可以通过寄存器TIMx_SMCR的SMS位来进行选择和控制
1。内部时钟的配:CK_INT:通用定时器处理TIM15~17在APB2总线上以外其他的几个定时器都在APB1的总线上,时钟频率位240mHZ. 时钟的频率的范围可以从在软件(代码SYS_STM32_CLOCK中进行修改D2PPRE2的分频因子的大小来进行修改。)如果时钟记得不太清楚了,可以参考和回顾具体可以参考《STM32H7xx 参考手册_V3(中文版).pdf》第 290 页,表 47。 多看看就好了。
2.外部时钟模式1(TI1,TI2): (采用该模式要将时钟配置位外部始终模式一:SMS为0111)
这是上面图的分图:
外部时钟源信号
→
IO
→
TIMx_CH1
(或者
TIMx_CH2
),这里需要注意的是:外部时钟模
式
1
下,时钟源信号只能从
CH1
或者
CH2
输入到定时器,
CH3
和
CH4
都是不可以的。从
IO
到
TIMx_CH1
(或者
TIMx_CH2
),就需要我们配置
IO
的复用功能,才能使
IO
和定时器通道相
连通。 (玩编码器的时候要注意了,别接在通道三和四上了)
这里以通道二为例,通道一预期类似,(再次提醒,通道三和通道四不支持) 具体流程:时钟源信号二(TI2)到来的后,经过选择滤波器的状态。也可以不进行滤波,在通过边沿检测电路(上升沿和下降沿)触发后,来到出发选择的开关,选择触发信号的来源,TI1F_ED 表示来
自于
CH1
,并且没有经过边沿检测器过滤的信号,所以它是
CH1
的双边沿信号,即上升沿或者
下降沿都是有效的。
TI1FP1
表示来自
CH1
并经过边沿检测器后的信号,可以是上升沿或者下
降沿。
TI2FP2
表示来自
CH2
并经过边沿检测器后的信号,可以是上升沿或者下降沿。这里以
CH2
为例,那只能选择
TI2FP2
。如果是
CH1
为例,那就可以选择
TI1F_ED
或者
TI1FP1
。
最后经过从模式选择器,由
ECE
位和
SMS[2:0]位来选择定时器的时钟源。这里我们介绍
的是外部时钟模式
1
,所以
ECE
位置
0
,
SMS[2:0] = 111
即可。
CK_PSC
需要经过定时器的预分
频器分频后,最终就能到达计数器进行计数了。(是不是很简单!!!!)
3.外部时钟模式1(ETR): 时钟!时钟!时钟
通常在看看数据手册的时候会有TIM_ETR的引脚的复用和重映射,当时浏览器搜索过,也没太多的在意,
这个时钟源的来头就比较有意思了,来源于IO口,用到IO口就要将其设置为复用的模式,从图中看先经过TIMx_AF1的ETRSEL[3:0]选择时钟源来自IO口,
不是所有的定时器都有这个寄存器的功能的 接着经过外部触发时钟极性选择器,TIMx_SMCR的ETR来控制上升沿和下降沿有效,选择下降沿的化会经过一个反相器 。然后来到分频器ETPS选择分频系数的大小 (外部触发信号 ETRP 频率不得超过 CK_INT 频率的 1/4)
紧接着经过滤波器器,由
ETF[3:0]
位来设置滤波方式,也可以设置不使用滤波器。
fDTS
由
TIMx_CR1
寄存器的
CKD
位设置。(
一般不进行滤波,当然也有二般的情况
)
最后经过从模式选择器,由
ECE
位和
SMS[2:0]
位来选择定时器的时钟源。这里我们介绍
的是外部时钟模式
2
,直接把
ECE
位置
1
即可。
CK_PSC
需要经过定时器的预分频器分频后,
最终就能到达计数器进行计数了。
4。内部触发输入
内部触发输入是使用一个定时器作为另一个定时器的预分频器,即实现定时器的级联。(目前还没用过。)
控制器单元:
控制器包括:从模式控制器、编码器接口和触发控制器(
TRGO
)。从模式控制器可以控制
计数器复位、启动、递增
/
递减、计数。编码器接口针对编码器计数。触发控制器用来提供触发
信号给别的外设,比如为其它定时器提供时钟或者为
DAC/ADC
的触发转换提供信号。
时基单元:
与基本定时器类似,主要三大块构成,可以参考基本定时器():不同点在与计数模式支持递增,递减,中心对其的模式且TIM2和TIM5是32位的可以计数的时间更长,
输入捕获:
通过相应的定时器的四个通道的复用和输入的配置:大多数测量信号的脉冲宽度,测量PWM的脉冲输入信号的频率和占空比,测量高电平脉冲宽度的工作原理,方便大家的理解:一般先要设置输入捕获的边沿检测极性,如:我们设置上升沿检测,那么当检测到上升沿时,定时器会把计数器 CNT的值锁存到相应的捕获/比较寄存器 TIMx_CCRy 里,y=1~4。然后我们再设置边沿检测为下降
沿检测,当检测到下降沿时,定时器会把计数器
CNT
的值再次锁存到相应的捕获
/
比较寄存器 TIMx_CCRy 里。最后,我们将前后两次锁存的
CNT
的值相减,就可以算出高电平脉冲期间内 计数器的计数个数,再根据定时器的计数频率就可以计算出这个高电平脉冲的时间。如果要测 量的高电平脉宽时间长度超过定时器的溢出时间周期,就会发生溢出,这时候我们还需要做定 时器溢出的额外处理。低电平脉冲捕获同理。
流程的大致的分析:(看的多了可以自己先行分析一下:受人已渔不如受人已鱼)
信号来到后,命名为TI1,经过滤波器进行滤波(通过寄存器的配置选择)后来到边沿的检测的电路,检测是上升沿和下降沿 下面的CC1P/CC1NP为互补通道的边沿检测,只有高级定时器才有,再通过通道映射选择O1(通道一)后进行分频系数的调整后经过使能位的使能后捕获信号IC1PS进入通到五的公共部分区域,看下图:
以通道
1
输入为例,
CC1S[1:0] = 01
,即
IC1
映射到
TI1
上;
CC1E
位置
1
,使能输入
捕获;比如不滤波、不分频,
ICF[3:0] = 00
,
ICPS[1:0] = 00
;比如检测上升沿,
CC1P
位置
0
;
接着就是等待测量信号的上升沿到来。当上升沿到来时,
IC1PS
信号就会触发输入捕获事件发
生,计数器的值就会被锁存到捕获
/
比较影子寄存器里。通过读取寄存器CCR1的数值可到到相应的捕获内容。
输出比较
写入比较值。这个比较值需要转移到对应的捕获
/比较影子 寄存器后才会真正生效。可以看到 compare_transfer 旁边的与门,需要满足三个条件:CCR1 不在写入操作期间、CC1S[1:0] = 0 配置为输出、OC1PE 位置0(或者 OC1PE 位置 1,并且需要发生更新事件,)
CC1P
位用于选择通道输出极性。
CC1E
位置
1
使能通道输出。
OC1
信号就会从
TIMx_CH1
输出到
IO
端口,再到
IO 外部。
通用定时器的中断的实验:
寄存器的配置:可以参考基本定时器和参考手册:
相关的代码:见上面的基本定时器的程序的代码:无非就是改改定时器号,中断号,中断入口,
注意:再次提醒,定时器的15 ,16,17在APB2上,而不是在APB1上。
通用定时器的PWM的输出实验:(脉宽调制实验):(用到的单元为3.5.6)
老样子,先上图:
我们可以让定时器产生
PWM
, 在计数器频率固定时,PWM
频率或者周期由自动重载寄存器(
TIMx_ARR
)的值决定,其占空 比由捕获/
比较寄存器(
TIMx_CCRx
)的值决定。
定时器工作在递增计数模式,纵轴是计数器的计数值 CNT,横轴表示时。当
CNT<CCRx 时,IO 输出低电平(逻辑 0);当 CNT>=CCRx 时,IO 输出高电平(逻辑 1);当
CNT=ARR 时,定时器溢出,CNT 的值被清零,然后继续递增,依次循环。在这个循环中,改
变 CCRx 的值,就可以改变 PWM 的占空比,改变 ARR 的值,就可以改变 PWM 的频率,这就
是 PWM 输出的原理。
STM32H750
的定时器除了
TIM6
和
TIM7
外,其他的定时器都可以产生
PWM
输出。其中
高级定时器
TIM1
和
TIM8
可以同时产生多达
7
路的
PWM
输出。而通用定时器也能同时产生
多达
4
路的
PWM 输出!
PWM相关寄存器的操作(小tips:结合着上面的PWM的分图和参考手册会更加理解为什么要自操作这些相应的位置的作用)
1.捕获/比较模式寄存器TIMx_ CCMR1/2 :该寄存器通常有两个,一用来孔子通道一二,二用来控制通道三四。
还是把上面的图拿下来,看着方便
CC1S[1:0]来控制输出和输入的模式, OC1/2M 控制模式1或2,OC1PE 控制输出比较通道 1 的预装载使能,实 际就是控制 CCR1 寄存器是否进行缓冲。
2.捕获/比较使能寄存器TIM_CCER:控制通道的使能位置
通过CCIE位置来设置。
3.捕获/比较寄存器TIM_CCR(1,2,3,4):给CCRx进行赋值:
注意,对 于 TIM2
和
TIM5
来说,该寄存器是
32
位有效的,对其他定时器来说,则是
16
位有效位。
4.断路和死区寄存器TIMx_BDR
要想上述定时器的
PWM
正常输出,则必须设置
MOE
位为
1
,否则不会有输出。
程序的配置:
1. HAL_TIM_PWM_Init 函数:函数的初始化的配置和调用;特别要与HAL_TIM_Base_Init区分开来。以及他们各自的回调函数。
2.
HAL_TIM_PWM_ConfigChannel 函数:
于配置定时器基本参数,配置定时器输出比较参数和通道号
3. HAL_TIM_PWM_Start
函数 定时器 PWM
输出启动函数,
4.HAL_TIM_ConfigClockSource
函数 配置定时器时钟源函数,
举出的栗子为定时器三的通道一:映射到PA6的引脚上
PWM.H
#define GTIM_TIMX_PWM_CHY_GPIO_PORT GPIOB
#define GTIM_TIMX_PWM_CHY_GPIO_PIN GPIO_PIN_4
#define GTIM_TIMX_PWM_CHY_GPIO_AF GPIO_AF2_TIM3
/* AF
功能选择
*/
#define GTIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE()
do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)
/* PB
口时钟使能
*/
#define GTIM_TIMX_PWM TIM3
#define GTIM_TIMX_PWM_CHY TIM_CHANNEL_1
/*
通道
Y, 1<= Y <=4 */
#define GTIM_TIMX_PWM_CHY_CCRX TIM3->CCR1
/*
通道
Y
的输出比较寄存器
*/
#define GTIM_TIMX_PWM_CHY_CLK_ENABLE()
do{ __HAL_RCC_TIM3_CLK_ENABLE(); }while(0)
/* TIM3
时钟使能
*/
PWM.C
/*初始化的配置*/
void
gtim_timx_pwm_chy_init
(
uint16_t
arr
,
uint16_t
psc
)
{
g_timx_pwm_chy_handle
.
Instance
=
GTIM_TIMX_PWM
;
/*
定时器
x */
g_timx_pwm_chy_handle
.
Init
.
Prescaler
=
psc
;
/*
定时器分频
*/
g_timx_pwm_chy_handle
.
Init
.
CounterMode
=
TIM_COUNTERMODE_UP
;
/*
向上计数模式
*/
g_timx_pwm_chy_handle
.
Init
.
Period
=
arr
;
/*
自动重装载值
*/
HAL_TIM_PWM_Init
(&
g_timx_pwm_chy_handle
);
/*
初始化
PWM */
g_timx_oc_pwm_chy_handle
.
OCMode
=
TIM_OCMODE_PWM1
;
/*
模式选择
PWM1 */
/*
设置比较值
,
此值用来确定占空比,这里默认比较值为自动重装载值的一半
,
即占空比为
50% */
g_timx_oc_pwm_chy_handle
.
Pulse
=
arr
/
2
;
g_timx_oc_pwm_chy_handle
.
OCPolarity
=
TIM_OCPOLARITY_LOW
;
/*
输出比较极性为低
*/
HAL_TIM_PWM_ConfigChannel
(&
g_timx_pwm_chy_handle
, &
g_timx_oc_pwm_chy_handle
,
GTIM_TIMX_PWM_CHY
);
/*
配置
TIMx
通道
y */
HAL_TIM_PWM_Start
(&
g_timx_pwm_chy_handle
,
GTIM_TIMX_PWM_CHY
);
/*
开启
PWM
通道
1*/
}
/**
* @brief
定时器底层驱动,时钟使能,引脚配置
此函数会被
HAL_TIM_PWM_Init()
调用
* @param htim:
定时器句柄
* @retval
无
*/
void
HAL_TIM_PWM_MspInit
(
TIM_HandleTypeDef
*
htim
)
{
if
(
htim
->
Instance
==
GTIM_TIMX_INT
)
{
GPIO_InitTypeDef gpio_init_struct
;
GTIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE
();
/*
开启通道
y
的
GPIO
时钟
*/
GTIM_TIMX_PWM_CHY_CLK_ENABLE
();
gpio_init_struct
.
Pin
=
GTIM_TIMX_PWM_CHY_GPIO_PIN
;
/*
通道
y
的
GPIO
口
*/
gpio_init_struct
.
Mode
=
GPIO_MODE_AF_PP
;
/*
复用推完输出
*/
gpio_init_struct
.
Pull
=
GPIO_PULLUP
;
/*
上拉
*/
gpio_init_struct
.
Speed
=
GPIO_SPEED_FREQ_HIGH
;
/*
高速
*/
/*
定时器
x
通道
y
的
GPIO
口复用
*/
gpio_init_struct
.
Alternate
=
GTIM_TIMX_PWM_CHY_GPIO_AF
;
HAL_GPIO_Init
(
GTIM_TIMX_PWM_CHY_GPIO_PORT
, &
gpio_init_struct
);
}
}
main.c
int
main
(
void
)
{
uint16_t
ledrpwmval
=
0
;
uint8_t
dir
=
1
;
sys_cache_enable
();
/*
打开
L1-Cache */
HAL_Init
();
/*
初始化
HAL
库
*/
sys_stm32_clock_init
(
240
,
2
,
2
,
4
);
/*
设置时钟
, 480Mhz */
delay_init
(
480
);
/*
延时初始化
*/
usart_init
(
115200
);
/*
串口初始化为
115200 */
led_init
();
/*
初始化
LED */
/* 240M/240=1M
的计数频率,自动重装载为
500
,那么
PWM
频率为
1M/500=2kHZ */
gtim_timx_pwm_chy_init
(
500
-
1
,
240
-
1
);
while
(
1
)
{
delay_ms
(
10
);
if
(
dir
)
ledrpwmval
++;
/* dir==1 ledrpwmval
递增
*/
else
ledrpwmval
--;
/* dir==0 ledrpwmval
递减
*/
if
(
ledrpwmval
>
300
)
dir
=
0
;
/* ledrpwmval
到达
300
后,方向为递减
*/
if
(
ledrpwmval
==
0
)
dir
=
1
;
/* ledrpwmval
递减到
0
后,方向改为递增
*/
/*
修改比较值控制占空比
*/
__HAL_TIM_SET_COMPARE
(&
g_timx_pwm_chy_handle
,
GTIM_TIMX_PWM_CHY
,
ledrpwmval
);
}
}
输入捕获实验:
输入捕获模式可以用来测量脉冲宽度或者测量频率。
老规矩:先上图:
t1
到
t2
的时间段,就是我们需要测量的高电平时间。测量方法如下:假如定 时器工作在递增计数模式,首先设置定时器通道 x
为上升沿捕获,这样在
t1
时刻上升沿到来 时,就会发生捕获事件。这里我们还会打开捕获中断,所以捕获事件发生就意味着捕获中断也 会发生。在捕获中断里将计数器值清零,并设置通道 x
为下降沿捕获,这样
t2
时刻下降沿到来 时,就会发生捕获事件和捕获中断。捕获事件发生时,计数器的值会被锁存到捕获/
比较寄存器 中(比如通道 1
对应的是
CCR1
寄存器)。那么在捕获中断里,我们读取捕获
/
比较寄存器就可 以获取到高电平脉冲时间内,计数器计数的个数,从而可以算出高电平脉冲的时间。这里是假 设定时器没有溢出为前提的。
计数器计数的个数计算方法为:N*(ARR+1)+ CCRx2,CCRx2 表示 t2 时间 点,捕获/比较寄存器的值
相关寄存器的描述和使用:
捕获
/
比较模式寄存器
1/2
(
TIMx_CCMR1/2
)
通道方向通过配置相应的 CCxS 位进行定义。此寄存器的所有其它位在输入模式和输出模式下的功能均不同。对于任 一给定位,OCxx
用于说明通道配置为输出时该位对应的功能,
ICxx
则用于说明通道配置为输入时该位对应的功能。
TIMx_CCMR1
寄存器对应于通道
1
和通道
2
的设置,
CCMR2
寄存器对应通道
3 和通道 4
。
这两个位用于 CCR1 的通道配置,这里我们设置 IC1S[1:0]=01,也就是配 置 IC1 映射在 TI1 上。输入捕获 1 预分频器 IC1PSC[1:0],这个比较好理解。我们是 1 次边沿就触发 1 次捕获,所以选择 00 就行了。
捕获
/
比较使能寄存器(
TIMx_ CCER
)
TIM2/TIM3/TIM4/TIM5
的捕获
/
比较使能寄存器,该寄存器控制着各个输入输出通道的开
关和极性
DMA/中断使能寄存器:TIMx_DIER,
例如们使用通道一进行捕获,则要使能CC1IE, 同时我们还需要在定时器溢出中断中累计定时器溢出的次数,所 以还需要使能定时器的更新中断,即 UIE 置 1。
控制寄存器:TIMx_CR1,我们只用到了它的最低位,也就是用来使能定时器的。
捕获
/
比较寄存器
1
:
TIMx_CCR1
,该寄存器用来存储发生捕获事件时,
TIMx_CNT
的值,我们从
TIMx_CCR1
就可以读出通道
1
捕获事件发生时刻的
TIMx_CNT
值,
通过两次捕获(一次上升沿捕获,一次下降沿捕获)的差值,就可以计算出高电平脉冲的宽度
(注意,对于高电平脉宽太长的情况,还要计算定时器溢出的次数)。
软件的编写和测试:
通过按下按键检测上升沿的时间
1. HAL_TIM_IC_Init
函数
定时器的输入捕获模式初始化函数,
2. HAL_TIM_IC_ConfigChannel
函数
定时器的输入捕获通道设置初始化函数
3. HAL_TIM_IC_Start_IT
函数
启动定时器输入捕获模式函数