33.1 初学者重要提示
学习本章节前,务必优先学习第32章,HAL库的几个常用API均作了讲解和举例。
STM32H7支持TIM1-TIM8,TIM12-TIM17共14个定时器,而中间的TIM9,TIM10,TIM11是不存在的,这点要注意。
STM32H7的进出中断的速度能跑到12.5MHz,所有程序在TCM和Flash运行没差别,详情可看本章2.3小节。
实际应用中,中断入口函数名称不要写错,有些中断的入口函数名称比较特殊,详情可看本章的2.2小节。
33.2 定时器中断的驱动设计
定时器中断的实现相对比较简单,仅需一个函数即可实现TIM1-TIM17定时器的中断更新配置。
33.2.1 定时器中断初始化
实现代码如下:
1. /*
2. ******************************************************************************************************
3. * 函 数 名: bsp_RCC_TIM_Enable
4. * 功能说明: 使能TIM RCC 时钟
5. * 形 参: 无
6. * 返 回 值: 无
7. ******************************************************************************************************
8. */
9. void bsp_RCC_TIM_Enable(TIM_TypeDef* TIMx)
10. {
11. if (TIMx == TIM1) __HAL_RCC_TIM1_CLK_ENABLE();
12. else if (TIMx == TIM2) __HAL_RCC_TIM2_CLK_ENABLE();
13. else if (TIMx == TIM3) __HAL_RCC_TIM3_CLK_ENABLE();
14. else if (TIMx == TIM4) __HAL_RCC_TIM4_CLK_ENABLE();
15. else if (TIMx == TIM5) __HAL_RCC_TIM5_CLK_ENABLE();
16. else if (TIMx == TIM6) __HAL_RCC_TIM6_CLK_ENABLE();
17. else if (TIMx == TIM7) __HAL_RCC_TIM7_CLK_ENABLE();
18. else if (TIMx == TIM8) __HAL_RCC_TIM8_CLK_ENABLE();
19. // else if (TIMx == TIM9) __HAL_RCC_TIM9_CLK_ENABLE();
20. // else if (TIMx == TIM10) __HAL_RCC_TIM10_CLK_ENABLE();
21. // else if (TIMx == TIM11) __HAL_RCC_TIM11_CLK_ENABLE();
22. else if (TIMx == TIM12) __HAL_RCC_TIM12_CLK_ENABLE();
23. else if (TIMx == TIM13) __HAL_RCC_TIM13_CLK_ENABLE();
24. else if (TIMx == TIM14) __HAL_RCC_TIM14_CLK_ENABLE();
25. else if (TIMx == TIM15) __HAL_RCC_TIM15_CLK_ENABLE();
26. else if (TIMx == TIM16) __HAL_RCC_TIM16_CLK_ENABLE();
27. else if (TIMx == TIM17) __HAL_RCC_TIM17_CLK_ENABLE();
28. else
29. {
30. Error_Handler(__FILE__, __LINE__);
31. }
32. }
33.
34. /*
35. ******************************************************************************************************
36. * 函 数 名: bsp_SetTIMforInt
37. * 功能说明: 配置TIM和NVIC,用于简单的定时中断,开启定时中断。另外注意中断服务程序需要由用户应
38. * 用程序实现。
39. * 形 参: TIMx : 定时器
40. * _ulFreq : 定时频率 (Hz)。 0 表示关闭。
41. * _PreemptionPriority : 抢占优先级
42. * _SubPriority : 子优先级
43. * 返 回 值: 无
44. ******************************************************************************************************
45. */
46. void bsp_SetTIMforInt(TIM_TypeDef* TIMx, uint32_t _ulFreq, uint8_t _PreemptionPriority,
47. uint8_t _SubPriority)
48. {
49. TIM_HandleTypeDef TimHandle = {0};
50. uint16_t usPeriod;
51. uint16_t usPrescaler;
52. uint32_t uiTIMxCLK;
53.
54. /* 使能TIM时钟 */
55. bsp_RCC_TIM_Enable(TIMx);
56.
57. /*-----------------------------------------------------------------------
58. bsp.c 文件中 void SystemClock_Config(void) 函数对时钟的配置如下:
59.
60. System Clock source = PLL (HSE)
61. SYSCLK(Hz) = 400000000 (CPU Clock)
62. HCLK(Hz) = 200000000 (AXI and AHBs Clock)
63. AHB Prescaler = 2
64. D1 APB3 Prescaler = 2 (APB3 Clock 100MHz)
65. D2 APB1 Prescaler = 2 (APB1 Clock 100MHz)
66. D2 APB2 Prescaler = 2 (APB2 Clock 100MHz)
67. D3 APB4 Prescaler = 2 (APB4 Clock 100MHz)
68.
69. 因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = APB1 x 2 = 200MHz;
70. 因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = APB2 x 2 = 200MHz;
71. APB4上面的TIMxCLK没有分频,所以就是100MHz;
72.
73. APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14,LPTIM1
74. APB2 定时器有 TIM1, TIM8 , TIM15, TIM16,TIM17
75.
76. APB4 定时器有 LPTIM2,LPTIM3,LPTIM4,LPTIM5
77. ----------------------------------------------------------------------- */
78. if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM15) || (TIMx == TIM16) || (TIMx == TIM17))
79. {
80. /* APB2 定时器时钟 = 200M */
81. uiTIMxCLK = SystemCoreClock / 2;
82. }
83. else
84. {
85. /* APB1 定时器 = 200M */
86. uiTIMxCLK = SystemCoreClock / 2;
87. }
88.
89. if (_ulFreq < 100)
90. {
91. usPrescaler = 10000 - 1; /* 分频比 = 10000 */
92. usPeriod = (uiTIMxCLK / 10000) / _ulFreq - 1; /* 自动重装的值 */
93. }
94. else if (_ulFreq < 3000)
95. {
96. usPrescaler = 100 - 1; /* 分频比 = 100 */
97. usPeriod = (uiTIMxCLK / 100) / _ulFreq - 1; /* 自动重装的值 */
98. }
99. else /* 大于4K的频率,无需分频 */
100. {
101. usPrescaler = 0; /* 分频比 = 1 */
102. usPeriod = uiTIMxCLK / _ulFreq - 1; /* 自动重装的值 */
103. }
104.
105. /*
106. 定时器中断更新周期 = TIMxCLK / usPrescaler + 1)/usPeriod + 1)
107. */
108. TimHandle.Instance = TIMx;
109. TimHandle.Init.Prescaler = usPrescaler;
110. TimHandle.Init.Period = usPeriod;
111. TimHandle.Init.ClockDivision = 0;
112. TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
113. TimHandle.Init.RepetitionCounter = 0;
114. TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
115. if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
116. {
117. Error_Handler(__FILE__, __LINE__);
118. }
119.
120. /* 使能定时器中断 */
121. __HAL_TIM_ENABLE_IT(&TimHandle, TIM_IT_UPDATE);
122.
123.
124. /* 配置TIM定时更新中断 (Update) */
125. {
126. uint8_t irq = 0; /* 中断号, 定义在 stm32h7xx.h */
127.
128. if (TIMx == TIM1) irq = TIM1_UP_IRQn;
129. else if (TIMx == TIM2) irq = TIM2_IRQn;
130. else if (TIMx == TIM3) irq = TIM3_IRQn;
131. else if (TIMx == TIM4) irq = TIM4_IRQn;
132. else if (TIMx == TIM5) irq = TIM5_IRQn;
133. else if (TIMx == TIM6) irq = TIM6_DAC_IRQn;
134. else if (TIMx == TIM7) irq = TIM7_IRQn;
135. else if (TIMx == TIM8) irq = TIM8_UP_TIM13_IRQn;