STM32F767 Timer中断的基本用法

 本文介绍STM32F767 Timer中断的基本用法。

开发环境

硬件环境

  • 电脑:Windows 10 Home x64
  • Apollo STM32F767开发板(ST-LINK V2仿真器)

软件环境

  • Keil Version 5.24.1 (Pack Installer:Keil.STM32F7xx_DFP.2.9.0.pack)
  • STM32CubeMX Version 4.25.0(Packages Manager:STM32CubeF7)

TIM的基本特性

TIM分类

 在STM32F767中,TIM定时器共分为3类:基本定时器基本通用定时器通用定时器高级控制定时器低功耗定时器

基本定时器

TIM6/TIM7基本定时器,具备的功能有:

  • 16 位自动重载递增计数器
  • 16 位可编程预分频器,用于对计数器时钟频率进行分频(可在运行时修改),分频系数
    介于 1 和 65536 之间
  • 用于触发 DAC 的同步电路
  • 发生如下更新事件时会生成中断/DMA 请求:计数器上溢

基本通用定时器

TIM9/TIM10/TIM11/TIM12/TIM13/TIM14基本通用定时器,具备的功能有:

  • 16 位自动重载递增计数器
  • 16 位可编程预分频器,用于对计数器时钟频率进行分频(可在运行时修改),分频系数
    介于 1 和 65536 之间
  • 多达 2 个独立通道,可用于:输入捕获、输出比较、PWM生成(边沿对齐)、单脉冲模式输出
  • 使用外部信号控制定时器且可实现多个定时器互连的同步电路
  • 发生如下事件时生成中断:更新(计数器上溢、计数器初始化(通过软件或内部触发))、触发事件(计数器启动、停止、初始化或者由内部触发计数)、输入捕获、输出比较

通用定时器

TIM2/TIM3/TIM4/TIM5通用定时器,具备的功能有:

  • 16 位(TIM3 和 TIM4)或 32 位(TIM2 和 TIM5)递增、递减和递增/递减自动重载计数器
  • 16 位可编程预分频器,用于对计数器时钟频率进行分频(可在运行时修改),分频系数
    介于 1 到 65535 之间
  • 多达 4 个独立通道,可用于:输入捕获、输出比较、PWM生成(边沿和中心对齐)、单脉冲模式输出
  • 使用外部信号控制定时器且可实现多个定时器互连的同步电路
  • 发生如下事件时生成中断:更新(计数器上溢/下溢、计数器初始化(通过软件或内部/外部触发))、触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)、输入捕获、输出比较
  • 支持定位用增量(正交)编码器和霍尔传感器电路
  • 触发输入作为外部时钟或者逐周期电流管理

高级控制定时器

TIM1/TIM8高级控制定时器,具备的功能有:

  • 16 位递增、递减、递增/递减自动重载计数器
  • 16 位可编程预分频器,用于对计数器时钟频率进行分频(可在运行时修改),分频系数
    介于 1 到 65536 之间
  • 多达 6 个独立通道,可用于:输入捕获(但通道 5 和通道 6 除外)、输出比较、PWM生成(边沿和中心对齐)、单脉冲模式输出
  • 带可编程死区的互补输出
  • 使用外部信号控制定时器且可实现多个定时器互连的同步电路
  • 重复计数器,用于仅在给定数目的计数器周期后更新定时器寄存器
  • 具有2 个断路输入,用于将定时器的输出信号置于用户可选的安全配置中
  • 发生如下事件时生成中断/DMA 请求:更新(计数器上溢/下溢、计数器初始化(通过软件或内部/外部触发))、触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)、输入捕获、输出比较
  • 支持定位用增量(正交)编码器和霍尔传感器电路
  • 触发输入作为外部时钟或者逐周期电流管理

TIM2基本特性

 本例中,使用TIM2定时器完成实验。TIM2的基本特性如下:

  • 为通用定时器;
  • 32 位递增、递减和递增/递减自动重载计数器;
  • 时钟源为APB1,频率为108MHz

基于TIM2的timer中断基本用法

系统框图

 通用定时器的系统框图如图所示。本次进行定时器中断实验只需要用到计数以及中断部分。

Timer代码设置

代码概述

 Timer的初始化代码如下所示。其初始化主要由3个函数完成,以下将对这3个函数进行简要说明。

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
TIM_HandleTypeDef htim2;
/* TIM2 init function */
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 10800 - 1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 5000 - 1;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}

