34.1 初学者重要提示
学习本章节前,务必优先学习第32章,HAL库的几个常用API均作了讲解和举例。
如果配置的GPIO引脚无法正确输出,注意本章2.1小节,保证是定时器复用支持的引脚。
STM32H7支持TIM1-TIM8,TIM12-TIM17共14个定时器,而中间的TIM9,TIM10,TIM11是不存在的,这点要注意。
STM32H7的PWM输出100MHz也是没问题的。输出效果见本章2.3小节。
34.2 定时器PWM的驱动设计
针对STM32H7的定时器PWM功能,专门设置了一个超级函数,用户可以方便的配置TIM1-TIM17所有定时器的PWM输出。
34.2.1 定时器PWM输出支持的引脚
STM32H7支持的PWM输出引脚如下(未整理互补输出引脚):
TIM1_CH1, PA8 PE9 PK1
TIM1_CH2, PA9 PE11
TIM1_CH3, PA10 PE13 PJ9
TIM1_CH4, PA11 PE14 PJ11
TIM2_CH1, PA0 PA5 PA15
TIM2_CH2, PA1 PB3
TIM2_CH3, PA2
TIM2_CH4, PA3 PB11
TIM3_CH1, PA6 PC6 PB4
TIM3_CH2, PA7 PC7 PB5
TIM3_CH3, PB0 PC8
TIM3_CH4, PB1 PC9
TIM4_CH1, PB6 PD12
TIM4_CH2, PB7 PD13
TIM4_CH3, PB8 PD14
TIM4_CH4, PB9 PD15
TIM5_CH1, PA0 PH10
TIM5_CH2, PA1 PH11
TIM5_CH3, PA2 PH12
TIM5_CH4, PA3 PI0
TIM8_CH1, PC6 PI5 PJ8
TIM8_CH2, PC7 PI6 PJ10
TIM8_CH3, PC8 PI7 PK0
TIM8_CH4, PC9
TIM12_CH1, PB14 PH6
TIM12_CH2, PB15 PH9
TIM13_CH1, PF8
TIM14_CH1, PF9
TIM15_CH1, PE5
TIM15_CH2, PE6
TIM16_CH1, PB8 PF6
TIM16_CH2, PF7
TIM17_CH1, PB9
使用时,直接配置定时器PWM模式,并配置相应引脚即可使用。
34.2.2 定时器PWM初始化
下面函数的作用是根据使用的是GPIO,使能相应的GPIO时钟。
1. /*
2. ******************************************************************************************************
3. * 函 数 名: bsp_RCC_GPIO_Enable
4. * 功能说明: 使能GPIO时钟
5. * 形 参: GPIOx GPIOA - GPIOK
6. * 返 回 值: 无
7. ******************************************************************************************************
8. */
9. void bsp_RCC_GPIO_Enable(GPIO_TypeDef* GPIOx)
10. {
11. if (GPIOx == GPIOA) __HAL_RCC_GPIOA_CLK_ENABLE();
12. else if (GPIOx == GPIOB) __HAL_RCC_GPIOB_CLK_ENABLE();
13. else if (GPIOx == GPIOC) __HAL_RCC_GPIOC_CLK_ENABLE();
14. else if (GPIOx == GPIOD) __HAL_RCC_GPIOD_CLK_ENABLE();
15. else if (GPIOx == GPIOE) __HAL_RCC_GPIOE_CLK_ENABLE();
16. else if (GPIOx == GPIOF) __HAL_RCC_GPIOF_CLK_ENABLE();
17. else if (GPIOx == GPIOG) __HAL_RCC_GPIOG_CLK_ENABLE();
18. else if (GPIOx == GPIOH) __HAL_RCC_GPIOH_CLK_ENABLE();
19. else if (GPIOx == GPIOI) __HAL_RCC_GPIOI_CLK_ENABLE();
20. else if (GPIOx == GPIOJ) __HAL_RCC_GPIOJ_CLK_ENABLE();
21. else if (GPIOx == GPIOK) __HAL_RCC_GPIOK_CLK_ENABLE();
22. }
下面函数的作用是根据使用的定时器,使能和禁止相应的定时器时钟。
1. /*
2. ******************************************************************************************************
3. * 函 数 名: bsp_RCC_TIM_Enable
4. * 功能说明: 使能TIM RCC 时钟
5. * 形 参: TIMx TIM1 - TIM17
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_RCC_TIM_Disable
37. * 功能说明: 关闭TIM RCC 时钟
38. * 形 参: TIMx TIM1 - TIM17
39. * 返 回 值: TIM外设时钟名
40. ******************************************************************************************************
41. */
42. void bsp_RCC_TIM_Disable(TIM_TypeDef* TIMx)
43. {
44. /*
45. APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14
46. APB2 定时器有 TIM1, TIM8 , TIM15, TIM16,TIM17
47. */
48. if (TIMx == TIM1) __HAL_RCC_TIM3_CLK_DISABLE();
49. else if (TIMx == TIM2) __HAL_RCC_TIM2_CLK_DISABLE();
50. else if (TIMx == TIM3) __HAL_RCC_TIM3_CLK_DISABLE();
51. else if (TIMx == TIM4) __HAL_RCC_TIM4_CLK_DISABLE();
52. else if (TIMx == TIM5) __HAL_RCC_TIM5_CLK_DISABLE();
53. else if (TIMx == TIM6) __HAL_RCC_TIM6_CLK_DISABLE();
54. else if (TIMx == TIM7) __HAL_RCC_TIM7_CLK_DISABLE();
55. else if (TIMx == TIM8) __HAL_RCC_TIM8_CLK_DISABLE();
56. // else if (TIMx == TIM9) __HAL_RCC_TIM9_CLK_DISABLE();
57. // else if (TIMx == TIM10) __HAL_RCC_TIM10_CLK_DISABLE();
58. // else if (TIMx == TIM11) __HAL_RCC_TIM11_CLK_DISABLE();
59. else if (TIMx == TIM12) __HAL_RCC_TIM12_CLK_DISABLE();
60. else if (TIMx == TIM13) __HAL_RCC_TIM13_CLK_DISABLE();
61. else if (TIMx == TIM14) __HAL_RCC_TIM14_CLK_DISABLE();
62. else if (TIMx == TIM15) __HAL_RCC_TIM15_CLK_DISABLE();
63. else if (TIMx == TIM16) __HAL_RCC_TIM16_CLK_DISABLE();
64. else if (TIMx == TIM17) __HAL_RCC_TIM17_CLK_DISABLE();
65. else
66. {
67. Error_Handler(__FILE__, __LINE__);
68. }
69. }
配置定时器的PWM功能时,要是设置引脚的复用模式,下面函数就是起到这个作用。
1. /*
2. ******************************************************************************************************
3. * 函 数 名: bsp_GetAFofTIM
4. * 功能说明: 根据TIM 得到AF寄存器配置
5. * 形 参: TIMx TIM1 - TIM17
6. * 返 回 值: AF寄存器配置
7. ******************************************************************************************************
8. */
9. uint8_t bsp_GetAFofTIM(TIM_TypeDef* TIMx)
10. {
11. uint8_t ret = 0;
12.
13. if (TIMx == TIM1) ret = GPIO_AF1_TIM1;
14. else if (TIMx == TIM2) ret = GPIO_AF1_TIM2;
15. else if (TIMx == TIM3) ret = GPIO_AF2_TIM3;
16. else if (TIMx == TIM4) ret = GPIO_AF2_TIM4;
17. else if (TIMx == TIM5) ret = GPIO_AF2_TIM5;
18. else if (TIMx == TIM8) ret = GPIO_AF3_TIM8;
19. else if (TIMx == TIM12) ret = GPIO_AF2_TIM12;
20. else if (TIMx == TIM13) ret = GPIO_AF9_TIM13;
21. else if (TIMx == TIM14) ret = GPIO_AF9_TIM14;
22. else if (TIMx == TIM15) ret = GPIO_AF4_TIM15;
23. else if (TIMx == TIM16) ret = GPIO_AF1_TIM16;
24. else if (TIMx == TIM17) ret = GPIO_AF1_TIM17;
25. else
26. {
27. Error_Handler(__FILE__, __LINE__);