使用ESP32的MCPWM外设输出两路互补PWM波控制驱动电路

写在前面

本文分享使用MCPWM的基本操作,最后的程序可用于输出双路互补PMW波以控制H桥电路。
本文只讨论了实现该PWM输出的必备模块,若需深入了解MCPWM,建议在学习MCPWM模块时多参考ESP32的技术参考手册和头文件。

MCPWM简单介绍

MCPWM外设提供了6个PWM输出,可用于控制H桥驱动电路等电路结构。使用MCPWM模块可以使ESP32在控制电机输出同时执行其他程序。
每个 MCPWM 外设(单元)都有一个时钟分频器(预分频器),三个 PWM 定时器,三个 PWM 操作器和一个捕获模块。
一些ESP32芯片包含两个MCPWM单元,如ESP32-S3。

MCPWM外设概览

MCPWM编程必备配置

开发平台:VS code PlatformIO扩展
以下配置均为mcpwm.h头文件中的声明,编程时使用#include <driver/mcpwm.h>导入。

MCPWM模块

某些ESP32芯片有多个MCPWM外设,如ESP32-S3,在使用时应当选择要使用的模块。

typedef enum {
    MCPWM_UNIT_0,   /*!<选择MCPWM unit0*/
    MCPWM_UNIT_1,   /*!<选择MCPWM unit1*/
    MCPWM_UNIT_MAX, /*!<MCPWM 单元最大数量*/
} mcpwm_unit_t;
// 可以通过定义变量方式使用
mcpwm_unit_t unit = MCPWM_UNIT_0;

计时器

每一个MCPWM外设均包括三个定时器,用来控制PWM波形的频率。

typedef enum {
    MCPWM_TIMER_0,   /*!<选择MCPWM timer0*/
    MCPWM_TIMER_1,   /*!<选择MCPWM timer1*/
    MCPWM_TIMER_2,   /*!<选择MCPWM timer2*/
    MCPWM_TIMER_MAX, /*!<一个MCPWM单元中定时器最大数量*/
} mcpwm_timer_t;

MCPWM输出信号

包括6路独立输出PWM通道,3路同步信号,3路故障检测信号,3路捕获通道。

typedef enum {
    MCPWM0A = 0,        /*!<PWM0A output pin*/
    MCPWM0B,            /*!<PWM0B output pin*/
    MCPWM1A,            /*!<PWM1A output pin*/
    MCPWM1B,            /*!<PWM1B output pin*/
    MCPWM2A,            /*!<PWM2A output pin*/
    MCPWM2B,            /*!<PWM2B output pin*/
    MCPWM_SYNC_0,       /*!<SYNC0  input pin*/
    MCPWM_SYNC_1,       /*!<SYNC1  input pin*/
    MCPWM_SYNC_2,       /*!<SYNC2  input pin*/
    MCPWM_FAULT_0,      /*!<FAULT0 input pin*/
    MCPWM_FAULT_1,      /*!<FAULT1 input pin*/
    MCPWM_FAULT_2,      /*!<FAULT2 input pin*/
    MCPWM_CAP_0 = 84,   /*!<CAP0   input pin*/
    MCPWM_CAP_1,        /*!<CAP1   input pin*/
    MCPWM_CAP_2,        /*!<CAP2   input pin*/
} mcpwm_io_signals_t;

MCPWM参数配置

对MCPWM其中一个操作器的基本参数进行配置,包括频率、占空比、占空比计算方式和计数方式。

typedef struct {
    uint32_t frequency;              /*!<以Hz为单位设置MCPWM的输出频率*/
    float cmpr_a;                    /*!<设置操作器A(MCPWMXA)的占空比百分数, 要设置A路占空比为62.3%时,令 cmpr_a = 62.3*/
    float cmpr_b;                    /*!<设置操作器B(MCPWMXB)的占空比百分数, 要设置B路占空比为48%时,令cmpr_b = 48.0*/
    mcpwm_duty_type_t duty_mode;     /*!<设置占空比计算方式,常用MCPWM_DUTY_MODE_0,即在异步控制时,占空比与高电平持续时间成正比*/
    mcpwm_counter_type_t counter_mode;  /*!<设置MCPWM计数器工作方式,如*/
} mcpwm_config_t;
//设置范例:
  mcpwm_config_t pwm_config = {
    .frequency = 20000, // 频率为20kHz
    .cmpr_a = 70.0, // A通道占空比
    .cmpr_b = 30.0, // B通道占空比
    .duty_mode = MCPWM_DUTY_MODE_0, // duty cycle proportional to high time
    .counter_mode = MCPWM_FREEZE_COUNTER //不使用计数
  };

引脚绑定

将MCPWM输出信号或其他输入信号与引脚绑定。可以使用下面的函数绑定一个管脚,也可以直接使用结构体一次性全部绑定。

/*
参数:
mcpwm_num:MCPWM单元选择(0-1)
io_signal:MCPWM的输入输出信号
gpio_num:外设引脚
*/
esp_err_t mcpwm_gpio_init(mcpwm_unit_t mcpwm_num, mcpwm_io_signals_t io_signal, int gpio_num);
// 将MCPWM单元0中操作器0的A通道与10号引脚绑定
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, 10)

// 配置引脚的结构体
typedef struct {
    int mcpwm0a_out_num;       /*!<MCPWM0A out pin*/
    int mcpwm0b_out_num;       /*!<MCPWM0A out pin*/
    int mcpwm1a_out_num;       /*!<MCPWM0A out pin*/
    int mcpwm1b_out_num;       /*!<MCPWM0A out pin*/
    int mcpwm2a_out_num;       /*!<MCPWM0A out pin*/
    int mcpwm2b_out_num;       /*!<MCPWM0A out pin*/
    int mcpwm_sync0_in_num;    /*!<SYNC0  in pin*/
    int mcpwm_sync1_in_num;    /*!<SYNC1  in pin*/
    int mcpwm_sync2_in_num;    /*!<SYNC2  in pin*/
    int mcpwm_fault0_in_num;   /*!<FAULT0 in pin*/
    int mcpwm_fault1_in_num;   /*!<FAULT1 in pin*/
    int mcpwm_fault2_in_num;   /*!<FAULT2 in pin*/
    int mcpwm_cap0_in_num;     /*!<CAP0   in pin*/
    int mcpwm_cap1_in_num;     /*!<CAP1   in pin*/
    int mcpwm_cap2_in_num;     /*!<CAP2   in pin*/
} mcpwm_pin_config_t;
// 使用结构体绑定
esp_err_t mcpwm_set_pin(mcpwm_unit_t mcpwm_num, const mcpwm_pin_config_t *mcpwm_pin);

MCPWM初始化

/*
参数:
mcpwm_num:MCPWM单元选择(0-1)
timer_pwm:MCPWM单元的计时器
mcpwm_conf:参数配置结构体
*/
esp_err_t mcpwm_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpwm_config_t  *mcpwm_conf);
// 示例(pwm_config为上述MCPWM参数配置中的定义):
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config)

死区设定

MCPWM的死区生成器可以直接用来配置一个A、B信号对的波形,如互补波;还可以设置它们的死区时间,常用高电平有效互补(AHC)。
AHC波形

/*
参数:
mcpwm_num:MCPWM单元选择(0-1)
timer_pwm:MCPWM单元的计时器
mcpwm_deadtime_type_t:死区方式选择。如MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE表示高电平有效互补,MCPWM_ACTIVE_HIGH_MODE表示高电平有效。
red、fed:上升沿和下降沿的延迟,单位为100ns。
*/
esp_err_t mcpwm_deadtime_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_deadtime_type_t dt_mode, uint32_t red, uint32_t fed);

调用以下函数时,死区设置停用:

esp_err_t mcpwm_deadtime_disable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num);

配置好MCPWM参数后,调用以下函数启动MCPWM:

// 启动MCPWM单元0的计时器0
mcpwm_start(MCPWM_UNIT_0, MCPWM_TIMER_0);

MCPWM在运行时,可以改变分辨率、频率、占空比等参数,同时也可以通过有关函数读取。进行修改的函数如下:

/*
参数:
mcpwm_num:MCPWM单元选择(0-1)
timer_pwm:MCPWM单元的计时器
frequency:改变PWM波的频率
*/
esp_err_t mcpwm_set_frequency(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, uint32_t frequency);
/*
参数:
mcpwm_num:MCPWM单元选择(0-1)
timer_pwm:MCPWM单元的计时器
gen:选择操作器(如:MCPWM0A)
frequency:改变PWM波的频率
*/
esp_err_t mcpwm_set_duty(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_generator_t gen, float duty);
// 设置MCPWM0A输出的占空比为50%
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_GEN_A, 50.0);

主程序

输出两路互补PWM波,并使用模拟输入改变PWM波的占空比。
开发板:ESP32-S3 DevKitC-1

#include <Arduino.h>
#include <driver/mcpwm.h>


#define GPIO_PWM0A_OUT 10
#define GPIO_PWM0B_OUT 48
mcpwm_unit_t unit = MCPWM_UNIT_0;
mcpwm_timer_t timer = MCPWM_TIMER_0;
mcpwm_deadtime_type_t deadtime_type = MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE; // 高电平有效互补
volatile float analog;


void setup() {
  // put your setup code here, to run once:
  pinMode(9, OUTPUT); // 9号引脚读取模拟量
  mcpwm_config_t pwm_config = {
    .frequency = 20000, // 频率为20kHz
    .cmpr_a = 70.0, // 占空比
    .cmpr_b = 30.0, // 实验发现,死区类型设置为高电平互补模式时该数无效
    .duty_mode = MCPWM_DUTY_MODE_0, //占空比计算方式为高电平时间
    .counter_mode = MCPWM_UP_COUNTER //计数模式为向上计数
  };
  mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT); // 绑定10号引脚和48号引脚为
  mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, GPIO_PWM0B_OUT);
  mcpwm_init(unit, timer, &pwm_config);
  mcpwm_deadtime_enable(unit, timer, deadtime_type, 10, 10); //死区方式配置
  mcpwm_start(unit, timer);
}


void loop() {
  // put your main code here, to run repeatedly:
  analog = analogRead(9);
  mcpwm_set_duty(unit, timer, MCPWM_GEN_A, analog / 4095 * 100); // 根据读取到的模拟量设置占空比
}

程序运行时,输出频率为20kHz的一对互补PWM波,由引脚10和引脚48输出,且占空比可以通过引脚9的输入调节。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值