时基单元初始化

 时基单元初始化通过HAL_TIM_Base_Init()函数实现,具体如下。

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
/**
* @brief Initializes the TIM Time base Unit according to the specified
* parameters in the TIM_HandleTypeDef and create the associated handle.
* @param htim pointer to a TIM_HandleTypeDef structure that contains
* the configuration information for TIM module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
{
/* Check the TIM handle allocation */
if(htim == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_TIM_INSTANCE(htim->Instance));
assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
if(htim->State == HAL_TIM_STATE_RESET)
{
/* Allocate lock resource and initialize it */
htim->Lock = HAL_UNLOCKED;
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
/* Reset interrupt callbacks to legacy week callbacks */
TIM_ResetCallback(htim);
if(htim->Base_MspInitCallback == NULL)
{
htim->Base_MspInitCallback = HAL_TIM_Base_MspInit;
}
/* Init the low level hardware : GPIO, CLOCK, NVIC */
htim->Base_MspInitCallback(htim);
#else
/* Init the low level hardware : GPIO, CLOCK, NVIC */
HAL_TIM_Base_MspInit(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
/* Set the TIM state */
htim->State= HAL_TIM_STATE_BUSY;
/* Set the Time Base configuration */
TIM_Base_SetConfig(htim->Instance, &htim->Init);
/* Initialize the TIM state*/
htim->State= HAL_TIM_STATE_READY;
return HAL_OK;
}

 程序中调用了HAL_TIM_Base_MspInit()函数,该函数完成TIM2 RCC时钟的使能NVIC的使能以及优先级设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 1, 1);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
}

 程序中之后调用的TIM_Base_SetConfig()函数为时基单元的设置

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
/**
* @brief Time Base configuration
* @param TIMx TIM peripheral
* @param Structure pointer on TIM Time Base required parameters
* @retval None
*/
void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure)
{
uint32_t tmpcr1 = 0;
tmpcr1 = TIMx->CR1;
/* Set TIM Time Base Unit parameters ---------------------------------------*/
if(IS_TIM_CC3_INSTANCE(TIMx) != RESET)
{
/* Select the Counter Mode */
tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
tmpcr1 |= Structure->CounterMode;
}
if(IS_TIM_CC1_INSTANCE(TIMx) != RESET)
{
/* Set the clock division */
tmpcr1 &= ~TIM_CR1_CKD;
tmpcr1 |= (uint32_t)Structure->ClockDivision;
}
/* Set the auto-reload preload */
MODIFY_REG(tmpcr1, TIM_CR1_ARPE, Structure->AutoReloadPreload);
TIMx->CR1 = tmpcr1;
/* Set the Auto-reload value */
TIMx->ARR = (uint32_t)Structure->Period ;
/* Set the Prescaler value */
TIMx->PSC = (uint32_t)Structure->Prescaler;
if(IS_TIM_ADVANCED_INSTANCE(TIMx) != RESET)
{
/* Set the Repetition Counter value */
TIMx->RCR = Structure->RepetitionCounter;
}
/* Generate an update event to reload the Prescaler
and the repetition counter(only for TIM1 and TIM8) value immediately */
TIMx->EGR = TIM_EGR_UG;
}

 该函数的功能简介如下:

  • tmpcr1TIMx->CR1寄存器的待写入值,该值首先保存TIMx->CR1寄存器当前值;
  • 经过IS_TIM_CC3_INSTANCE实例检测后,tmpcr1设置计数器模式,本例为增计数;
  • 经过IS_TIM_CC1_INSTANCE实例检测后,tmpcr1设置计时器中频率与数字滤波器所用时钟ETR、TIx的分频比,本例为不分频;
  • MODIFY_REG()函数设置tmpcr1的ARPE位,本例为TIMx_ARR 寄存器不进行缓冲;
  • tmpcr1写入到TIMx->CR1寄存器;
  • TIMx->ARR写入定时器周期值,本例写入值为5000-1,考虑到计数值从0开始,所以一个周期内共计数5000次
  • TIMx->PSC写入定时器预分频器值,计数器时钟频率 CK_CNT 等于 $f_{CK_PSC} / (PSC[15:0] + 1)$。本例写入值为10800 - 1,则时钟频率为108MHz/10800=10kHz
  • 定时器时钟为10kHz计数值为5000,则定时器周期为500ms
  • TIMx->EGR寄存器UG位写入1,生成更新事件,更新计数器值以及预分频计数器。

