第33章 STM32H7的定时器应用之TIM1-TIM17的中断实现
本章教程为大家讲解定时器应用之TIM1 – TIM17所有定时器的周期性中断实现。实际项目中用到的地方较多,特别是周期性的事件查询。
33.1 初学者重要提示
33.2 定时器中断的驱动设计
33.3 定时器板级支持包(bsp_tim_pwm.c)
33.4 定时器驱动移植和使用
33.5 实验例程设计框架
33.6 实验例程说明(MDK)
33.7 实验例程说明(IAR)
33.8 总结
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; /*自动重装的