PWM概述
我们即将创建一个会变换颜色的呼吸灯的程序,在编写程序之前我觉得有必要先稍微讲解一下什么是pwm。
pwm的全称是Pulse Width Modulation,翻译过来就是脉冲宽度调制。
以上就是pwm的原理示意图。在T1这个时间段中属于高电平输出,在T2这个时间段中属于底电平输出。高电平在整个周期(T1+T2)中所占时间的比例就是占空比,通过对占空比的控制我们可以输出一段幅值相等的脉冲。
PWM控制亮度的原理
我们平时调节手机屏幕和灯的亮暗就是靠pwm来进行控制的,通过对占空比的控制我们可以让led灯进行快速的闪烁,这个闪烁因为过快导致我们的肉眼根本无法识别出来,在不停的闪烁中如果灭的持续时间长那么我们就会觉得屏幕变暗了,如果亮的时间长我们就会觉得屏幕变亮了。
编程思路
首先贴上本次要使用的函数:
rt_device_find() rt_pwm_set() rt_pwm_enable() rt_pwm_disable()
函数 | 描述 |
---|---|
rt_device_find() | 根据 PWM 设备名称查找设备获取设备句柄 |
rt_pwm_set() | 设置 PWM 周期和脉冲宽度 |
rt_pwm_enable() | 使能 PWM 设备 |
rt_pwm_disable() | 关闭 PWM 设备 |
通过不停对占空比进行有序的改变可以让灯的亮度由暗变亮再让灯由亮变暗,有两种方法可以完成这种操作,一个是使用for或者while循环,一个就是使用数组,在接下来的实例中我们是使用数组进行有序控制的。
代码
首先在这儿声明一下,这里使用的开发板以低电平输出亮,高电平输出暗,开发板中关于led的原理图如下:
#include <rtthread.h> #include <rtdevice.h> #include <board.h> #define pwm "pwm3" int jun[300];//声明数组 int a=0; /* 将占空比的值赋给数组 */ void pwm_sat8(){ for(int i=100000;i>=0;i=i-1000){ jun[a]=i; a++; } for(int i=0;i<=100000;i=i+1000){ jun[a]=i; a++; } a=0; struct rt_device_pwm *pwm_dev;//设备句柄 pwm_dev = (struct rt_device_pwm *)rt_device_find(pwm);//查找设备 /* 完成红、绿、蓝亮度的依次变化 */ while(1){ for(a=0;a<=201;a++){ rt_pwm_set(pwm_dev,2,100000,jun[a]); rt_pwm_enable(pwm_dev,2); rt_thread_mdelay(20); } for(a=0;a<=201;a++){ rt_pwm_set(pwm_dev,3,100000,jun[a]); rt_pwm_enable(pwm_dev,3); rt_thread_mdelay(20); } for(a=0;a<=201;a++){ rt_pwm_set(pwm_dev,4,100000,jun[a]); rt_pwm_enable(pwm_dev,4); rt_thread_mdelay(20); } } } MSH_CMD_EXPORT(pwm_sat8, pwm sample)
首先,我们定义了一个名字为jun,大小为300的数组。
我们在这里设置的周期是100000纳秒(也就是0.1ms),因为亮度的大小范围是0%——100%,所以我们将占空比从100000,每次以减1000的方式赋值给数组,再从0,以每次加1000的方式赋值给数组,这样子我们就得到了{100000,99000,98000…98000,99000,100000}的数组。
接着使用rt_device_find()获取设备句柄,在获取设备句柄之前我们可以看到有这么一行代码:
struct rt_device_pwm *pwm_dev;
这行代码我们先创建了一个结构体,并给这个结构体设置了一个指针。
因为rt_device_find()返回的是一个句柄所以我们要先强制类型转换,然后才能把返回的句柄赋给指针。
while(1){ for(a=0;a<=201;a++){ rt_pwm_set(pwm_dev,2,100000,jun[a]); rt_pwm_enable(pwm_dev,2); rt_thread_mdelay(20); } for(a=0;a<=201;a++){ rt_pwm_set(pwm_dev,3,100000,jun[a]); rt_pwm_enable(pwm_dev,3); rt_thread_mdelay(20); } for(a=0;a<=201;a++){ rt_pwm_set(pwm_dev,4,100000,jun[a]); rt_pwm_enable(pwm_dev,4); rt_thread_mdelay(20); } }
以上代码就是实现交替变换颜色并且安照顺序调节亮度的代码。我们抽取第一段分析一下:
for(a=0;a<=201;a++){ rt_pwm_set(pwm_dev,2,100000,jun[a]); rt_pwm_enable(pwm_dev,2); rt_thread_mdelay(20); }
通过rt_pwm_set()可以设置我们需要使用的pwm设备和需要使用的通道(不理解什么是通道?看看我刚发的led原理图),然后设置周期为100000,最后设置占空比,在上文中我们已经讲过我们是使用数组进行占空比设置的,所以设置为jun[a],通过for循环中的判断和更新变量来完成占空比从100000到0再从0到100000的变化。
在设置pwm设备后我们要使能pwm设备,最后加上延时函数rt_thread_mdelay(),这里我们设置延时为0.02毫秒。
*注意
因为本次使用的开发板是以低电平为输出led亮的,所以当你使用env工具配置好pwm设备后它会默认亮起来,为了解决这个问题我们可以在mian()函数中编写如下代码:
int main(){ struct rt_device_pwm *pwm_dev; pwm_dev = (struct rt_device_pwm *)rt_device_find("pwm3"); rt_pwm_set(pwm_dev,2,100000,100000); rt_pwm_enable(pwm_dev,2); rt_pwm_set(pwm_dev,3,100000,100000); rt_pwm_enable(pwm_dev,3); rt_pwm_set(pwm_dev,4,100000,100000); rt_pwm_enable(pwm_dev,4); }
这样子我们就能在开始的时候把它给关闭了。
学习辛苦了,看点色图放松一下吧(/龇牙)