时钟源设置

 时钟源的选择通过如下函数实现。本例中时钟选择为内部时钟,即将TIMx_SMCR寄存器SMS控制位设置为0000

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**
* @brief Configures the clock source to be used
* @param htim pointer to a TIM_HandleTypeDef structure that contains
* the configuration information for TIM module.
* @param sClockSourceConfig pointer to a TIM_ClockConfigTypeDef structure that
* contains the clock source information for the TIM peripheral.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef * sClockSourceConfig)
{
uint32_t tmpsmcr = 0;
/* Process Locked */
__HAL_LOCK(htim);
htim->State = HAL_TIM_STATE_BUSY;
/* Check the parameters */
assert_param(IS_TIM_CLOCKSOURCE(sClockSourceConfig->ClockSource));
/* Reset the SMS, TS, ECE, ETPS and ETRF bits */
tmpsmcr = htim->Instance->SMCR;
tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS);
tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);
htim->Instance->SMCR = tmpsmcr;
switch (sClockSourceConfig->ClockSource)
{
case TIM_CLOCKSOURCE_INTERNAL:
{
assert_param(IS_TIM_INSTANCE(htim->Instance));
/* Disable slave mode to clock the prescaler directly with the internal clock */
htim->Instance->SMCR &= ~TIM_SMCR_SMS;
}
break;
case TIM_CLOCKSOURCE_ETRMODE1:
{
assert_param(IS_TIM_ETR_INSTANCE(htim->Instance));
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
/* Configure the ETR Clock source */
TIM_ETR_SetConfig(htim->Instance,
sClockSourceConfig->ClockPrescaler,
sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter);
/* Get the TIMx SMCR register value */
tmpsmcr = htim->Instance->SMCR;
/* Reset the SMS and TS Bits */
tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS);
/* Select the External clock mode1 and the ETRF trigger */
tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1);
/* Write to TIMx SMCR */
htim->Instance->SMCR = tmpsmcr;
}
break;
case TIM_CLOCKSOURCE_ETRMODE2:
{
assert_param(IS_TIM_ETR_INSTANCE(htim->Instance));
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
/* Configure the ETR Clock source */
TIM_ETR_SetConfig(htim->Instance,
sClockSourceConfig->ClockPrescaler,
sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter);
/* Enable the External clock mode2 */
htim->Instance->SMCR |= TIM_SMCR_ECE;
}
break;
case TIM_CLOCKSOURCE_TI1:
{
assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
/* Check TI1 input conditioning related parameters */
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
TIM_TI1_ConfigInputStage(htim->Instance,
sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter);
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1);
}
break;
case TIM_CLOCKSOURCE_TI2:
{
assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
/* Check TI1 input conditioning related parameters */
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
TIM_TI2_ConfigInputStage(htim->Instance,
sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter);
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2);
}
break;
case TIM_CLOCKSOURCE_TI1ED:
{
assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
/* Check TI1 input conditioning related parameters */
assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
TIM_TI1_ConfigInputStage(htim->Instance,
sClockSourceConfig->ClockPolarity,
sClockSourceConfig->ClockFilter);
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED);
}
break;
case TIM_CLOCKSOURCE_ITR0:
{
assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0);
}
break;
case TIM_CLOCKSOURCE_ITR1:
{
assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1);
}
break;
case TIM_CLOCKSOURCE_ITR2:
{
assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2);
}
break;
case TIM_CLOCKSOURCE_ITR3:
{
assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR3);
}
break;
default:
break;
}
htim->State = HAL_TIM_STATE_READY;
__HAL_UNLOCK(htim);
return HAL_OK;
}

