ESP32-S3的HW_PWM详解
引言
硬件脉冲宽度调制(HW_PWM)是ESP32-S3的一个重要特性,它可以用于控制LED的亮度、电机的速度等。硬件脉冲宽度调制与软件改变 PWM 占空比实验的驱动一致
软件改变 PWM 占空比
硬件脉冲宽度调制和软件脉冲宽度调制有什么区别
硬件脉冲宽度调制(HW_PWM)和软件脉冲宽度调制(SW_PWM)都是实现脉冲宽度调制的方法,但它们在实现方式和应用场景上有所不同:
-
硬件脉冲宽度调制(HW_PWM):硬件PWM是通过微控制器的硬件定时器/计数器来生成PWM信号。硬件PWM的优点是精度高,可以实现高速、高精度的脉冲宽度调制,同时可以实现多路同步脉宽调制。
-
软件脉冲宽度调制(SW_PWM):软件PWM是通过编程控制微控制器的通用输入/输出(GPIO)引脚来生成PWM信号。软件PWM的优点是成本低,可以根据需要随时调整频率和占空比,实现起来比较简单。
使用硬件改变 PWM 占空比
LEDPWM 控 制 器 硬 件 可 逐 渐 改 变 占 空 比 的 数 值 。 要 使 用 此 功 能 , 需 用 函 数
ledc_fade_func_install()
使能渐变,之后用下列可用渐变函数之一配置:
ledc_set_fade_with_time()
ledc_set_fade_with_step()
ledc_set_fade()
最后需要调用 ledc_fade_start()
开启渐变。渐变可以在阻塞或非阻塞模式下运行,具体区别请查看 ledc_fade_mode_t
。需要特别注意的是,不管在哪种模式下,下一次渐变或是单次占空比配置的指令生效都必须等到前一次渐变完成或被中止。中止一个正在运行中的渐变需要调用函数 ledc_fade_stop()
。如不需要渐变和渐变中断,可用函数 ledc_fade_func_uninstall()
关闭。
使用硬件改变 PWM达到LDE呼吸灯效果
pwm.h
// 文件: pwm.h
// 作者: 宁子希 (1589326497@qq.com)
// 简介: PWM驱动代码
// 版本: 0.1
// 日期: 2024-04-24
// 版权所有 (c) 2024#ifndef __PWM_H_
#define __PWM_H_
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h" // 这个头文件包含了FreeRTOS中信号量的相关函数和宏定义
#include "driver/ledc.h"
#include "driver/gpio.h"// 引脚以及重要参数定义
#define LEDC_PWM_TIMER LEDC_TIMER_0 // 使用定时器0
#define LEDC_PWM_MODE LEDC_LOW_SPEED_MODE // 模式设定必须使用LEDC低速模式
#define LEDC_PWM_CH0_GPIO GPIO_NUM_10 // LED控制器通道对应GPIO
#define LEDC_PWM_CH0_CHANNEL LEDC_CHANNEL_0 // LED控制器通道号
#define LEDC_PWM_DUTY 8000 // 渐变的变大最终目标占空比
#define LEDC_PWM_FADE_TIME 3000 // 变化时长// 函数声明
void pwm_init(uint8_t resolution, uint16_t freq); // 初始化PWM
void pwm_set_duty(uint16_t duty); // PWM占空比设置#endif
pwm.c
/*** @file pwm.c* @author 宁子希 (1589326497@qq.com)* @brief PWM驱动代码* @version 0.1* @date 2024-04-24* * @copyright Copyright (c) 2024* */
#include "pwm.h"
/*** @brief 初始化PWM* @param resolution:PWM占空比分辨率* freq: PWM信号频率* @retval 无*/
void pwm_init(uint8_t resolution, uint16_t freq){ledc_timer_config_t ledc_timer; // LEDC定时器句柄ledc_channel_config_t ledc_channel; // LEDC通道配置句柄// 配置LEDC定时器ledc_timer.duty_resolution = resolution; // PWM占空比分辨率ledc_timer.freq_hz = freq; // PWM信号频率ledc_timer.speed_mode = LEDC_PWM_MODE; // 定时器模式ledc_timer.timer_num = LEDC_PWM_TIMER; // 定时器序号ledc_timer.clk_cfg = LEDC_AUTO_CLK; // LEDC时钟源ledc_timer_config(&ledc_timer); // 配置定时器// 配置LEDC通道ledc_channel.gpio_num = LEDC_PWM_CH0_GPIO; // LED控制器通道对应引脚ledc_channel.speed_mode = LEDC_PWM_MODE; // LEDC高速模式ledc_channel.channel = LEDC_PWM_CH0_CHANNEL; // LEDC控制器通道号ledc_channel.intr_type = LEDC_INTR_DISABLE; // LEDC失能中断ledc_channel.timer_sel = LEDC_PWM_TIMER; // 定时器序号ledc_channel.duty = 0; // 占空比值ledc_channel_config(&ledc_channel); // 配置LEDC通道ledc_fade_func_install(0); // 使能渐变(该函数不可或缺)}/*** @brief PWM占空比设置* @param duty:PWM占空比* @retval 无*/
void pwm_set_duty(uint16_t duty){ledc_set_fade_with_time(LEDC_PWM_MODE, LEDC_PWM_CH0_CHANNEL, duty, LEDC_PWM_FADE_TIME); // 设置占空比以及渐变时长ledc_fade_start(LEDC_PWM_MODE, LEDC_PWM_CH0_CHANNEL, LEDC_FADE_NO_WAIT); // 开始渐变ledc_set_fade_with_time(LEDC_PWM_MODE, LEDC_PWM_CH0_CHANNEL, 0, LEDC_PWM_FADE_TIME); // 设置占空比以及渐变时长ledc_fade_start(LEDC_PWM_MODE, LEDC_PWM_CH0_CHANNEL, LEDC_FADE_NO_WAIT); // 开始渐变
}
main.c
/*** @file main.c* @author 宁子希 (1589326497@qq.com)* @brief PWM驱动代码* @version 0.1* @date 2024-04-24* * @copyright Copyright (c) 2024* */#include "nvs_flash.h"
#include "pwm.h"void app_main(void){//初始化NVSesp_err_t ret;ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND){ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}pwm_init(13, 5000); //初始化PWMfor(;;) {vTaskDelay(10/portTICK_PERIOD_MS);pwm_set_duty(LEDC_PWM_DUTY); //设置占空比} }
参考资料
LED PWM 控制器