目录
文章目录
前言
目标
学习内容
需求
高级定时器通道互补输出
开发流程
通道配置
打开互补保护电路
完整代码
练习题
总结
前言
在嵌入式软件开发中,PWM(脉冲宽度调制)技术被广泛应用于控制各种电子设备的亮度、速度等参数。理解PWM开发流程、定时器与通道的关系,掌握多通道配置策略和互补PWM配置策略,以及掌握定时器查询方式和代码抽取优化策略,对于提高嵌入式软件开发的效率和质量至关重要。
本次学习的目标是点亮2个LED灯,采用互补PWM的方式来控制互补LED效果。通过学习高级定时器通道互补输出,我们将逐步了解如何初始化PWM、配置通道的P极和N极、控制PWM占空比,以实现目标效果。
目标
- 加强掌握PWM开发流程
- 理解定时器与通道的关系
- 掌握多通道配置策略
- 掌握互补PWM配置策略
- 掌握定时器查询方式
- 掌握代码抽取优化策略
- 掌握PWM调试方式
学习内容
需求
点亮2个灯,采用互补pwm的方式
定时器 | 通道 | 引脚 | AF | 极性 | LED序号 |
T0 | ch0 | PE8 | AF1 | ON | LED1 |
PE9 | AF1 | OP | LED2 |
将PE8短接至PD8,PE9短接至PD9,实现互补LED效果。
高级定时器通道互补输出
开发流程
- 添加Timer依赖
- 初始化PWM
- 配置通道的P极和N极
- PWM占空比控制
通道配置
void timer_channel_config(uint32_t timer_periph, uint16_t channel) {/* TIMER 通道输出配置 */timer_oc_parameter_struct ocpara;/* initialize TIMER channel output parameter struct */timer_channel_output_struct_para_init(&ocpara);ocpara.outputstate = TIMER_CCX_ENABLE; // OP Enableocpara.outputnstate = TIMER_CCXN_ENABLE; // ON Enableocpara.ocpolarity = TIMER_OC_POLARITY_HIGH; // OP Polarityocpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; // ON Polarity/* 配置输出参数 configure TIMER channel output function */timer_channel_output_config(timer_periph, channel, &ocpara);/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}
- ocnpolarity:N极性电平
- ocpolarity:P极性电平
打开互补保护电路
// break 只针对高级定时器TIMER0 & TIMER7,打开互补保护电路
/* TIMER通道互补保护电路 */
timer_break_parameter_struct breakpara;
/* 初始化TIMER break参数结构体 */
timer_break_struct_para_init(&breakpara);
/* break输入的极性 HIGH */
breakpara.breakpolarity = TIMER_BREAK_POLARITY_HIGH;
/* 输出自动的启用 */
breakpara.outputautostate = TIMER_OUTAUTO_ENABLE;
/* break输入的启用*/
breakpara.breakstate = TIMER_BREAK_ENABLE;
/* 配置TIMER0 break */
timer_break_config(TIMER0, &breakpara);
/* 启用TIMER0 break */
timer_break_enable(TIMER0);
完整代码
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "USART0.h"void USART0_on_recv(uint8_t* data, uint32_t len) {printf("g_rx_buffer: %s g_rx_cnt:%d \n", data, len);
}static void GPIO_config() {rcu_periph_clock_enable(RCU_GPIOC);gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);gpio_bit_reset(GPIOC, GPIO_PIN_6);// rcu_periph_clock_enable(RCU_GPIOD);
// gpio_mode_set(GPIOD, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_8 | GPIO_PIN_9);
}void timer_gpio_config(uint32_t gpio_rcu, uint32_t gpio_port, uint32_t gpio_pin, uint32_t gpio_af) {rcu_periph_clock_enable(gpio_rcu);/* 设置gpio模式 */gpio_mode_set(gpio_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_pin);gpio_output_options_set(gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, gpio_pin);gpio_af_set(gpio_port, gpio_af, gpio_pin);
}void timer_init_config(rcu_periph_enum rcu_periph, uint32_t timer_periph,uint16_t t_prescaler, uint32_t t_period) {rcu_periph_clock_enable(rcu_periph);timer_deinit(timer_periph);/*初始化参数 */timer_parameter_struct initpara;/* initialize TIMER init parameter struct */timer_struct_para_init(&initpara);/* 根据需要配置值 分频系数 (可以实现更低的timer频率) */initpara.prescaler = t_prescaler - 1;/* 1个周期的计数(period Max: 65535) Freq > 3662 */initpara.period = t_period - 1;/* initialize TIMER counter */timer_init(timer_periph, &initpara);/* enable a TIMER */timer_enable(timer_periph);}void timer_channel_config(uint32_t timer_periph, uint16_t channel) {/* TIMER 通道输出配置 */timer_oc_parameter_struct ocpara;/* initialize TIMER channel output parameter struct */timer_channel_output_struct_para_init(&ocpara);ocpara.outputstate = TIMER_CCX_ENABLE; // OP Enableocpara.outputnstate = TIMER_CCXN_ENABLE; // ON Enableocpara.ocpolarity = TIMER_OC_POLARITY_HIGH; // OP Polarityocpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; // ON Polarity/* 配置输出参数 configure TIMER channel output function */timer_channel_output_config(timer_periph, channel, &ocpara);/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}// PWM
#define PRESCALER 1
#define FREQ 10000
#define PERIOD (SystemCoreClock / FREQ)// LED1 TM0CH1 PE9 OP
// LED2 TM0CH0 PE8 ON
static void Timer_config() {// 定时器// GPIO ----------------------------------------timer_gpio_config(RCU_GPIOE, GPIOE, GPIO_PIN_9, GPIO_AF_1);timer_gpio_config(RCU_GPIOE, GPIOE, GPIO_PIN_8, GPIO_AF_1);// TIMER----------------------------------------/* 升级频率*/rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);timer_init_config(RCU_TIMER0, TIMER0, PRESCALER, PERIOD); // 与通道无关// TIMER channel-------------------------------timer_channel_config(TIMER0, TIMER_CH_0);// Break --------------------------------------------------// break 只针对高级定时器TIMER0 & TIMER7,打开互补保护电路/* TIMER通道互补保护电路 */timer_break_parameter_struct breakpara;/* 初始化TIMER break参数结构体 */timer_break_struct_para_init(&breakpara);/* break输入的极性 HIGH */breakpara.breakpolarity = TIMER_BREAK_POLARITY_HIGH;/* 输出自动的启用 */breakpara.outputautostate = TIMER_OUTAUTO_ENABLE;/* break输入的启用*/breakpara.breakstate = TIMER_BREAK_ENABLE;/* 配置TIMER0 break */timer_break_config(TIMER0, &breakpara);/* 启用TIMER0 break */timer_break_enable(TIMER0);}/*********************************************************** @brief 更新pwm占空比* @param timer_periph 定时器* @param channel 通道* @param duty 占空比[0, 100]* @return **********************************************************/
void PWM_update(uint32_t timer_periph, uint16_t channel, float duty) { // 0-100if(duty > 100) duty = 100;else if(duty < 0) duty = 0;// pulse / PERIOD == duty / 100uint32_t pulse = PERIOD * duty / 100.0f - 1;// 计数值 65535timer_channel_output_pulse_value_config(timer_periph, channel, pulse);
}int main(void)
{systick_config();USART0_init();// 拉低总开关
// GPIO_config();Timer_config();printf("Init Complete!\n");float duty = 0;int8_t dir = 1;while(1) {PWM_update(TIMER0, TIMER_CH_0, duty);if (duty >= 100) {dir = -1;} else if (duty <= 0) {dir = 1;}duty += dir;printf("duty: %.2f \n", duty);delay_1ms(10);}
}
练习题
总结
通过本次学习,我们深入了解了PWM技术在嵌入式软件开发中的应用。从添加Timer依赖开始,我们逐步完成了初始化PWM、配置通道的P极和N极、设定PWM占空比等步骤,最终实现了点亮2个LED灯的效果,并采用互补PWM的方式来控制LED的亮度。
在实现过程中,我们学习了定时器与通道的关系,掌握了多通道配置策略和互补PWM配置策略,同时了解了定时器查询方式和代码抽取优化策略,为日后更高效地进行PWM开发打下了坚实的基础。通过不断学习和实践,我们将能够提升自己在嵌入式软件开发领域的技能水平,开发出更加优秀和稳定的产品和应用。