第十二章 PWM输出实验
本章将介绍Kendryte K210的PWM外设使用。通过本章的学习,读者将学习到SDK编程技术控制Kendryte K210的输出PWM波。 本章分为如下几个小节: 12.1 PWM介绍 12.2 硬件设计 12.3 程序设计 12.4 运行验证
12.1 PWM介绍 PWM用于控制脉冲输出的占空比。Kendryte K210的PWM定时器模块可配置以下功能: 1. 通过指定PWM定时器频率或周期来控制事件发生的频率 2. 配置特定PWM定时器与其他PWM定时器或模块同步 3. 使PWM定时器与其他PWM定时器或模块同相 4. 设置定时器计数模式:递增,递减,或递增递减循环计数模式 5. 使用预分频器更改PWM定时器时钟(PT_clk)的速率。每个定时器都有自己的预分频器,通过寄存器PWM_TIMER0_CFG0_REG的PWM_TIMERx_PRESCALE配置。PWM定时器根据该寄存器的设置以较慢的速度递增或递减 PWM本质是一个定时器,Kendryte K210芯片的硬件定时器共有三个,每个硬件定时器均可设置PWM输出功能,且每个硬件定时器有四路通道,所以Kendryte K210芯片可以同时产生12路的PWM。需要注意的是,定时器如果设置了PWM输出功能,就不可以使用定时的功能,所以注意设置 PWM 号与通道时不要与TIMER定时器冲突。 Kendryte K210官方SDK提供了3个操作PWM的函数,这些函数介绍如下: 1, pwm_init函数 该函数主要用于定时器时钟使能,如下代码所示: void pwm_init(pwm_device_number_t pwm_number) { sysctl_clock_enable(SYSCTL_CLOCK_TIMER0 + pwm_number); } /* pwm_init定时器选项pwm_number的配置参数 */ typedef enum _pwm_device_number { PWM_DEVICE_0, PWM_DEVICE_1, PWM_DEVICE_2, PWM_DEVICE_MAX, } pwm_device_number_t; 2,gpio_set_drive_mode函数 该函数用于使能定时器,控制定时器的启动和关闭,如下代码所示: void pwm_set_enable(pwm_device_number_t pwm_number, pwm_channel_number_t channel, int enable); /* pwm_set_enable通道选项 channel的配置参数 */ typedef enum _pwm_channel_number { PWM_CHANNEL_0, PWM_CHANNEL_1, PWM_CHANNEL_2, PWM_CHANNEL_3, PWM_CHANNEL_MAX, } pwm_channel_number_t; 第一个参数选择定时器,有三个定时器可以选择,第二个参数用于选择开启的通道,该参数下共有4个成员变量可选择,所以一共可开启12路PWM,第三个参数是设置是否开启定时器,0:禁用,1:使能,该函数无返回值。 3,pwm_set_frequency函数 该函数用来设置PWM的输出频率和占空比,该函数原型及参数描述如下所示: double pwm_set_frequency(pwm_device_number_t pwm_number, pwm_channel_number_t channel, double frequency, double duty); 下面我们讲解下这个函数的后面两个参数,frequency是配置PWM输出的频率,duty用于配置PWM的占空比。该函数无返回值。
12.2 硬件设计 12.2.1 例程功能 1.使用定时器1通道0,并将定时器1的输出通道1与红色LED灯引脚IO24绑定 2. 按下KEY0按键后减少PWM输出PWM的占空比 3. 按下KEY1按键后增加PWM输出PWM的占空比 12.2.2 硬件资源 1. 双色LED LEDR - IO24 2. 独立按键 KEY0按键 - IO18 KEY1按键 - IO19 12.2.3 原理图 本章实验内容,主要讲解PWM外设的使用,无需关注原理图。 12.3 程序设计 12.3.1 PWM驱动代码 定时器中断驱动源码包括两个文件:pwm.c和pwm.h,我们先介绍pwm.h文件的内容。 /* 硬件IO口,与原理图对应 */ #define PIN_PWM_LED (24) 这里宏定义了红色LED灯的硬件引脚编号,因为和LED的驱动文件使用的外设不同,所以在这里重新定义了一个宏。下面我们看其源代码内容。 void pwm1_init(double fre, double duty) { /* 系统中断初始化 */ plic_init(); sysctl_enable_irq(); /* 初始化PWM */ pwm_init(PWM_DEVICE_1); /* 设置PWM频率为200KHZ,占空比为0.5的方波 */ pwm_set_frequency(PWM_DEVICE_1, PWM_CHANNEL_0, fre, duty); /* 定时器1输出1(通道0)与红色LED灯引脚绑定 */ fpioa_set_function(PIN_PWM_LED, FUNC_TIMER1_TOGGLE1); /* 使能 PWM 输出 */ pwm_set_enable(PWM_DEVICE_1, PWM_CHANNEL_0, 1); } pwm.c文件只有一个PWM初始化函数pwm1_init,该函数有两个参数fre和duty,通过这两个参数可以在初始化的时候设置不同的PWM输出频率和占空比,接着我们看PWM的初始化过程,首先我们要开启系统中断并使能,然后初始化PWM1(对应定时器1),接着设置PWM输出频率和占空比,占空比的范围0%~100%,我们参数duty设置0~1即可,我们要将PWM输出到对应的硬件引脚,所以要将功能编号和引脚号绑定,最后使能PWM输出,红色LED灯引脚就能输出不同占空比的方波了。 12.3.2 main.c代码 main.c中的代码如下所示: int main(void) { uint8_t key; static double duty_cycle = 0.5; key_init(); /* 按键初始化 */ pwm1_init(200000, duty_cycle); /* 初始化PWM */ while(1) { key = key_scan(0); /* 得到键值 */ if (key == KEY0_PRES) { duty_cycle -= 0.1; if (duty_cycle < 0.0) { duty_cycle = 0.0; } /* 传入cycle的不同值,调节PWM的占用比,也就是调节灯的亮度 */ pwm_set_frequency(PWM_DEVICE_1, PWM_CHANNEL_0, 200000, duty_cycle); } else if(key == KEY1_PRES) { duty_cycle += 0.1; if(duty_cycle > 1.0) { duty_cycle = 1.0; } /* 传入cycle的不同值,调节PWM的占用比,也就是调节灯的亮度 */ pwm_set_frequency(PWM_DEVICE_1, PWM_CHANNEL_0, 200000, duty_cycle); } else msleep(10); } } 可以看到,我们创建了一个变量duty_cycle并设置为0.5,然后初始化使用到独立按键,接着进行PWM的初始化,我们初始化PWM的频率设置为200000,占空比设置为0.5,初始化完成后红色LED灯对应的引脚就能输出频率为200000Hz、占空比50%的方波了。 最后就是在一个循环中读取按键的状态,当读取到KEY0按键被按下,则减少PWM输出的占空比,具体应表现为红色LED的亮度增加,当读取到KEY1按键被按下,则增加PWM输出的占空比,具体应表现为红色LED的亮度减小。 12.4 运行验证 将DNK210开发板连接到电脑主机,通过VSCode将固件烧录到开发板中,此时,便可看到红色LED处于半亮状态(理论状态),若按下KEY0按键,则可以看到红色LED的亮度增加,这是因为PWM输出的占空比减小导致的,若按下KEY1按键,则可以看到红色LED的亮度减小,这是因为PWM输出的占空比增加导致的。
|