基质喷涂
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

230 lines
7.7 KiB

  1. #include "pwm_control.h"
  2. #include <cstdio>
  3. #include <main.h>
  4. #include "stm32f4xx_hal.h"
  5. // 全局变量,用于存储频率和占空比
  6. volatile uint32_t pwm_frequency = 1000; // 默认频率为1000Hz
  7. volatile uint8_t pwm_duty_cycle = 50; // 默认占空比为50%
  8. // 定时器句柄
  9. TIM_HandleTypeDef htim;
  10. // 定义定时器和通道
  11. #define TIMx TIM4
  12. #define TIMx_CLK_ENABLE __HAL_RCC_TIM4_CLK_ENABLE()
  13. #define GPIOx GPIOD
  14. #define GPIOx_CLK_ENABLE __HAL_RCC_GPIOD_CLK_ENABLE()
  15. // 根据通道选择对应的定时器通道
  16. uint32_t Get_TIM_Channel(PWM_Channel_TypeDef channel) {
  17. switch (channel) {
  18. case PWM_PUMP_PUL:
  19. return TIM_CHANNEL_1;
  20. case PWM_LASER:
  21. return TIM_CHANNEL_2;
  22. case PWM_GY:
  23. return TIM_CHANNEL_3;
  24. default:
  25. return 0;
  26. }
  27. }
  28. // 根据通道选择对应的GPIO引脚
  29. uint32_t Get_GPIO_Pin(PWM_Channel_TypeDef channel) {
  30. switch (channel) {
  31. case PWM_PUMP_PUL:
  32. return GPIO_PIN_12;
  33. case PWM_LASER:
  34. return GPIO_PIN_13;
  35. case PWM_GY:
  36. return GPIO_PIN_14;
  37. default:
  38. return 0;
  39. }
  40. }
  41. // 初始化定时器和GPIO
  42. void TIM_PWM_Init(void) {
  43. #if 0
  44. TIM_OC_InitTypeDef sConfigOC = {0};
  45. // 使能GPIO和定时器时钟
  46. GPIOx_CLK_ENABLE;
  47. TIMx_CLK_ENABLE;
  48. // 配置GPIO引脚为复用功能
  49. GPIO_InitTypeDef GPIO_InitStruct = {0};
  50. GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14;
  51. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  52. GPIO_InitStruct.Pull = GPIO_NOPULL;
  53. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  54. GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
  55. HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
  56. // 配置定时器
  57. htim.Instance = TIMx;
  58. htim.Init.Prescaler = 0;
  59. htim.Init.CounterMode = TIM_COUNTERMODE_UP;
  60. htim.Init.Period = 0;
  61. htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  62. htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  63. HAL_TIM_PWM_Init(&htim);
  64. // 配置PWM通道
  65. sConfigOC.OCMode = TIM_OCMODE_PWM1;
  66. sConfigOC.Pulse = 0;
  67. sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  68. sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  69. HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1);
  70. HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_2);
  71. HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_3);
  72. // 启动PWM输出
  73. HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1);
  74. HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_2);
  75. HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_3);
  76. #else
  77. TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  78. TIM_MasterConfigTypeDef sMasterConfig = {0};
  79. TIM_OC_InitTypeDef sConfigOC = {0};
  80. // 使能GPIO和定时器时钟
  81. GPIOx_CLK_ENABLE;
  82. TIMx_CLK_ENABLE;
  83. // 配置GPIO引脚为复用功能
  84. GPIO_InitTypeDef GPIO_InitStruct = {0};
  85. GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14;
  86. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  87. GPIO_InitStruct.Pull = GPIO_NOPULL;
  88. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  89. GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
  90. HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
  91. // 配置定时器
  92. htim.Instance = TIM4;
  93. htim.Init.Prescaler = 32;
  94. htim.Init.CounterMode = TIM_COUNTERMODE_UP;
  95. htim.Init.Period = 1000;
  96. htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  97. htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  98. if (HAL_TIM_Base_Init(&htim) != HAL_OK) {
  99. Error_Handler();
  100. }
  101. sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  102. if (HAL_TIM_ConfigClockSource(&htim, &sClockSourceConfig) != HAL_OK) {
  103. Error_Handler();
  104. }
  105. if (HAL_TIM_PWM_Init(&htim) != HAL_OK) {
  106. Error_Handler();
  107. }
  108. sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  109. sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  110. if (HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig) != HAL_OK) {
  111. Error_Handler();
  112. }
  113. sConfigOC.OCMode = TIM_OCMODE_PWM1;
  114. sConfigOC.Pulse = 0;
  115. sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  116. sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  117. if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
  118. Error_Handler();
  119. }
  120. if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) {
  121. Error_Handler();
  122. }
  123. if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) {
  124. Error_Handler();
  125. }
  126. // 启动PWM输出
  127. HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1);
  128. HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_2);
  129. HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_3);
  130. #endif
  131. }
  132. // 更新指定通道的PWM频率和占空比
  133. void Update_PWM(PWM_Channel_TypeDef channel, uint32_t frequency, uint8_t duty_cycle) {
  134. #if 0
  135. if (frequency == 0) {
  136. if (duty_cycle == 0) {
  137. // 关闭定时器,GPIO输出0
  138. uint32_t tim_channel = Get_TIM_Channel(channel);
  139. uint32_t gpio_pin = Get_GPIO_Pin(channel);
  140. HAL_TIM_PWM_Stop(&htim, tim_channel);
  141. HAL_GPIO_WritePin(GPIOx, gpio_pin, GPIO_PIN_RESET);
  142. } else if (duty_cycle == 100) {
  143. // GPIO输出1
  144. uint32_t tim_channel = Get_TIM_Channel(channel);
  145. uint32_t gpio_pin = Get_GPIO_Pin(channel);
  146. HAL_TIM_PWM_Stop(&htim, tim_channel);
  147. HAL_GPIO_WritePin(GPIOx, gpio_pin, GPIO_PIN_SET);
  148. }
  149. } else {
  150. // 计算定时器的周期和脉冲宽度
  151. uint32_t timer_clock = HAL_RCC_GetPCLK1Freq() * 2; // TIM4挂载在APB1总线上,APB1预分频器为2时,定时器时钟为APB1时钟的2倍
  152. uint32_t prescaler = (timer_clock / (frequency * 1000)) - 1;
  153. uint32_t period = 1000;
  154. uint32_t pulse = (period * duty_cycle) / 100;
  155. // 配置定时器参数
  156. htim.Instance->CR2 &= 0x00;
  157. htim.Instance->PSC = prescaler;
  158. htim.Instance->ARR = period;
  159. uint32_t tim_channel = Get_TIM_Channel(channel);
  160. switch (tim_channel) {
  161. case TIM_CHANNEL_1:
  162. htim.Instance->CCR1 = pulse;
  163. HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1);
  164. break;
  165. case TIM_CHANNEL_2:
  166. htim.Instance->CCR2 = pulse;
  167. HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_2);
  168. break;
  169. case TIM_CHANNEL_3:
  170. htim.Instance->CCR3 = pulse;
  171. HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_3);
  172. break;
  173. }
  174. htim.Instance->CR2 &= 0x00;
  175. }
  176. #else
  177. // 计算定时器的周期和预分频器
  178. uint32_t timer_clock = HAL_RCC_GetPCLK1Freq() * 2; // TIM4挂载在APB1总线上,APB1预分频器为2时,定时器时钟为APB1时钟的2倍
  179. uint32_t prescaler = (timer_clock / (frequency * 1000)) - 1;
  180. uint32_t period = 999; // 固定周期为999,通过调整预分频器实现频率变化
  181. uint32_t tim_channel = Get_TIM_Channel(channel);
  182. uint32_t pulse = (period * duty_cycle) / 100;
  183. // HAL_TIM_PWM_Stop(&htim, tim_channel);
  184. // TIM_OC_InitTypeDef sConfigOC;
  185. // htim.Init.Period = period;
  186. // sConfigOC.Pulse = pulse;
  187. // sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  188. // sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  189. // HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, channel);
  190. // HAL_TIM_PWM_Start(&htim, tim_channel);
  191. // htim.Instance->CR2 &= 0x00;
  192. // htim.Instance->PSC = prescaler;
  193. // htim.Instance->ARR = period;
  194. // htim.Instance->CCR1 = pulse;
  195. // htim.Instance->CCR2 = pulse;
  196. // htim.Instance->CCR3 = pulse;
  197. __HAL_TIM_SET_PRESCALER(&htim, prescaler);
  198. __HAL_TIM_SET_AUTORELOAD(&htim, period);
  199. __HAL_TIM_SET_COMPARE(&htim, tim_channel, pulse);
  200. // 触发更新事件
  201. HAL_TIM_GenerateEvent(&htim, TIM_EVENTSOURCE_UPDATE);
  202. #endif
  203. }