学习目标

  1. 加强掌握PWM开发流程
  2. 理解定时器与通道的关系
  3. 掌握多通道配置策略
  4. 掌握互补PWM配置策略
  5. 掌握定时器查询方式
  6. 掌握代码抽取优化策略
  7. 掌握PWM调试方式

    学习内容

    需求

    210.png209.png
    211.png
    点亮8个灯,采用pwm的方式。
定时器 通道 引脚 AF 极性 LED序号
T0 ch0 PA7 AF1 ON LED1
PA8 AF1 OP LED2
T7 ch2 PB15 AF3 ON LED3
PC8 AF3 OP LED4
ch1 PB14 AF3 ON LED5
PC7 AF3 OP LED6
ch0 PA5 AF3 ON LED7
PC6 AF3 OP LED8

实现互补效果。

高级定时器单通道互补功能

开发流程

  1. 添加Timer依赖
  2. 初始化PWM
  3. 配置通道的P极和N极
  4. PWM占空比控制

    通道配置

    1. ////////// 配置输出通道
    2. timer_oc_parameter_struct tops;
    3. // ch0
    4. timer_channel_output_struct_para_init(&tops);
    5. // n config
    6. tops.outputnstate = TIMER_CCXN_ENABLE;
    7. // p config
    8. tops.outputstate = TIMER_CCX_ENABLE;
    9. timer_channel_output_config(timerx, TIMER_CH_0, &tops);
  • ocnpolarity:N极性电平
  • ocpolarity:P极性电平

    完整代码

    ```c

    include “gd32f4xx.h”

    include “systick.h”

    include

    include “main.h”

    include “Usart0.h”

// T0 // ch0 PA7 ON // ch0 PA8 OP

// 分频计数 // 周期计数

define PRESCALER (10 - 1)

define PERIOD (SystemCoreClock / 100000 - 1)

void Usart0_recv(uint8_t *data, uint32_t len) {

}

static void PWM_config() { uint32_t timerx = TIMER0; uint32_t timerx_rcu = RCU_TIMER0; uint32_t timerx_psc = RCU_TIMER_PSC_MUL2;

  1. uint32_t timerx_prescaler = PRESCALER; // 分频计数
  2. uint32_t timerx_period = PERIOD; // 周期计数
  3. uint32_t timerx_ch0_p_port = GPIOA;
  4. uint32_t timerx_ch0_p_port_rcu = RCU_GPIOA;
  5. uint32_t timerx_ch0_p_pin = GPIO_PIN_8;
  6. uint32_t timerx_ch0_p_af = GPIO_AF_1;
  7. uint32_t timerx_ch0_n_port = GPIOA;
  8. uint32_t timerx_ch0_n_port_rcu = RCU_GPIOA;
  9. uint32_t timerx_ch0_n_pin = GPIO_PIN_7;
  10. uint32_t timerx_ch0_n_af = GPIO_AF_1;
  11. /*************** GPIO config **************/
  12. //// ch0 p
  13. // 配置时钟
  14. rcu_periph_clock_enable(timerx_ch0_p_port_rcu);
  15. // 配置GPIO模式
  16. gpio_mode_set(timerx_ch0_p_port, GPIO_MODE_AF, GPIO_PUPD_NONE, timerx_ch0_p_pin);
  17. // 配置GPIO输出
  18. gpio_output_options_set(timerx_ch0_p_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, timerx_ch0_p_pin);
  19. // 配置复用功能
  20. gpio_af_set(timerx_ch0_p_port, timerx_ch0_p_af, timerx_ch0_p_pin);
  21. //// ch0 n
  22. // 配置时钟
  23. rcu_periph_clock_enable(timerx_ch0_n_port_rcu);
  24. // 配置GPIO模式
  25. gpio_mode_set(timerx_ch0_n_port, GPIO_MODE_AF, GPIO_PUPD_NONE, timerx_ch0_n_pin);
  26. // 配置GPIO输出
  27. gpio_output_options_set(timerx_ch0_n_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, timerx_ch0_n_pin);
  28. // 配置复用功能
  29. gpio_af_set(timerx_ch0_n_port, timerx_ch0_n_af, timerx_ch0_n_pin);
  30. /*************** Timer config *************/
  31. // 时钟配置
  32. rcu_periph_clock_enable(timerx_rcu);
  33. // 复位定时器
  34. timer_deinit(timerx);
  35. // 倍频配置
  36. rcu_timer_clock_prescaler_config(timerx_psc);
  37. // 初始化定时器
  38. timer_parameter_struct tps;
  39. timer_struct_para_init(&tps);
  40. tps.prescaler = timerx_prescaler; // 分频计数
  41. tps.period = timerx_period; // 周期计数
  42. timer_init(timerx, &tps);
  43. ////////// 配置输出通道
  44. timer_oc_parameter_struct tops;
  45. // ch0
  46. timer_channel_output_struct_para_init(&tops);
  47. // n config
  48. tops.outputnstate = TIMER_CCXN_ENABLE;
  49. // p config
  50. tops.outputstate = TIMER_CCX_ENABLE;
  51. timer_channel_output_config(timerx, TIMER_CH_0, &tops);
  52. ////////// 输出模式配置
  53. // ch0
  54. timer_channel_output_mode_config(timerx, TIMER_CH_0, TIMER_OC_MODE_PWM0);
  55. ////////// Break配置
  56. timer_break_parameter_struct tbps;
  57. timer_break_struct_para_init(&tbps);
  58. tbps.breakpolarity = TIMER_BREAK_POLARITY_HIGH;
  59. tbps.outputautostate = TIMER_OUTAUTO_ENABLE;
  60. tbps.breakstate = TIMER_BREAK_ENABLE;
  61. timer_break_config(timerx, &tbps);
  62. // 初始化
  63. timer_enable(timerx);

}

static void PWM_update_ch0(float duty) { uint32_t timerx = TIMER0; uint32_t timerx_chn = TIMER_CH_0;

  1. uint32_t pulse = duty * (PERIOD + 1) / 100;
  2. /***************** pwm update *******************/
  3. // 配置输出的占空比
  4. timer_channel_output_pulse_value_config(timerx, timerx_chn, pulse);

}

static void GPIO_config() { // 配置时钟 rcu_periph_clock_enable(RCU_GPIOA); // 配置GPIO模式 gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3); // 配置GPIO输出 gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_3); }

int main(void) { systick_config(); nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); Usart0_init(); GPIO_config(); PWM_config();

  1. gpio_bit_reset(GPIOA, GPIO_PIN_3);
  2. int8_t i;
  3. while(1) {
  4. for(i = 0; i < 25; i++) {
  5. PWM_update_ch0(i);
  6. delay_1ms(50);
  7. }
  8. for(i = 24; i >= 0; i--) {
  9. PWM_update_ch0(i);
  10. delay_1ms(50);
  11. }
  12. delay_1ms(1000);
  13. }

}

  1. <a name="q1l0U"></a>
  2. ### 高级定时器多通道互补功能
  3. <a name="qXpuR"></a>
  4. #### 开发流程
  5. 1. 添加Timer依赖
  6. 2. 初始化PWM
  7. 3. 配置通道的P极和N极
  8. 4. PWM占空比控制
  9. <a name="sLxj0"></a>
  10. #### 多通道配置
  11. ```c
  12. timer_oc_parameter_struct tops;
  13. timer_channel_output_struct_para_init(&tops);
  14. // n config
  15. tops.outputnstate = TIMER_CCXN_ENABLE;
  16. tops.ocnpolarity = TIMER_OCN_POLARITY_LOW;
  17. // p config
  18. tops.outputstate = TIMER_CCX_ENABLE;
  19. tops.ocpolarity = TIMER_OC_POLARITY_LOW;
  20. ///// ch0
  21. timer_channel_output_config(timerx, TIMER_CH_0, &tops);
  22. ///// ch1
  23. timer_channel_output_config(timerx, TIMER_CH_1, &tops);
  24. ///// ch2
  25. timer_channel_output_config(timerx, TIMER_CH_2, &tops);

