本帖最后由 lazyduck 于 2019-12-2 13:37 编辑
这一节主要就是一个内容: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依次从暗到亮,熄灭,下一个~~~ 另外,官方的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的硬件参数,也就是前面定义的那个数组。
|