一、PWM基础知识
1.PWM介绍
PWM(Pulse Width Modulation脉宽调制)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号任然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有,要么完全无。比如我们的电压输出是5v的,那么经过改变PWM的占空比,可以达到在一定时间内输出3.3V或者1.3V的效果。
2.GD32PWM了解
GD32F450ZGT6一共有14个定时器,可以分为五种类型,高级定时器0/7、通用定时器(L0)1-4、通用定时器(L1)8/11、通用定时器(L2)9/10/12/13和基本定时器5/6。
定时器类型 | 高级定时器0/7 | 通用定时器(L0)1-4 | 通用定时器(L1)8/11 | 通用定时器(L2)9/10/12/13 | 基本定时器5/6 |
通道数 | 4 | 4 | 2 | 1 | 0 |
3.PWM基本参数
参数 | 描述 |
频率 | 频率是值每秒钟信号从高电平到低电平再回到高电平的次数。 |
占空比 | 占空比是指一个周期内高电平所占的比例。 |
周期 | 周期是指一个完整PWM信号持续的时间。 |
4.PWM控制方法
如这里所示,GD32F450xx的led4 的IO口为PA5,这里PA5有对应的TIMER1的CH0可以作为计时器
只要脉冲的积分是一样的,那么两种脉冲具有相同的效果
5.PWM应用
PWM可应用于电机调速、功率调制、PID调节、通信等,配置简单、抗干扰能力强。可以通过PWM来控制LED灯的亮暗变化,可以通过PWM信号来控制无源蜂鸣器发出简单的声音以及实现功率继电器的线圈节能等。PWM用来驱动电机和调节电机转速是非常重要的内容。
二、PWM操作流程
通过驱动PWM实现一个呼吸灯的效果,通过PWM信号占空比的变化,可以实现流过LED电流的不同,实现LED亮暗的渐变。
三、配置PWM流程
1.配置通道引脚GPIO
led4灯的PWM映射到PA5的GPIO(PA5)
void pwmgpio_config(void)
{
/* 宏定义引脚
#define BSP_PWM_RCUBSP_PWM_RCU RCU_GPIOA
#define BSP_PWM_PORT GPIOA
#define BSP_PWM_PIN GPIO_PIN_5
#define BSP_PWM_AF GPIO_AF_1
*/
/* 使能时钟*/
rcu_periph_clock_enable(BSP_PWM_RCU);
/*配置GPIO的模式:复用*/
gpio_mode_set(BSP_PWM_PORT,GPIO_MODE_AF,GPIO_PUPD_NONE,BSP_PWM_PIN );
/* 配置GPIO的输出模式 */
gpio_output_options_set(BSP_PWM_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,BSP_PWM_PIN);
gpio_af_set(BSP_PWM_PORT,BSP_PWM_AF,BSP_PWM_PIN);
}
这里的GPIO的输出模式是复用,所以在下面需要再一次对其进行引脚复用设置
2.配置定时器
在使用pwm之前 需要对其对应的gpio进行声明
void pwm_config(uint16_t pre, uint16_t per)
{
pwmgpio_config();
/* 初始化参数的结构体 */
timer_parameter_struct timer_initpara;
/* 开启定时器时钟
#define BSP_TIMER_RCU RCU_TIMER5
*/
rcu_periph_clock_enable(BSP_PWM_TIMER_RCU);
//定时器的时钟配置为了200M
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
/*
#define BSP_TIMER TIMER5
初始化定时器
#define BSP_PWM_TIMER_RCU RCU_TIMER1
#define BSP_PWM_TIMER TIMER1
*/
timer_deinit(BSP_PWM_TIMER_RCU);
timer_initpara.prescaler = pre-1; // 计时时间
timer_initpara.alignedmode = TIMER_COUNTER_EDGE; //对齐模式
timer_initpara.counterdirection = TIMER_COUNTER_UP; //计数模式
timer_initpara.clockdivision = TIMER_CKDIV_DIV1; //分频因子
timer_initpara.period = per-1 ; //周期
timer_initpara.repetitioncounter = 0; //重复计数器
timer_init(BSP_PWM_TIMER_RCU,&timer_initpara);
/*配置中断的优先级
#define BSP_TIMER_IRQ TIMER5_DAC_IRQn
*/
timer_enable(BSP_PWM_TIMER_RCU);//参数为定时器
}
3.配置输出结构体
参数 | 描述 |
ocpolarity | 通道输出的极性,也就是配置为低电平有效还是高电平有效,这里配置为高电平有效TIMER_OC_POLARITY_HIGH。 |
outputstate | 通道输出状态,一般是使能TIMER_CCX_ENABLE,使能PWM输出到端口。 |
这里只使用了极性和输出通道状态,因为是led灯,所以配置为高电平有效
/* 输出结构体 、输出配置*/
timer_ocinpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocinpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(BSP_PWM_TIMER_RCU,BSP_PWM_CHANNEL,&timer_ocinpara);
4.配置定时器输出通道
/* 配置输出模式为PWM0模式 */
timer_channel_output_mode_config(BSP_PWM_TIMER,BSP_PWM_CHANNEL,TIMER_OC_MODE_PWM0);
5.配置定时器输出通道占空比
在per的输入值为200时,psc_clk的值为200MHz/200 = 1MHz,要使输出的频率为100Hz 那pre的值应该为10000,则PWM的占空比为100/10000
/* 输出占空比 */
timer_channel_output_pulse_value_config(BSP_PWM_TIMER,BSP_PWM_CHANNEL,100);
6.定时器自动重载影子使能
/* 自动影子重载使能 */
timer_auto_reload_shadow_enable(BSP_PWM_TIMER);
四、呼吸灯函数
void pwm_breathing_lamp(void)
{
static uint8_t direct = 0;// 方向
static uint16_t value = 0;// 脉冲值
if(direct == 0)//逐渐变亮的过程
{
value +=200;
if(value >=10000)
{
direct = 1;
}
}
else
{
value -=200;
if(value <= 0)
{
direct = 0;
}
}
timer_channel_output_pulse_value_config(BSP_PWM_TIMER,BSP_PWM_CHANNEL,value);
delay_1ms(25);
}