完整代码

  1. #include "gd32f4xx.h"
  2. #include "systick.h"
  3. #include <stdio.h>
  4. #include "main.h"
  5. #include "Usart0.h"
  6. // T7
  7. // ch0
  8. // N: PA5 ON
  9. // P: PC6 OP
  10. // ch1
  11. // N: PB14 ON
  12. // P: PC7 OP
  13. // ch2
  14. // N: PB15 ON
  15. // P: PC8 OP
  16. // 分频计数
  17. // 周期计数
  18. #define PRESCALER (10 - 1)
  19. #define PERIOD (SystemCoreClock / 100000 - 1)
  20. void Usart0_recv(uint8_t *data, uint32_t len) {
  21. }
  22. static void PWM_config() {
  23. uint32_t timerx = TIMER7;
  24. uint32_t timerx_rcu = RCU_TIMER7;
  25. uint32_t timerx_psc = RCU_TIMER_PSC_MUL2;
  26. uint32_t timerx_prescaler = PRESCALER; // 分频计数
  27. uint32_t timerx_period = PERIOD; // 周期计数
  28. // ch0
  29. uint32_t timerx_ch0_n_port = GPIOA;
  30. uint32_t timerx_ch0_n_port_rcu = RCU_GPIOA;
  31. uint32_t timerx_ch0_n_pin = GPIO_PIN_5;
  32. uint32_t timerx_ch0_n_af = GPIO_AF_3;
  33. uint32_t timerx_ch0_p_port = GPIOC;
  34. uint32_t timerx_ch0_p_port_rcu = RCU_GPIOC;
  35. uint32_t timerx_ch0_p_pin = GPIO_PIN_6;
  36. uint32_t timerx_ch0_p_af = GPIO_AF_3;
  37. // ch1
  38. uint32_t timerx_ch1_n_port = GPIOB;
  39. uint32_t timerx_ch1_n_port_rcu = RCU_GPIOB;
  40. uint32_t timerx_ch1_n_pin = GPIO_PIN_14;
  41. uint32_t timerx_ch1_n_af = GPIO_AF_3;
  42. uint32_t timerx_ch1_p_port = GPIOC;
  43. uint32_t timerx_ch1_p_port_rcu = RCU_GPIOC;
  44. uint32_t timerx_ch1_p_pin = GPIO_PIN_7;
  45. uint32_t timerx_ch1_p_af = GPIO_AF_3;
  46. // ch2
  47. uint32_t timerx_ch2_n_port = GPIOB;
  48. uint32_t timerx_ch2_n_port_rcu = RCU_GPIOB;
  49. uint32_t timerx_ch2_n_pin = GPIO_PIN_15;
  50. uint32_t timerx_ch2_n_af = GPIO_AF_3;
  51. uint32_t timerx_ch2_p_port = GPIOC;
  52. uint32_t timerx_ch2_p_port_rcu = RCU_GPIOC;
  53. uint32_t timerx_ch2_p_pin = GPIO_PIN_8;
  54. uint32_t timerx_ch2_p_af = GPIO_AF_3;
  55. /*************** GPIO config **************/
  56. //// ch0
  57. //// p
  58. // 配置时钟
  59. rcu_periph_clock_enable(timerx_ch0_p_port_rcu);
  60. // 配置GPIO模式
  61. gpio_mode_set(timerx_ch0_p_port, GPIO_MODE_AF, GPIO_PUPD_NONE, timerx_ch0_p_pin);
  62. // 配置GPIO输出
  63. gpio_output_options_set(timerx_ch0_p_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, timerx_ch0_p_pin);
  64. // 配置复用功能
  65. gpio_af_set(timerx_ch0_p_port, timerx_ch0_p_af, timerx_ch0_p_pin);
  66. //// n
  67. // 配置时钟
  68. rcu_periph_clock_enable(timerx_ch0_n_port_rcu);
  69. // 配置GPIO模式
  70. gpio_mode_set(timerx_ch0_n_port, GPIO_MODE_AF, GPIO_PUPD_NONE, timerx_ch0_n_pin);
  71. // 配置GPIO输出
  72. gpio_output_options_set(timerx_ch0_n_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, timerx_ch0_n_pin);
  73. // 配置复用功能
  74. gpio_af_set(timerx_ch0_n_port, timerx_ch0_n_af, timerx_ch0_n_pin);
  75. //// ch1
  76. //// p
  77. // 配置时钟
  78. rcu_periph_clock_enable(timerx_ch1_p_port_rcu);
  79. // 配置GPIO模式
  80. gpio_mode_set(timerx_ch1_p_port, GPIO_MODE_AF, GPIO_PUPD_NONE, timerx_ch1_p_pin);
  81. // 配置GPIO输出
  82. gpio_output_options_set(timerx_ch1_p_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, timerx_ch1_p_pin);
  83. // 配置复用功能
  84. gpio_af_set(timerx_ch1_p_port, timerx_ch1_p_af, timerx_ch1_p_pin);
  85. //// n
  86. // 配置时钟
  87. rcu_periph_clock_enable(timerx_ch1_n_port_rcu);
  88. // 配置GPIO模式
  89. gpio_mode_set(timerx_ch1_n_port, GPIO_MODE_AF, GPIO_PUPD_NONE, timerx_ch1_n_pin);
  90. // 配置GPIO输出
  91. gpio_output_options_set(timerx_ch1_n_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, timerx_ch1_n_pin);
  92. // 配置复用功能
  93. gpio_af_set(timerx_ch1_n_port, timerx_ch1_n_af, timerx_ch1_n_pin);
  94. //// ch2
  95. //// p
  96. // 配置时钟
  97. rcu_periph_clock_enable(timerx_ch2_p_port_rcu);
  98. // 配置GPIO模式
  99. gpio_mode_set(timerx_ch2_p_port, GPIO_MODE_AF, GPIO_PUPD_NONE, timerx_ch2_p_pin);
  100. // 配置GPIO输出
  101. gpio_output_options_set(timerx_ch2_p_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, timerx_ch2_p_pin);
  102. // 配置复用功能
  103. gpio_af_set(timerx_ch2_p_port, timerx_ch2_p_af, timerx_ch2_p_pin);
  104. //// n
  105. // 配置时钟
  106. rcu_periph_clock_enable(timerx_ch2_n_port_rcu);
  107. // 配置GPIO模式
  108. gpio_mode_set(timerx_ch2_n_port, GPIO_MODE_AF, GPIO_PUPD_NONE, timerx_ch2_n_pin);
  109. // 配置GPIO输出
  110. gpio_output_options_set(timerx_ch2_n_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, timerx_ch2_n_pin);
  111. // 配置复用功能
  112. gpio_af_set(timerx_ch2_n_port, timerx_ch2_n_af, timerx_ch2_n_pin);
  113. /*************** Timer config *************/
  114. // 时钟配置
  115. rcu_periph_clock_enable(timerx_rcu);
  116. // 复位定时器
  117. timer_deinit(timerx);
  118. // 倍频配置
  119. rcu_timer_clock_prescaler_config(timerx_psc);
  120. // 初始化定时器
  121. timer_parameter_struct tps;
  122. timer_struct_para_init(&tps);
  123. tps.prescaler = timerx_prescaler; // 分频计数
  124. tps.period = timerx_period; // 周期计数
  125. timer_init(timerx, &tps);
  126. ////////// 配置输出通道
  127. timer_oc_parameter_struct tops;
  128. ///// ch0
  129. timer_channel_output_struct_para_init(&tops);
  130. // n config
  131. tops.outputnstate = TIMER_CCXN_ENABLE;
  132. tops.ocpolarity = TIMER_OC_POLARITY_LOW;
  133. // p config
  134. tops.outputstate = TIMER_CCX_ENABLE;
  135. tops.ocpolarity = TIMER_OC_POLARITY_LOW;
  136. timer_channel_output_config(timerx, TIMER_CH_0, &tops);
  137. ///// ch1
  138. timer_channel_output_struct_para_init(&tops);
  139. // n config
  140. tops.outputnstate = TIMER_CCXN_ENABLE;
  141. // p config
  142. tops.outputstate = TIMER_CCX_ENABLE;
  143. tops.ocpolarity = TIMER_OC_POLARITY_LOW;
  144. timer_channel_output_config(timerx, TIMER_CH_1, &tops);
  145. ///// ch2
  146. timer_channel_output_struct_para_init(&tops);
  147. // n config
  148. tops.outputnstate = TIMER_CCXN_ENABLE;
  149. // p config
  150. tops.outputstate = TIMER_CCX_ENABLE;
  151. tops.ocpolarity = TIMER_OC_POLARITY_LOW;
  152. timer_channel_output_config(timerx, TIMER_CH_2, &tops);
  153. ////////// 输出模式配置
  154. // ch0
  155. timer_channel_output_mode_config(timerx, TIMER_CH_0, TIMER_OC_MODE_PWM0);
  156. // ch1
  157. timer_channel_output_mode_config(timerx, TIMER_CH_1, TIMER_OC_MODE_PWM0);
  158. // ch2
  159. timer_channel_output_mode_config(timerx, TIMER_CH_2, TIMER_OC_MODE_PWM0);
  160. ////////// Break配置
  161. timer_break_parameter_struct tbps;
  162. timer_break_struct_para_init(&tbps);
  163. tbps.breakpolarity = TIMER_BREAK_POLARITY_HIGH;
  164. tbps.outputautostate = TIMER_OUTAUTO_ENABLE;
  165. tbps.breakstate = TIMER_BREAK_ENABLE;
  166. timer_break_config(timerx, &tbps);
  167. // 初始化
  168. timer_enable(timerx);
  169. }
  170. static void PWM_update_ch0(float duty) {
  171. uint32_t timerx = TIMER7;
  172. uint32_t timerx_chn = TIMER_CH_0;
  173. uint32_t pulse = duty * (PERIOD + 1) / 100;
  174. /***************** pwm update *******************/
  175. // 配置输出的占空比
  176. timer_channel_output_pulse_value_config(timerx, timerx_chn, pulse);
  177. }
  178. static void PWM_update_ch1(float duty) {
  179. uint32_t timerx = TIMER7;
  180. uint32_t timerx_chn = TIMER_CH_1;
  181. uint32_t pulse = duty * (PERIOD + 1) / 100;
  182. /***************** pwm update *******************/
  183. // 配置输出的占空比
  184. timer_channel_output_pulse_value_config(timerx, timerx_chn, pulse);
  185. }
  186. static void PWM_update_ch2(float duty) {
  187. uint32_t timerx = TIMER7;
  188. uint32_t timerx_chn = TIMER_CH_2;
  189. uint32_t pulse = duty * (PERIOD + 1) / 100;
  190. /***************** pwm update *******************/
  191. // 配置输出的占空比
  192. timer_channel_output_pulse_value_config(timerx, timerx_chn, pulse);
  193. }
  194. static void GPIO_config() {
  195. // 配置时钟
  196. rcu_periph_clock_enable(RCU_GPIOA);
  197. // 配置GPIO模式
  198. gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3);
  199. // 配置GPIO输出
  200. gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);
  201. }
  202. int main(void)
  203. {
  204. systick_config();
  205. nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
  206. Usart0_init();
  207. GPIO_config();
  208. PWM_config();
  209. gpio_bit_reset(GPIOA, GPIO_PIN_3);
  210. int8_t i;
  211. while(1) {
  212. for(i = 0; i < 25; i++) {
  213. PWM_update_ch0(i);
  214. PWM_update_ch1(i);
  215. PWM_update_ch2(i);
  216. delay_1ms(50);
  217. }
  218. for(i = 24; i >= 0; i--) {
  219. PWM_update_ch0(i);
  220. PWM_update_ch1(i);
  221. PWM_update_ch2(i);
  222. delay_1ms(50);
  223. }
  224. delay_1ms(1000);
  225. }
  226. }

练习题

  1. 实现互补pwm