一.相关知识介绍
脉冲宽度调制(PWM) :是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。
频率 :时钟速度 1GHZ = 1000MHZ = 1000 000 KHZ =1 000 000 000 HZ(如12MHz:1秒12 000 000个脉冲)
占空比 :占空比是指在一个脉冲循环内,通电时间(有效电平)相对于一个脉冲总时间所占的比例。(可以简单理解为该高、低电平的占脉冲总时间的比例)。
PWM原理如下图所示:
这就是一个简单的PWM原理示意图。图中,我们假定定时器工作在向上计数PWM模式,且当CNT<CCRx时,输出0,当CNT>=CCRx时输出1。那么就可以得到如上的PWM示意图:当CNT值小于CCRx的时候,IO输出低电平(0),当CNT值大于等于CCRx的时候,IO输出高电平(1),当CNT达到ARR值的时候,重新归零,然后重新向上计数,依次循环。改变CCRx的值,就可以改变PWM输出的占空比,改变ARR的值,就可以改变PWM输出的频率,这就是PWM输出的原理。
查看GD32F4xx系列器件的用户手册,可以发现,其中除了TIM5和6(基本定时器)以外,其他的定时器都可以用来产生PWM输出。这里考虑到板子自带的LED2是接在了PC6引脚上,通过引脚复用功能的重映射配置TIMER2\_CH0到 PC6上,由TIMER2\_CH0输出PWM波来控制LED2的亮度,如呼吸一样的闪烁。
二.代码实现
本次以兆易创新库开发的方式进行代码的编写。
1.配置GPIO
本实验使用PC6作为定时器PWM输出通道,先对它进行初始化。用作PWM输出通道的引脚需要被配置为复用推挽输出模式。
关于引脚功能复用的介绍详见GD32F427xx_Datasheet_Rev1.2这份芯片数据手册的第2.6小节Pin definitions。
void gpio_config(void)
{
rcu_periph_clock_enable(RCU_GPIOC);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
gpio_af_set(GPIOC, GPIO_AF_2, GPIO_PIN_6);
}
2.配置定时器模式
在timer\_config()函数中,完成了呼吸灯所需要的定时器PWM输出模式配置。
void timer_config(void)
{
timer_oc_parameter_struct timer_ocinitpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER2);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
timer_deinit(TIMER2);
timer_initpara.prescaler = 199;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 250;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER2,&timer_initpara);
timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocinitpara.outputstate = TIMER_CCX_ENABLE;
timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE;
timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIMER2,TIMER_CH_0,&timer_ocinitpara);
timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,0);
timer_channel_output_mode_config(TIMER2,TIMER_CH_0,TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER2,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);
timer_auto_reload_shadow_enable(TIMER2);
timer_enable(TIMER2);
}
3.主循环中延时函数5ms的引用
借助演示代码systick.c中的延时函数,来实现精确的5ms延时。
首先引用头文件:
#include "systick.h"
然后即可直接调用systick.c中的系统时钟配置函数systick_config(),进行系统定时器中断的相关配置。
4.最终主函数逻辑
经过代码的整合,加上循环逻辑,不断的修改PWM波的占空比,就可以实现呼吸灯的效果了。
int main(void)
{
uint16_t i = 0;
FlagStatus breathe_flag = SET;
gpio_config();
timer_config();
systick_config();
while(1)
{
delay_1ms(5);
if(SET == breathe_flag)
{
i++;
}
else
{
i
}
if(250 < i)
{
breathe_flag = RESET;
}
if(0 >= i)
{
breathe_flag = SET;
}
TIMER_CH0CV(TIMER2) = (uint32_t)i;
}
}
原作者:Q_dGHvwj