ESP8266_07基于PWM的呼吸灯

这一节主要就是一个内容:PWM的用法。

先看手册上对PWM功能的介绍(以下内容转自乐鑫手册):

ESP8266系统的PWM( Pulse Width Modulation)由FRC1在软件上实现,可实现同频

率、不同占空比的多路PWM,可用来控制彩灯、蜂鸣器和电机等设备。

说明:FRC1是一个23bts的硬件定时器。

PWM的特性如下所示。

使用NM( Non Maskable Interrupt)中断,更加精确。

可扩展最多8路PVM信号

>14bit分辨率,最小分辨率45ns。

无需配置寄存器,调用函数接口即可完成配置。

注意:PWM驱动接口不能跟硬件定时器(hw_timer)接口函数同时使用,因为二者共用一个硬件定时器。

参数说明

最小分辨率:45ns(近似对应于硬件 PWM 的输入时钟频率为22.72 MHZ ) :>14 bit PWM @1 KHZ 

PWM 周期:1000 us (1 KHz )~10000 us (100 Hz)

先说频率范围,100HZ~1KHZ,这个频率实在是有些低。不过据说有些人能用到二三十K,不知道真的假的。由于本人比较懒,没有测,所以上面的说法仅供参考。

然后是用法,依然使用万能的三色LED做演示,做一个呼吸灯。

最终实现的效果,上电后,三个LED依次从暗到亮,熄灭,下一个~~~

另外,官方的SDK里面,提供了一个IoT_Demo的例程,里面有用PWM实现呼吸灯的代码。所以这里参考例程,进行一定的修改。

使用之前包含下面的头文件,同时把user_light.c文件拷到user目录下:

#include "user_light.h"
#include "pwm.h"

先说PWM的用法,很简单,只有三步。但因为我用了user_light.c里面的结构体,所以多加一步,先定义一个结构体。

1、定义一个结构体,存放PWM相关参数。

struct light_saved_param light_param;

结构体类型定义如下:

struct light_saved_param {

uint32 pwm_period;

uint32 pwm_duty[PWM_CHANNEL];

};

PWM_CHANNEL是一个宏定义,定义PWM通道个数,这里是3.结构体里面可以设置PWM的周期,以及每个通道的占空比。

2、定义一个二维数组

uint32 io_info[][3] = { {PWM_0_OUT_IO_MUX,PWM_0_OUT_IO_FUNC,PWM_0_OUT_IO_NUM},

{PWM_1_OUT_IO_MUX,PWM_1_OUT_IO_FUNC,PWM_1_OUT_IO_NUM},

{PWM_2_OUT_IO_MUX,PWM_2_OUT_IO_FUNC,PWM_2_OUT_IO_NUM},

};

这一步的意义在于,你要让哪几个IO输出PWM。数组的格式要记住,但凡用到PWM,都要以这样的格式进行定义。举例来说,第一行:

PWM_0_OUT_IO_MUX,PWM_0_OUT_IO_FUNC,PWM_0_OUT_IO_NUM

分别是:管脚名、管脚功能、管脚编号。直接看肯定看不懂,因为都是宏定义,如下:

#define PWM_0_OUT_IO_MUX PERIPHS_IO_MUX_MTDI_U
#define PWM_0_OUT_IO_NUM 12
#define PWM_0_OUT_IO_FUNC FUNC_GPIO12

有人会觉得烦,说你搞这么多宏定义累不累?

但其实不是我搞的,IoT_Demo的例程里已经写好了,直接用就可以。而且,这个格式相对比较规范,所以还是建议使用。

3、PWM初始化

pwm_init(light_param.pwm_period, light_param.pwm_duty ,PWM_CHANNEL,io_info);

共有四个参数:

第一个参数:PWM的周期,这里写的是1000,单位是us。所有通道的周期都是一样的。

第二个参数:PWM的占空比,上面周期是1000,那占空比的最大值是多少?

如果答1000,那你就太年轻了!它这里有个计算公式,也需要记住(别记了,还是查手册吧)

duty = period*1000/45

period是1000,带入计算的到22222.所以占空比的取值范围是0~22222.

第三个参数:通道个数,也就是说,你要输出几路PWM?

第四个参数:PWM各个通道的GPIO的硬件参数,也就是前面定义的那个数组。

4、启动PWM

pwm_start();

看函数名就能看懂了,不解释。

注意事项:手册里对该函数的描述是参数更新,所以但凡涉及到更新的(周期、占空比),改完之后,一定要调用一下这个函数。

经过前面四步,PWM就开始输出了。但是,咱们要做的是呼吸灯,呼吸灯是要定时修改PWM的占空比的,怎么改?再来一次pwm_init?

NO!

pwm_init只能初始化的时候调用一次,严禁多次调用。修改占空比使用下面的函数:

pwm_set_duty(duty, channel);

函数名如此简单,我已经懒得解释了。第一个参数略过,直接看第二个,channel,要写多少?

首先,这里定义了三个通道,定义的时候在数组里按照从0开始的规则,对三个通道自动进行了编号,分别是:0,1,2.

所以,你想改哪个通道,写入哪个编号即可。

注:参考手册2c-esp8266_non_os_sdk_api_reference_cn的157页,和esp8266-technical_reference_cn的100页。

保存、清理、编译、下载一条龙,然后重新上电,你会发现呼吸灯开始变化。

微信截图_20190806195316

到此,PWM的用法说完了。

完整工程源码,请关注公众号:单片机爱好者,回复关键字:ESP8266,即可获取。

留下评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据