主模式设置

 设置时钟主模式的设置通过如下代码实现。

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**
* @brief Configures the TIM in master mode.
* @param htim pointer to a TIM_HandleTypeDef structure that contains
* the configuration information for TIM module.
* @param sMasterConfig pointer to a TIM_MasterConfigTypeDef structure that
* contains the selected trigger output (TRGO) and the Master/Slave
* mode.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, TIM_MasterConfigTypeDef * sMasterConfig)
{
uint32_t tmpcr2;
uint32_t tmpsmcr;
/* Check the parameters */
assert_param(IS_TIM_SYNCHRO_INSTANCE(htim->Instance));
assert_param(IS_TIM_TRGO_SOURCE(sMasterConfig->MasterOutputTrigger));
assert_param(IS_TIM_MSM_STATE(sMasterConfig->MasterSlaveMode));
/* Check input state */
__HAL_LOCK(htim);
/* Get the TIMx CR2 register value */
tmpcr2 = htim->Instance->CR2;
/* Get the TIMx SMCR register value */
tmpsmcr = htim->Instance->SMCR;
/* If the timer supports ADC synchronization through TRGO2, set the master mode selection 2 */
if (IS_TIM_TRGO2_INSTANCE(htim->Instance))
{
/* Check the parameters */
assert_param(IS_TIM_TRGO2_SOURCE(sMasterConfig->MasterOutputTrigger2));
/* Clear the MMS2 bits */
tmpcr2 &= ~TIM_CR2_MMS2;
/* Select the TRGO2 source*/
tmpcr2 |= sMasterConfig->MasterOutputTrigger2;
}
/* Reset the MMS Bits */
tmpcr2 &= ~TIM_CR2_MMS;
/* Select the TRGO source */
tmpcr2 |= sMasterConfig->MasterOutputTrigger;
/* Reset the MSM Bit */
tmpsmcr &= ~TIM_SMCR_MSM;
/* Set master mode */
tmpsmcr |= sMasterConfig->MasterSlaveMode;
/* Update TIMx CR2 */
htim->Instance->CR2 = tmpcr2;
/* Update TIMx SMCR */
htim->Instance->SMCR = tmpsmcr;
__HAL_UNLOCK(htim);
return HAL_OK;
}

 该函数的功能简介如下:

  • tmpcr2首先读取了TIMx_CR2寄存器值,清空MMS值并写入2,即以更新时间作为触发输出(TRGO);
  • tmpsmcr首先读取了TIMx_SMCR寄存器值,清空MSM值并写入0,代表主从模式不执行任何操作。
  • tmpcr2tmpsmcr分别写入到TIMx_CR2TIMx_SMCR寄存器。

Timer中断设置

 在定时器中断中设置翻转GPIOB PIN1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @brief Period elapsed callback in non blocking mode
* @param htim pointer to a TIM_HandleTypeDef structure that contains
* the configuration information for TIM module.
* @retval None
*/
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
/* NOTE : This function Should not be modified, when the callback is needed,
the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
*/
}

启动定时器

 启动定时器的程序如下。

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
HAL_TIM_Base_Start_IT(&htim2);
/**
* @brief Starts the TIM Base generation in interrupt mode.
* @param htim pointer to a TIM_HandleTypeDef structure that contains
* the configuration information for TIM module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
{
/* Check the parameters */
assert_param(IS_TIM_INSTANCE(htim->Instance));
/* Enable the TIM Update interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);
/* Enable the Peripheral */
__HAL_TIM_ENABLE(htim);
/* Return function status */
return HAL_OK;
}
#define __HAL_TIM_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DIER |= (__INTERRUPT__))
#define __HAL_TIM_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1|=(TIM_CR1_CEN))

 该程序向TIMx_DIER寄存器UIE写入1使能更新中断;向TIMx_CR1寄存器CEN位写入1,使能计数器。至此,则定时器启动

运行程序

 运行程序,可以看到GPIOB PIN1翻转,高电平与低电平持续时间均为500ms

时基单元的准确性确认

 为了确认时基单元准确性,对定时器分频器与周期进行不同设置并测量周期时长。

Prescaler TIM时钟频率 TIM时钟周期 Period TIM理论周期 TIM实测周期 说明
10800 - 1 10kHz 0.1ms 10 - 1 1ms 1.00025ms 误差远低于TIM时钟周期,故Period设置方法无误。
10-1 10.8MHz 1/10.8us 10800-1 1ms 1.00024ms 误差远低于TIM理论周期,故Prescaler设置无误。
108 - 1 1MHz 1us 2-1 2us 2.005us 误差低于1%,确认无误。
文章目录
  1. 1. 开发环境
    1. 1.1. 硬件环境
    2. 1.2. 软件环境
  2. 2. TIM的基本特性
    1. 2.1. TIM分类
      1. 2.1.1. 基本定时器
      2. 2.1.2. 基本通用定时器
      3. 2.1.3. 通用定时器
      4. 2.1.4. 高级控制定时器
    2. 2.2. TIM2基本特性
  3. 3. 基于TIM2的timer中断基本用法
    1. 3.1. 系统框图
    2. 3.2. Timer代码设置
      1. 3.2.1. 代码概述
      2. 3.2.2. 时基单元初始化
      3. 3.2.3. 时钟源设置
      4. 3.2.4. 主模式设置
    3. 3.3. Timer中断设置
    4. 3.4. 启动定时器
    5. 3.5. 运行程序
    6. 3.6. 时基单元的准确性确认
|