PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如方波的占空比就是50%.
PWM用途很广,像一些步进电机、舵机等等都需要用到。
PWM头文件
#include "driver/pwm.h"
提供的接口有:
esp_err_t pwm_init(uint32_t period, uint32_t *duties, uint8_t channel_num, const uint32_t *pin_num);//PWM功能初始化,包括GPIO、频率和占空比。
esp_err_t pwm_deinit(void); //失能PWM功能。
esp_err_t pwm_set_duty(uint8_t channel_num, uint32_t duty); //设定PWM通道的占空比,channel_num不可超过pwm_init中设定的channel_num。
esp_err_t pwm_get_duty(uint8_t channel_num, uint32_t *duty_p); //获取一个PWM通道的占空比。
esp_err_t pwm_set_period(uint32_t period); //设定PWM周期,单位:us。
esp_err_t pwm_get_period(uint32_t *period_p); //获取PWM周期,单位:us。
esp_err_t pwm_start(void); //开始PWM输出
esp_err_t pwm_stop(uint32_t stop_level_mask); //停止PWM输出,参数是停止输出后通道电平。
esp_err_t pwm_set_duties(uint32_t *duties); //设置所有通道的占空比,设置好后需要调用pwm_start才可生效。
esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase); //设置PWM通道的相位,设置好后需要调用pwm_start才可生效。
esp_err_t pwm_set_phases(int16_t *phases); //设置所有通道的相位,设置好后需要调用pwm_start才可生效。
esp_err_t pwm_get_phase(uint8_t channel_num, uint16_t *phase_p);//获得一个PWM通道的相位。
esp_err_t pwm_set_period_duties(uint32_t period, uint32_t *duties);//设置每个PWM通道的PWM周期和占空比,设置好需要调用pwm_start才可生效。
esp_err_t pwm_set_channel_invert(uint16_t channel_mask); //设置逆变输出PWM通道。
esp_err_t pwm_clear_channel_invert(uint16_t channel_mask); //清除逆变输出PWM通道,此函数仅适用于已经处于反向输出状态的PWM通道。
重点函数解析
**esp_err_t pwm_init(uint32_t period, uint32_t duties, uint8_t channel_num, const uint32_t pin_num); //PWM初始化
参数 | 解析 |
---|---|
period | PWM周期,单位:us |
duties | 占空比 |
channel_num | 通道数 |
pin_num | GPIO管脚号 |
esp_err_t pwm_set_duty(uint8_t channel_num, uint32_t duty); //设置PWM占空比
参数 | 解析 |
---|---|
channel_num | 通道数,该通道数不可超过pwm_init()初始化中给定的通道数 |
duty | 占空比,此处的单位也是us,具体占百分几需要计算,不可超出初始化设定的周期 |
esp_err_t pwm_start(void); //PWM开始输出
所有针对PWM配置的修改,为了能够生效都得重新开启;
esp_err_t pwm_set_phases(int16_t phase); //设置所有通道的相位
参数 | 解析 |
---|---|
phase | 需要设置的相位 |
用例:初始占空比为90%,有效电平为高;20s后停止PWM输出,同时拉高PWM通道;10s后将占空比修改为50%
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_err.h"
#include "esp8266/gpio_register.h"
#include "esp8266/pin_mux_register.h"
#include "driver/pwm.h"
#define PWM_PERIOD 1000
static const char *TAG = "pwm example";
const uint32_t PWM_OUT_IO_NUM = 5;
uint32_t duties = 900;
int16_t phase = 0;
void app_main()
{
pwm_init(PWM_PERIOD, &duties, 1, &PWM_OUT_IO_NUM); //PWM的初始化,周期1ms->1KHz,各通道工作周期500us,1条通道,GPIO5
pwm_set_phases(&phase); //初始相位0
pwm_start(); //开始PWM输出
int16_t count = 0;
while (1) {
if (count == 20) {
pwm_stop(0x1); //此处停止PWM并将引脚变成高电平
ESP_LOGI(TAG, "PWM stop\n");
} else if (count == 30) {
pwm_set_duty(0, 500); //将占空比改成50%
pwm_start(); //使修改占空比生效,需要再次开启
ESP_LOGI(TAG, "PWM re-start\n");
count = 0;
}
count++;
vTaskDelay(1000 / portTICK_RATE_MS);
}
}
运行结果: