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);
}
}
運行結果: