庆科MOC108性价比不太好, 想用8266替代,但用户又需要PWM,这里分享一下ESP8266 PWM 接口参考

庆科的wifi模块,好处是他们有自己的操作系统MICO也可以用keil开发,使用起来也很好上手,但是价格相差太大很多公司考虑成本问题无疑都会选ESP8266。但用户又需要PWM,这里分享一下ESP8266 PWM...

庆科的wifi模块,好处是他们有自己的操作系统MICO也可以用keil开发,使用起来也很好上手,但是价格相差太大很多公司考虑成本问题无疑都会选ESP8266。但用户又需要PWM,这里分享一下ESP8266 PWM 接口参考:

PWM 的特性如下所示。 

  • 使用 NMI (Non Maskable Interrupt) 中断,更加精确
  • 可扩展最多8路PWM信号
  • >14bit分辨率,最小分辨率45ns
  • 无需配置寄存器,调用函数接口即可完成配置。

ESP8266 系统提供了一种经过优化的软件算法,通过在FRC1定时器上挂载NMI,实现在 GPIO 端口输出多组 PWM 信号。PWM 的时钟源由高速系统时钟提供,其频率高达 80MHz。PWM 通过预分屏16分频,其输入时钟频率为 5MHz。PWM 通过 FRC1 来产生粗调定时,结合高速系统时钟的微调,可将分辨率提高到 45ns。

说明: NMI 拥有最高中断优先级,可以保证 PWM 输出波形的准确度。

配置说明

  • 在定时中断内,为尽快退出程序只在每次PWM周期开始时载入下一个周期的定时参数
  • 设置完各个通道的占空比后,系统会调用 pwm_start() 函数来计算定时周期。在此之前系统会进行保护操作,即保存当前的各通道参数,并清除计算完成标志, PWM 周期到来会使用保存后的参数。
  • PWM 周期中断后会使用新的参数,因此计算完成后需要设置标志为。这样在实现占空比渐进(如控制RGB 彩灯)的过程中,能保证颜色平滑过渡。
  • 可在 user_light.h 中配置采用的 GPIO。SDK代码示例使用 5 路 PWM,实际可以自行扩展,最多扩展至 8  路 PWM。最小分辨率 45ns, 频率在 1KHz 时,占空比最小可以达到 1/22222。

 参数说明

  • 最小分辨率:45ns (近似对应于硬件 PWM 的输入时钟频率为 22.72MHz): >14bit PWM @ 1 KHz
  • PWM 周期:1000us (1KHz) ~ 10000us (100Hz)

PWM.h 详解

代码示例

  1. #ifndef __PWM_H__
  2. #define __PWM_H__
  3. #define PWM_CHANNEL_NUM_MAX 8 // 最多 8 路 PWM
  4. struct pwm_single_param // 定义单个 PWM 通道参数结构体
  5. {
  6. uint16 gpio_set; // 需要置位的 GPIO
  7. uint16 gpio_clear; // 需要清零的 GPIO
  8. uint32 h_time; // 需要写入 FRC1_LOAD 寄存器的计数值
  9. };
  10. struct pwm_param // 定义 PWM 参数结构体
  11. {
  12. uint32 period; // PWM 周期
  13. uint32 freq; // PWM 频率
  14. uint32 duty[PWM_CHANNEL_NUM_MAX]; // PWM 占空比
  15. };
  16. void pwm_init(uint32 period, uint32 *duty, uint32 pwm_channel_num, uint32(*pin_info_list)[3]);
  17. void pwm_start(void);
  18. void pwm_set_duty(uint32 duty, uint8 channel);
  19. uint32 pwm_get_duty(uint8 channel);
  20. void pwm_set_freq(uint32 period);
  21. uint32 pwm_get_freq(void);

 接口说明

  1. 名称:pwm_init
  2. 含义:PWM 初始化
  3. 示例:pwm_init(uint32 freq, uint32 *duty, uint32 pwm_channel_num, uint32 (*pin_info_list)[3]);
  4. 描述:PWM GPIO, 参数和定时器初始化
  5. 参数:
  6. uint32 freq: PWM 的周期
  7. uint32 *duty: 各通道占空比参数
  8. uint32 pwm_channel_num: PWM 通道数。
  9. uint32 (*pin_info_list)[3]: PWM 各通道的 GPIO 硬件参数,该参数是一个 n*3 的数组指针。数组中定义了 GPIO 的寄存器,对应 PIN 脚的 IO 复用值,和 GPIO 对应的序号。
  10. 例如:初始化一个 3 通道的 PWM。
  11. uint32 io_info[][3] =
  12. {{PWM_0_OUT_IO_MUX, PWM_0_OUT_IO_FUNC, PWM_0_OUT_IO_NUM},
  13. {PWM_1_OUT_IO_MUX, PWM_1_OUT_IO_FUNC, PWM_1_OUT_IO_NUM},
  14. {PWM_2_OUT_IO_MUX, PWM_2_OUT_IO_FUNC, PWM_2_OUT_IO_NUM}};
  15. pwm_init(light_param.pwm_period, light_param.pwm_duty, 2, io_info);
  16. 调用:系统初始化时调用。目前只能调用一次。
  17. 返回值:无
  1. 名称:pwm_set_period
  2. 含义:设置 PWM 周期
  3. 示例:pwm_set_period(uint32 period)
  4. 描述:设置 PWM 周期,单位 us。
  5. 例如:1KHz PWM, 参数为 1000us.
  6. 参数:uint32 period:PWM 周期
  7. 调用:设置完成后需要嗲用 pwm_start() 才起作用。
  8. 返回值:无
  1. 名称:pwm_set_duty
  2. 含义:设置 PWM 某个通道信号的占空比
  3. 代码示例:pwm_set_duty(uint32 duty, uint8 channel);
  4. 描述:设置 PWM 占空比。设置各路 PWM 信号高电平所占的时间,duty 的范围随 PWM 周期改变。最大值为:period * 1000 / 45 (以1KHz为例:duty 范围是 0 ~ 22222)。
  5. 参数说明:uint32 duty:设置高电平参数,占空比的值为(duty * 45) / (period * 1000).
  6. uint8 channel:当前要设置的 PWM 通道,在 PWM_CHANNEL 定义的范围内。
  7. 调用:设置完成后需要调用 pwm_start() 才起作用。
  8. 返回值:无
  1. 名称:pwm_get_period
  2. 描述:获取当前 PWM 周期
  3. 代码示例:pwm_get_period(void)
  4. 参数说明:无
  5. 返回值:PWM 周期,单位us.
  1. 名称:pwm_get_duty
  2. 描述:获取对应 channel 的当前 PWM 信号的 duty 参数。
  3. 代码示例:pwm_get_duty(uint8 channel)
  4. 参数说明:uint8 channel:当前要获取的 PWM 的通道,在 PWM_CHANNEL 定义的范围内
  5. 调用:设置完成后需要调用pwm_start()才起作用。
  6. 返回值:channel对应的通道的占空比,占空比的值为 (duty * 45) / (period * 1000)。
  1. 名称:pwm_start
  2. 描述:PWM 更新参数
  3. 代码示例:pwm_start(void);
  4. 参数说明:无
  5. 调用:PWM 相关参数设置完成后,需要调用 pwm_start() 才起作用
  6. 返回值:无

自定义通道

用户还可以增加 PWM 通道,如增加 GPIO4 为 PWM 输出的第四通道,设置步骤如下所示。

  1. 1. 修改初始化参数。
  2. uint32 io_info[][3] =
  3. {
  4. {PWM_0_OUT_IO_MUX, PWM_0_OUT_IO_FUNC, PWM_0_OUT_IO_NUM},
  5. {PWM_1_OUT_IO_MUX, PWM_1_OUT_IO_FUNC, PWM_1_OUT_IO_NUM},
  6. {PWM_2_OUT_IO_MUX, PWM_2_OUT_IO_FUNC, PWM_2_OUT_IO_NUM},
  7. {PWM_3_OUT_IO_MUX, PWM_3_OUT_IO_FUNC, PWM_3_OUT_IO_NUM},
  8. {PWM_4_OUT_IO_MUX, PWM_4_OUT_IO_FUNC, PWM_4_OUT_IO_NUM},
  9. };
  10. pwm_init(light_param.pwm_period, light_param.pwm_duty, PWM_CHANNEL, io_info);
  1. 2. 修改 user_light.h 文件
  2. #define PWM_0_OUT_IO_MUX PERIPHS_IO_MUX_MTDI_U
  3. #define PWM_0_OUT_IO_NUM 12
  4. #define PWM_0_OUT_IO_FUNC FUNC_GPIO12
  5. #define PWM_1_OUT_IO_MUX PERIPHS_IO_MUX_MTDO_U
  6. #define PWM_1_OUT_IO_NUM 15
  7. #define PWM_1_OUT_IO_FUNC FUNC_GPIO15
  8. #define PWM_2_OUT_IO_MUX PERIPHS_IO_MUX_MTCK_U
  9. #define PWM_2_OUT_IO_NUM 13
  10. #define PWM_2_OUT_IO_FUNC FUNC_GPIO13
  11. #define PWM_3_OUT_IO_MUX PERIPHS_IO_MUX_GPIO4_U
  12. #define PWM_3_OUT_IO_NUM 4
  13. #define PWM_3_OUT_IO_FUNC FUNC_GPIO4
  14. #define PWM_4_OUT_IO_MUX PERIPHS_IO_MUX_GPIO5_U
  15. #define PWM_4_OUT_IO_NUM 5
  16. #define PWM_4_OUT_IO_FUNC FUNC_GPIO5
  17. #define PWM_CHANNEL 5

 


  • 发表于 2020-09-11 14:51
  • 阅读 ( 129 )
  • 分类:默认分类

0 条评论

请先 登录 后评论
杨杨
杨杨

2 篇文章

作家榜 »

  1. 淡若清风 35 文章
  2. 杨杨 2 文章
  3. seaky 0 文章
  4. 15139236712 0 文章
  5. selectcc 0 文章
  6. 温志亮 0 文章
  7. jamesfan007 0 文章
  8. Gavin 0 文章