上一章我们讲了定时器,本章我们来看一下PWM的功能,并实现一个呼吸灯的小实验;
PWM控制的是脉冲输出的占空比,占空比是指在一个脉冲循环内,通电时间相对于总时间所占的比例。比如说,一个RGB灯在它一个工作周期中有一半时间被接通了,那么它的占空比就是50%,同时亮度也只有50%。如果加在该工作元件上的信号电压为3V,则实际的工作电压平均值或电压有效值就是1.5V。
详细介绍可以参考我的这篇博客,原理都是类似的STM32开发(6)----CubeMX配置PWM
K210芯片定时器总共有3个,每个定时器有4路通道。每个定时器可以设置触发间隔,和定时器中断处理函数。定时器还可以设置为PWM输出的功能,但是如果设置PWM输出,则不可以使用定时的功能。
PWM 用于控制脉冲输出的占空比。其本质是一个定时器,所以注意设置 PWM 号与通道时不要与 TIMER定时器冲突。
PWM 模块具有以下功能:
? 配置 PWM 输出频率
? 配置 PWM 每个管脚的输出占空比
对应头文件 pwm.h
为用户提供以下接口
? pwm_init
? pwm_set_frequency
? pwm_set_enable
为了呈现实验效果,本文还使用RGB灯来观察现象
新建pwm文件夹,在文件夹里新建main.c
注意包含头文件
#include "fpioa.h"
#include "sleep.h"
#include "gpio.h"
#include "sysctl.h"
#include "plic.h"
#include "timer.h"
#include "pwm.h"
/*****************************HARDWARE-PIN*********************************/
// 硬件IO口,与原理图对应
#define PIN_RGB_R (12)
/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define RGB_R_GPIONUM (0)
/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
#define FUNC_RGB_R (FUNC_GPIO0 + RGB_R_GPIONUM)
void hardware_init(void)
{
fpioa_set_function(PIN_RGB_R, FUNC_TIMER1_TOGGLE1);//绑定pwm function
}
/**
* Function timer_timeout_cb
* @brief 定时器中断回调
* @param[in] ctx
* @param[out] void
* @retval 0
* @par History 无
*/
int timer_timeout_cb(void *ctx) {
static double duty_cycle = 0.01;
/* 0为渐增,1为渐减 */
static int flag = 0;
/* 传入cycle的不同值,调节PWM的占用比,也就是调节灯的亮度 */
pwm_set_frequency(PWM_DEVICE_1, PWM_CHANNEL_0, 200000, duty_cycle);
/* 修改cycle的值,让其在区间(0,1)内渐增和渐减 */
flag ? (duty_cycle -= 0.01): (duty_cycle += 0.01);
if(duty_cycle > 1.0)
{
duty_cycle = 1.0;
flag = 1;
}
else if (duty_cycle < 0.0)
{
duty_cycle = 0.0;
flag = 0;
}
return 0;
}
/**
* Function init_timer
* @brief 初始化定时器
* @param[in] ctx
* @param[out] void
* @retval 0
* @par History 无
*/
void init_timer(void) {
/* 定时器初始化 */
timer_init(TIMER_DEVICE_0);
/* 设置定时器超时时间,单位为ns */
timer_set_interval(TIMER_DEVICE_0, TIMER_CHANNEL_0, 10 * 1e6);
/* 设置定时器中断回调 */
timer_irq_register(TIMER_DEVICE_0, TIMER_CHANNEL_0, 0, 1, timer_timeout_cb, NULL);
/* 使能定时器 */
timer_set_enable(TIMER_DEVICE_0, TIMER_CHANNEL_0, 1);
}
/**
* Function init_pwm
* @brief 初始化PWM
* @param[in] void
* @param[out] void
* @retval void
* @par History 无
*/
void init_pwm(void)
{
/* 初始化PWM */
pwm_init(PWM_DEVICE_1);
/* 设置PWM频率为200KHZ,占空比为0.5的方波 */
pwm_set_frequency(PWM_DEVICE_1, PWM_CHANNEL_0, 200000, 0.5);
/* 使能 PWM 输出 */
pwm_set_enable(PWM_DEVICE_1, PWM_CHANNEL_0, 1);
}
/**
* Function main
* @brief 主函数,程序的入口
* @param[in] void
* @param[out] void
* @retval 0
* @par History 无
*/
int main(void)
{
/* 硬件引脚初始化 */
hardware_init();
/* 系统中断初始化和使能 */
plic_init();
sysctl_enable_irq();
/* 初始化定时器 */
init_timer();
/* 初始化PWM */
init_pwm();
while(1);
return 0;
}
代码写好后,我们开始编译,注意:如果你编译过程中出现错误,可以先make clean掉之前生成的过程文件,重新生成
cd build
//注意这里的目标文件目录改成gpio,和刚才新建的文件夹名称一致
cmake .. -DPROJ=timer -G "MinGW Makefiles"
make
编译完成后,在build文件夹下会生成pwm.bin文件。
使用type-C数据线连接电脑与K210开发板,打开kflash,选择对应的设备,再将程序固件烧录到K210开发板上。
观察现象,可以看到红色灯渐渐点亮,然后渐渐熄灭
本节介绍基于PWM的内部实现是基于定时器的定时功能,控制PWM的两个重要因素是频率和占空比,PWM输出修改的是占空比,也就是通电时间占总时间的百分比,改变了输出的有效值,从而改变了RGB灯的亮度。