bsp_V8M_YY_pwm.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #include "board.h"
  2. #include "hpm_pwm_drv.h"
  3. // #include "hpm_trgm_drv.h"
  4. #include "bsp_V8M_YY_pwm.h"
  5. #include "hpm_gpio_drv.h"
  6. #include "hpm_gpiom_drv.h"
  7. #include "ver_config.h"
  8. #include "test.h"
  9. #include "main.h"
  10. // PB16 PWM0 PB17 PWM0 PB18 PWM1 PB19 PWM1
  11. // motor用的ahb时钟,还有其他外设也用的这个,不对其进行分频了 保留200M
  12. // 2.5ms * 200 000000 => period = 500 000 - 1
  13. // 不要对ahb时钟进行修改
  14. #define PWM_MOTOR1 HPM_PWM1
  15. #define PWM_MOTOR1_CLK_NAME
  16. #define PWM_MOTOR1_OUT 1
  17. #define PWM_MOTOR1_CMP 0
  18. #define PWM_MOTOR2 HPM_PWM1
  19. #define PWM_MOTOR2_CLK_NAME
  20. #define PWM_MOTOR2_OUT 0
  21. #define PWM_MOTOR2_CMP 1
  22. #define PWM_MOTOR3 HPM_PWM1
  23. #define PWM_MOTOR3_CLK_NAME
  24. #define PWM_MOTOR3_OUT 3
  25. #define PWM_MOTOR3_CMP 2
  26. #define PWM_MOTOR4 HPM_PWM3
  27. #define PWM_MOTOR4_CLK_NAME
  28. #define PWM_MOTOR4_OUT 2
  29. #define PWM_MOTOR4_CMP 3
  30. #define PWM_MOTOR5
  31. #define PWM_MOTOR5_CLK_NAME
  32. #define PWM_MOTOR5_OUT
  33. #define PWM_MOTOR5_CMP 4
  34. #define PWM_MOTOR6
  35. #define PWM_MOTOR6_CLK_NAME
  36. #define PWM_MOTOR6_OUT
  37. #define PWM_MOTOR6_CMP 5
  38. #define PWM_EN_GPIO_CTRL HPM_GPIO0
  39. #define PWM_EN_GPIO_INDEX GPIO_DI_GPIOB
  40. #define PWM_EN_GPIO_PIN 3
  41. #define GPIOM_BASE HPM_GPIOM
  42. #define GPIOM_PORT_ASSIGN GPIOM_ASSIGN_GPIOB
  43. /*------------------ Macros definitions --------------------------------------*/
  44. #define V8M_MOTOR_PERIOD (2500*PRESCALER_FACTOR) /* PWM输出的周期,单位 us */
  45. #define V8M_PWM_DEF_VALUE (1000*PRESCALER_FACTOR) /* 默认初始化的 PWM 占空比 */
  46. /**----------------- Variables definitions -----------------------------------*/
  47. /*------------------ Functions definitions -----------------------------------*/
  48. static void __motor_pwm_gpio_config(void);
  49. static void __motor_pwm_timer_config(void);
  50. static void gen_pwm_to_motor(PWM_Type *pwm_x, uint8_t pwm_out, uint8_t cmp_index, uint32_t reload, uint32_t set_cmp_value )
  51. {
  52. pwm_cmp_config_t cmp_config = {0};
  53. pwm_config_t pwm_config = {0};
  54. // 准备pwm_config
  55. pwm_get_default_pwm_config(pwm_x, &pwm_config); // 填充 pwm_config_t 默认值
  56. pwm_config.enable_output = true;
  57. pwm_config.dead_zone_in_half_cycle = 0;
  58. #ifdef WAVE_INV
  59. pwm_config.invert_output = true;
  60. #else
  61. pwm_config.invert_output = false;
  62. #endif
  63. // 准备cmp_config
  64. pwm_get_default_cmp_config(pwm_x, &cmp_config); // 填充 pwm_cmp_config_t 默认值
  65. cmp_config.mode = pwm_cmp_mode_output_compare; // 设置PWM工作模式为输出
  66. cmp_config.cmp = set_cmp_value; // 设置初始CMP值,这样直接设置为 1/2 则后续不需要更新即可生成 50% 占空比
  67. // cmp_config.cmp = pwm_reload + 1; // CMP > RLD, 由于计数器值 CNT 始终达不到 CMPx,比较器输出 OCx 会保持逻辑 0
  68. cmp_config.update_trigger = pwm_shadow_register_update_on_modify; // 设置CMP影子寄存器值生效时刻为 更新后的下一个周期
  69. // pwm_shadow_register_update_on_modify 这种方式下一个指令周期就会重装CMP,可能会导致PWM波形不完整,手册不推荐这种方式
  70. pwm_stop_counter(pwm_x); // 停止计数(没有也可以)
  71. pwm_set_reload(pwm_x, 0, reload); // 设置RLD寄存器
  72. pwm_set_start_count(pwm_x, 0, 0); // 设置STA寄存器
  73. // 使用给定参数对PWM通道进行设置
  74. if (status_success != pwm_setup_waveform(pwm_x, pwm_out, &pwm_config, cmp_index, &cmp_config, 1)) {
  75. printf("failed to setup waveform\\n");
  76. while(1);
  77. }
  78. pwm_start_counter(pwm_x); // 开始计数(PWM输出开始)
  79. pwm_issue_shadow_register_lock_event(pwm_x); // 锁定影子寄存器
  80. // 和 cmp = pwm_reload + 1 一起使用,也可以得到 50% 占空比的 PWM波形
  81. // 在这里更新CMP影子寄存器,下一个周期CMP寄存器会得到更新,这种方式便于动态更新PWM波形
  82. // pwm_update_raw_cmp_edge_aligned(pwm_x, cmp_index, pwm_reload / 2); // 50 % HIGH
  83. }
  84. /**
  85. * @brief pwm 初始化
  86. */
  87. void Bsp_V8M_YY_PwmInit(void)
  88. {
  89. __motor_pwm_gpio_config();
  90. __motor_pwm_timer_config();
  91. // 输出默认值
  92. for (uint8_t i = V8M_PWM_YY_CH1; i <= V8M_PWM_YY_CH4; ++i)
  93. Bsp_V8M_YY_PwmSetCHValue(i, V8M_PWM_DEF_VALUE);
  94. }
  95. /**
  96. * @brief 配置PWM GPIO引脚
  97. */
  98. static void __motor_pwm_gpio_config(void)
  99. {
  100. HPM_IOC->PAD[IOC_PAD_PB18].FUNC_CTL = IOC_PB18_FUNC_CTL_PWM1_P_1;
  101. HPM_IOC->PAD[IOC_PAD_PB19].FUNC_CTL = IOC_PB19_FUNC_CTL_PWM1_P_0;
  102. HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_PWM1_P_3;
  103. HPM_IOC->PAD[IOC_PAD_PE06].FUNC_CTL = IOC_PE06_FUNC_CTL_PWM3_P_2;
  104. HPM_IOC->PAD[IOC_PAD_PB03].FUNC_CTL = IOC_PB03_FUNC_CTL_GPIO_B_03;
  105. // PWM 使能引脚 失能后pwm信号无效 修改引脚后这里要修改 https://tools.hpmicro.com/pinmux
  106. gpiom_set_pin_controller(GPIOM_BASE, GPIOM_PORT_ASSIGN, PWM_EN_GPIO_PIN, gpiom_soc_gpio0);
  107. gpio_set_pin_output(PWM_EN_GPIO_CTRL, PWM_EN_GPIO_INDEX, PWM_EN_GPIO_PIN);
  108. gpio_write_pin(PWM_EN_GPIO_CTRL, PWM_EN_GPIO_INDEX, PWM_EN_GPIO_PIN, 1);
  109. }
  110. /**
  111. * @brief pwm 定时器初始化
  112. *
  113. */
  114. static void __motor_pwm_timer_config(void)
  115. {
  116. uint32_t freq0, freq1, freq2, freq3;
  117. freq0 = clock_get_frequency(clock_mot0);
  118. freq1 = clock_get_frequency(clock_mot1);
  119. freq2 = clock_get_frequency(clock_mot2);
  120. freq3 = clock_get_frequency(clock_mot3);
  121. printf("PWM0,1,2,3时钟频率: %d %d %d %d Hz\n", freq0, freq1, freq2, freq3);
  122. gen_pwm_to_motor(PWM_MOTOR1, PWM_MOTOR1_OUT, PWM_MOTOR1_CMP, V8M_MOTOR_PERIOD, V8M_PWM_DEF_VALUE);
  123. gen_pwm_to_motor(PWM_MOTOR2, PWM_MOTOR2_OUT, PWM_MOTOR2_CMP, V8M_MOTOR_PERIOD, V8M_PWM_DEF_VALUE);
  124. gen_pwm_to_motor(PWM_MOTOR3, PWM_MOTOR3_OUT, PWM_MOTOR3_CMP, V8M_MOTOR_PERIOD, V8M_PWM_DEF_VALUE);
  125. gen_pwm_to_motor(PWM_MOTOR4, PWM_MOTOR4_OUT, PWM_MOTOR4_CMP, V8M_MOTOR_PERIOD, V8M_PWM_DEF_VALUE);
  126. }
  127. /**
  128. * @brief 改变 pwm 通道值
  129. */
  130. void Bsp_V8M_YY_PwmSetCHValue(uint8_t m_ch, uint32_t m_value)
  131. {
  132. if (m_value > V8M_MOTOR_PERIOD) {
  133. m_value = V8M_MOTOR_PERIOD;
  134. }
  135. switch (m_ch)
  136. {
  137. case 1:
  138. pwm_cmp_update_cmp_value(PWM_MOTOR1, PWM_MOTOR1_CMP, m_value, 0);
  139. break;
  140. case 2:
  141. pwm_cmp_update_cmp_value(PWM_MOTOR2, PWM_MOTOR2_CMP, m_value, 0);
  142. break;
  143. case 3:
  144. pwm_cmp_update_cmp_value(PWM_MOTOR3, PWM_MOTOR3_CMP, m_value, 0);
  145. break;
  146. case 4:
  147. pwm_cmp_update_cmp_value(PWM_MOTOR4, PWM_MOTOR4_CMP, m_value, 0);
  148. break;
  149. //case 5:
  150. // pwm_cmp_update_cmp_value(PWM_MOTOR5, PWM_MOTOR5_CMP, m_value, 0);
  151. // break;
  152. //case 6:
  153. // pwm_cmp_update_cmp_value(PWM_MOTOR6, PWM_MOTOR6_CMP, m_value, 0);
  154. // break;
  155. default:
  156. break;
  157. }
  158. }
  159. /**
  160. * @brief 获取对应通道比较值
  161. */
  162. uint32_t Bsp_V8M_YY_PwmGetCHValue(uint8_t m_ch)
  163. {
  164. uint16_t m_value = 0;
  165. switch (m_ch)
  166. {
  167. case 1:
  168. m_value = PWM_CMP_CMP_GET(PWM_MOTOR1->CMP[PWM_MOTOR1_CMP]);
  169. break;
  170. case 2:
  171. m_value = PWM_CMP_CMP_GET(PWM_MOTOR2->CMP[PWM_MOTOR2_CMP]);
  172. break;
  173. case 3:
  174. m_value = PWM_CMP_CMP_GET(PWM_MOTOR3->CMP[PWM_MOTOR3_CMP]);
  175. break;
  176. case 4:
  177. m_value = PWM_CMP_CMP_GET(PWM_MOTOR4->CMP[PWM_MOTOR4_CMP]);
  178. break;
  179. //case 5:
  180. // m_value = PWM_CMP_CMP_GET(PWM_MOTOR5->CMP[PWM_MOTOR5_CMP]);
  181. // break;
  182. //case 6:
  183. // m_value = PWM_CMP_CMP_GET(PWM_MOTOR6->CMP[PWM_MOTOR6_CMP]);
  184. // break;
  185. default:
  186. break;
  187. }
  188. return m_value;
  189. }
  190. static void print_pwm_cmp_values_direct(void)
  191. {
  192. printf("=== PWM 通道比较值 ===\n");
  193. // 通道1
  194. uint32_t cmp1 = PWM_CMP_CMP_GET(PWM_MOTOR1->CMP[PWM_MOTOR1_CMP]);
  195. printf("通道1 比较值: 0x%06lX (%lu)\n", cmp1, cmp1);
  196. // 通道2
  197. uint32_t cmp2 = PWM_CMP_CMP_GET(PWM_MOTOR2->CMP[PWM_MOTOR2_CMP]);
  198. printf("通道2 比较值: 0x%06lX (%lu)\n", cmp2, cmp2);
  199. // 通道3
  200. uint32_t cmp3 = PWM_CMP_CMP_GET(PWM_MOTOR3->CMP[PWM_MOTOR3_CMP]);
  201. printf("通道3 比较值: 0x%06lX (%lu)\n", cmp3, cmp3);
  202. // 通道4
  203. uint32_t cmp4 = PWM_CMP_CMP_GET(PWM_MOTOR4->CMP[PWM_MOTOR4_CMP]);
  204. printf("通道4 比较值: 0x%06lX (%lu)\n", cmp4, cmp4);
  205. printf("====================\n");
  206. }
  207. void PWM_IS_ENABLE(void)
  208. {
  209. gpio_write_pin(PWM_EN_GPIO_CTRL, PWM_EN_GPIO_INDEX, PWM_EN_GPIO_PIN, 1);
  210. }
  211. void PWM_IS_DISABLE(void)
  212. {
  213. gpio_write_pin(PWM_EN_GPIO_CTRL, PWM_EN_GPIO_INDEX, PWM_EN_GPIO_PIN, 0);
  214. }
  215. /* motor_pwm_test 经过测试 2026/03/13 */
  216. #ifdef PWM_TEST
  217. void v8m_yy_motor_pwm_test(void)
  218. {
  219. Bsp_V8M_YY_PwmInit();
  220. while(1)
  221. {
  222. board_delay_ms(500);
  223. print_pwm_cmp_values_direct();
  224. }
  225. }
  226. #endif