IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> esp32外设使用-MCPWM基本使用方法 -> 正文阅读

[嵌入式]esp32外设使用-MCPWM基本使用方法

概述

主要用途

  • 有刷/无刷电机驱动
  • 开关电源
  • DAC
  • 脉冲宽度计算,测距/测速
  • FOC驱动

PWM基本输出配置

关键函数

主要包括IO设置、分辨率设置和MCPWM初始化,分辨率设置值决定了输出PWM的频率,定时器周期寄存器只有16bit,因此分辨率不宜过大或过小,过大有可能计数值超范围,过小则有可能不够计数,需根据实际输出pwm频率范围确定,mcpwm_init()函数执行后会自动启动PWM输出。

//头文件
#include "driver/mcpwm.h"

//设置MCPWM的某个IO
esp_err_t mcpwm_gpio_init(
		mcpwm_unit_t mcpwm_num, //MCPWM_UNIT_0 / MCPWM_UNIT_1
		/**********************************
		* io_signal:
		* 	MCPWM0A / MCPWM0B / MCPWM1A / MCPWM1B / MCPWM2A / MCPWM2B: pwm输出信号
		* 	MCPWM_SYNC_0 / MCPWM_SYNC_1 / MCPWM_SYNC_2:同步输入信号
		* 	MCPWM_FAULT_0 / MCPWM_FAULT_1 / MCPWM_FAULT_2:故障输入信号
		* 	MCPWM_CAP_0 / MCPWM_CAP_1 / MCPWM_CAP_2:捕获输入信号
		* ************************************/
		mcpwm_io_signals_t io_signal, 
		int gpio_num);//GPIO号

//设置一组MCPWM的IO管脚
esp_err_t mcpwm_set_pin(
		mcpwm_unit_t mcpwm_num,//组号 0/1
 		const mcpwm_pin_config_t *mcpwm_pin)//管脚配置信息如下:
mcpwm_pin_config_t mcpwm_pin= {
    .mcpwm0a_out_num = 1,//实际IO号
    .mcpwm0b_out_num = 2,
    .mcpwm1a_out_num = 3,
    .mcpwm1b_out_num = 4,
    .mcpwm2a_out_num = 5,
    .mcpwm2b_out_num = 6,
    .mcpwm_cap0_in_num   = 7,
    .mcpwm_cap1_in_num   = 8,
    .mcpwm_cap2_in_num   = 9,
    .mcpwm_sync0_in_num  = -1,  //Not used
    .mcpwm_sync1_in_num  = -1,  //Not used
    .mcpwm_sync2_in_num  = -1,  //Not used
    .mcpwm_fault0_in_num = 10,
    .mcpwm_fault1_in_num = -1,  //Not used
    .mcpwm_fault2_in_num = -1   //Not used
};

//设置mcpwm分辨率,相当于MCPWMx所使用的时钟,需在mcpwm_init()之前调用
esp_err_t mcpwm_group_set_resolution(mcpwm_unit_t mcpwm_num, unsigned long int resolution);//MCPWM号(0/1)、分辨率(默认:10,000,000)

//设置定时器分辨率,相当于计数器的计数时钟,决定了计数器精度,需在mcpwm_init()之前调用
esp_err_t mcpwm_timer_set_resolution(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, unsigned long int resolution)//定时器号(0/1/2) 、分辨率(默认1,000,000) 当设置输出频率≥分辨率时将不能输出。

//初始化并启动一组MCPWM
esp_err_t mcpwm_init(
		mcpwm_unit_t mcpwm_num,//组号 0/1
		mcpwm_timer_t timer_num, //定时器号 0/1/2
		const mcpwm_config_t *mcpwm_conf);//配置如下:
mcpwm_config_t mcpwm_conf = {
        .frequency = 1000, //输出pwm波形频率 Hz
        .cmpr_a = 22.3,     //操作器A输出占空比, i.e duty_a = 62.3
        .cmpr_b = 42.8,     //操作器B输出占空比, i.e duty_a = 42.8
        /*******************************************
         *duty_mode (占空比类型):
         *	MCPWM_DUTY_MODE_0: 高有效,例如:%20占空比 == 高电平20%
         *	MCPWM_DUTY_MODE_1: 低有效,例如:%20占空比 == 低电平20%
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_LOW: 输出强制为低
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH:输出强制为高
         ********************************************/
        .duty_mode = MCPWM_DUTY_MODE_0,
        /****************************************
         * counter_mode (计数模式):
         * 	MCPWM_FREEZE_COUNTER: 计数器冻结
         * 	MCPWM_UP_COUNTER:  计数器递增,左对齐,频率不变
         * 	MCPWM_DOWN_COUNTER: 计数器递减,右对齐,频率不变
         * 	MCPWM_UP_DOWN_COUNTER:计数器递增递减,中间对齐,频率减半
         ********************************************/
        .counter_mode = MCPWM_UP_DOWN_COUNTER};

动态控制函数

//强制输出高电平 / 低电平
esp_err_t mcpwm_set_signal_high or mcpwm_set_signal_low (
		mcpwm_unit_t mcpwm_num, //MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num, //MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
		mcpwm_generator_t gen)//MCPWM_GEN_A / MCPWM_GEN_B

//启动/停止MCPWM输出
esp_err_t mcpwm_start(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
esp_err_t mcpwm_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)

//设置占空比类型
esp_err_t mcpwm_set_duty_type(
		mcpwm_unit_t mcpwm_num, //MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num, //MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
		mcpwm_generator_t gen, //MCPWM_GEN_A / MCPWM_GEN_B
		/*******************************************
         *duty_type (占空比类型):
         *	MCPWM_DUTY_MODE_0: 高有效,例如:%20占空比 == 高电平20%
         *	MCPWM_DUTY_MODE_1: 低有效,例如:%20占空比 == 低电平20%
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_LOW: 输出强制为低
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH:输出强制为高
         ********************************************/
		mcpwm_duty_type_t duty_type)
//动态调整占空比-比例调整
esp_err_t mcpwm_set_duty(
		mcpwm_unit_t mcpwm_num, //MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num, //MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
		mcpwm_generator_t gen, //MCPWM_GEN_A / MCPWM_GEN_B
		float duty)//0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
//动态调整占空比-按时间调整(us)
esp_err_t mcpwm_set_duty_in_us(
		mcpwm_unit_t mcpwm_num, //MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num, //MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
		mcpwm_generator_t gen, //MCPWM_GEN_A / MCPWM_GEN_B
		uint32_t duty_in_us)// x(us) 
//获取当前占空比-返回比例值
float mcpwm_get_duty(
		mcpwm_unit_t mcpwm_num, //MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num, //MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
		mcpwm_operator_t gen)//MCPWM_GEN_A / MCPWM_GEN_B

//设置PWM输出频率
esp_err_t mcpwm_set_frequency(
		mcpwm_unit_t mcpwm_num, //MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num, //MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
		uint32_t frequency)//频率值(Hz)
//获取当前频率值
uint32_t mcpwm_get_frequency(
		mcpwm_unit_t mcpwm_num, //MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num)//MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2

示例程序

本示例程序配置MCPWM0的定时器0输出5KHz的PWM,并每5ms动态调整占空比,需要注意的是系统默认tick速率位100Hz(10ms),不能延迟小于10ms,需进行以下修改,改为1ms(1000Hz)即可。
在这里插入图片描述

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"

#include "string.h"
#include "driver/mcpwm.h"

void app_main(void)
{
    mcpwm_pin_config_t mcpwm_pin = {
        .mcpwm0a_out_num = 14, //实际IO号
        .mcpwm0b_out_num = 15,
        .mcpwm1a_out_num = -1,
        .mcpwm1b_out_num = -1,
        .mcpwm2a_out_num = -1,
        .mcpwm2b_out_num = -1,
        .mcpwm_cap0_in_num = -1,
        .mcpwm_cap1_in_num = -1,
        .mcpwm_cap2_in_num = -1,
        .mcpwm_sync0_in_num = -1, // Not used
        .mcpwm_sync1_in_num = -1, // Not used
        .mcpwm_sync2_in_num = -1, // Not used
        .mcpwm_fault0_in_num = -1,
        .mcpwm_fault1_in_num = -1, // Not used
        .mcpwm_fault2_in_num = -1  // Not used
    };
    //设置PWM定时器分辨率
    ESP_ERROR_CHECK(mcpwm_set_pin(MCPWM_UNIT_0, &mcpwm_pin));
    ESP_ERROR_CHECK(mcpwm_group_set_resolution(MCPWM_UNIT_0, 10000000));               // MCPWM号(0/1)、分辨率(默认:10,000,000)
    ESP_ERROR_CHECK(mcpwm_timer_set_resolution(MCPWM_UNIT_0, MCPWM_TIMER_0, 1000000)); //定时器号(0/1/2)、分辨率(默认:1,000,000)

    mcpwm_config_t mcpwm_conf = {
        .frequency = 10000, //输出pwm波形频率 Hz
        .cmpr_a = 0,        //操作器A输出占空比, i.e duty_a = 62.3
        .cmpr_b = 0,        //操作器B输出占空比, i.e duty_a = 42.8
        /*******************************************
         *duty_mode (占空比类型):
         *	MCPWM_DUTY_MODE_0: 高有效,例如:%20占空比 == 高电平20%
         *	MCPWM_DUTY_MODE_1: 低有效,例如:%20占空比 == 低电平20%
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_LOW: 输出强制为低
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH:输出强制为高
         *	MCPWM_DUTY_MODE_MAX:Num of duty cycle modes
         ********************************************/
        .duty_mode = MCPWM_DUTY_MODE_0,
        /****************************************
         * counter_mode (计数模式):
         * 	MCPWM_FREEZE_COUNTER: 计数器冻结
         * 	MCPWM_UP_COUNTER:  计数器递增,左对齐,频率不变
         * 	MCPWM_DOWN_COUNTER: 计数器递减,右对齐,频率不变
         * 	MCPWM_UP_DOWN_COUNTER:计数器递增递减,中间对齐,频率减半
         ********************************************/
        .counter_mode = MCPWM_UP_DOWN_COUNTER};
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &mcpwm_conf));
    float j;
    while(1)
    {
        for (j = 0.1; j < 100; j = j + 0.1)
        {
            vTaskDelay(pdMS_TO_TICKS(5));
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_0, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_A,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_0, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_B,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
        }
        for (j = 99.9; j > 0; j = j - 0.1)
        {
            vTaskDelay(pdMS_TO_TICKS(5));
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_0, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_A,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_0, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_B,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
        }
    }
}

效果展示:
示波器1通道—MCPWM0_TIMER0_A; 示波器2通道—MCPWM0_TIMER0_B;
在这里插入图片描述

死区时间设置

原理说明

死区时间 : MOS管都存在结电容,存在开关延迟,死区时间是为了保证上下桥臂的MOS管不会同时导通的时间,一般在us级
ESP32死区时间控制原理如下图所示,控制S1 to S7 开关可选择不同的死区时间配置模式。
在这里插入图片描述

设置开关不容易理解且繁琐,下面列出几种常用的工作模式:

MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE(高有效互补):
输出A与输入同相,不考虑死区时间时输出A与B互补(A=!B),死区时间内A=B。
MCPWM_ACTIVE_LOW_COMPLIMENT_MODE(低有效互补):
输出A与输入反相,不考虑死区时间时输出A与B互补(A=!B),死区时间内A=B。
在这里插入图片描述
MCPWM_ACTIVE_HIGH_MODE(高有效模式):
输出A与输入同相,不考虑死区时间时输出A与B相等(A=B),死区时间内A=!B。
MCPWM_ACTIVE_LOW_MODE(低有效模式):
输出A与输入反相,不考虑死区时间时输出A与B相等(A=B),死区时间内A=!B。

在这里插入图片描述

函数说明

//使能死区时间设置,必须在mcpwm_init()函数之后设置,否则无效。
esp_err_t mcpwm_deadtime_enable(
		mcpwm_unit_t mcpwm_num, // MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
		mcpwm_deadtime_type_t dt_mode, //MCPWM_ACTIVE_HIGH/LOW_COMPLIMENT_MODE / MCPWM_ACTIVE_HIGH/LOW_MODE
		uint32_t red, //上升沿延迟: red x 100ns
		uint32_t fed) //下降沿延迟: fed x 100ns

esp_err_t mcpwm_deadtime_disable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)// MCPWM_UNIT_0 / 1 and MCPWM_TIMER_0 / 1 / 2

示例程序

该程序展示死区时间配置,死区模块配置为高有效互补模式,输出只与A相关,因此只需要调整A的占空比即可。上升沿延迟和下降沿延迟均为10us,需注意mcpwm_deadtime_enable()函数需在mcpwm_init()函数之后执行,否则无效。

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"

#include "string.h"
#include "driver/mcpwm.h"

void app_main(void)
{
    float j;
    mcpwm_pin_config_t mcpwm_pin = {
        .mcpwm0a_out_num = 14, //实际IO号
        .mcpwm0b_out_num = 15,
        .mcpwm1a_out_num = -1,
        .mcpwm1b_out_num = -1,
        .mcpwm2a_out_num = -1,
        .mcpwm2b_out_num = -1,
        .mcpwm_cap0_in_num = -1,
        .mcpwm_cap1_in_num = -1,
        .mcpwm_cap2_in_num = -1,
        .mcpwm_sync0_in_num = -1, // Not used
        .mcpwm_sync1_in_num = -1, // Not used
        .mcpwm_sync2_in_num = -1, // Not used
        .mcpwm_fault0_in_num = -1,
        .mcpwm_fault1_in_num = -1, // Not used
        .mcpwm_fault2_in_num = -1  // Not used
    };
    //设置PWM定时器分辨率
    ESP_ERROR_CHECK(mcpwm_set_pin(MCPWM_UNIT_0, &mcpwm_pin));
    ESP_ERROR_CHECK(mcpwm_group_set_resolution(MCPWM_UNIT_0, 10000000));               // MCPWM号(0/1)、分辨率(默认:10,000,000)
    ESP_ERROR_CHECK(mcpwm_timer_set_resolution(MCPWM_UNIT_0, MCPWM_TIMER_0, 1000000)); //定时器号(0/1/2)、分辨率(默认:1,000,000)

    mcpwm_config_t mcpwm_conf = {
        .frequency = 10000, //输出pwm波形频率 Hz
        .cmpr_a = 0,        //操作器A输出占空比, i.e duty_a = 62.3
        .cmpr_b = 0,        //操作器B输出占空比, i.e duty_a = 42.8
        /*******************************************
         *duty_mode (占空比类型):
         *	MCPWM_DUTY_MODE_0: 高有效,例如:%20占空比 == 高电平20%
         *	MCPWM_DUTY_MODE_1: 低有效,例如:%20占空比 == 低电平20%
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_LOW: 输出强制为低
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH:输出强制为高
         *	MCPWM_DUTY_MODE_MAX:Num of duty cycle modes
         ********************************************/
        .duty_mode = MCPWM_DUTY_MODE_0,
        /****************************************
         * counter_mode (计数模式):
         * 	MCPWM_FREEZE_COUNTER: 计数器冻结
         * 	MCPWM_UP_COUNTER:  计数器递增,左对齐,频率不变
         * 	MCPWM_DOWN_COUNTER: 计数器递减,右对齐,频率不变
         * 	MCPWM_UP_DOWN_COUNTER:计数器递增递减,中间对齐,频率减半
         ********************************************/
        .counter_mode = MCPWM_UP_DOWN_COUNTER};

    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &mcpwm_conf));
    ESP_ERROR_CHECK(mcpwm_deadtime_enable(
        MCPWM_UNIT_0,                      // MCPWM_UNIT_0 / MCPWM_UNIT_1
        MCPWM_TIMER_0,                     // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
        MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, // MCPWM_ACTIVE_HIGH/LOW_COMPLIMENT_MODE / MCPWM_ACTIVE_HIGH/LOW_MODE
        100,                               //上升沿延迟: red x 100ns
        100));                             //下降沿延迟: fed x 100ns
    while (1)
    {
        for (j = 20; j < 80; j = j + 0.1)
        {
            vTaskDelay(pdMS_TO_TICKS(5));
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_0, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_A,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
        }
        for (j = 80; j > 20; j = j - 0.1)
        {
            vTaskDelay(pdMS_TO_TICKS(5));
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_0, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_A,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
        }
    }
}

效果:
示波器1通道—MCPWM0_TIMER0_A; 示波器2通道—MCPWM0_TIMER0_B;
在这里插入图片描述

定时器同步

定时器同步用于对不同定时器之间计数值的同步,输入同步信号支持GPIO或来自其他定时器的同步输出信号。

关键函数说明

//初始化定时器同步子模块
esp_err_t mcpwm_sync_configure(
		mcpwm_unit_t mcpwm_num, // MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
		const mcpwm_sync_config_t *sync_conf)//
//关闭定时器同步
esp_err_t mcpwm_sync_disable(
		mcpwm_unit_t mcpwm_num, // MCPWM_UNIT_0 / MCPWM_UNIT_1
		mcpwm_timer_t timer_num)// MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
mcpwm_sync_config_t sync_cfg = {
		.sync_sig = MCPWM_SELECT_GPIO_SYNC0,//输入同步信号:MCPWM_SELECT_TIMER0/1/2_SYNC / MCPWM_SELECT_GPIO_SYNC0/1/2
		.timer_val = 0,//同步之后要载入的定时器值 0-999
		.count_direction = MCPWM_TIMER_DIRECTION_UP};//MCPWM_TIMER_DIRECTION_UP(递增)/ MCPWM_TIMER_DIRECTION_DOWN(递减)

示例程序

该程序启动MCPWM0中的Timer0和Timer1两个定时器,分别输出两个异步的PWM波,然后采用GPIO同步的方式,设置IO输出同步脉冲,进行软件同步。
注意:
该程序复用IO2即作为2个定时器的同步输入信号,又作为双向IO可进行软件置位/清零,IO复位后需先配置 mcpwm_set_pin() ,再配置IO方向,否则后面设置IO2高低电平函数不起作用。
在这里插入图片描述

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"

#include "string.h"
#include "driver/mcpwm.h"
#include "driver/gpio.h"

#define io_num(x) x

void app_main(void)
{
    float j;
    // IO配置
    mcpwm_pin_config_t mcpwm_pin = {
        .mcpwm0a_out_num = io_num(14), //实际IO号
        .mcpwm0b_out_num = io_num(15),
        .mcpwm1a_out_num = io_num(4),
        .mcpwm1b_out_num = io_num(9),
        .mcpwm2a_out_num = -1,
        .mcpwm2b_out_num = -1,
        .mcpwm_cap0_in_num = -1,
        .mcpwm_cap1_in_num = -1,
        .mcpwm_cap2_in_num = -1,
        .mcpwm_sync0_in_num = io_num(2), // Not used
        .mcpwm_sync1_in_num = -1,        // Not used
        .mcpwm_sync2_in_num = -1,        // Not used
        .mcpwm_fault0_in_num = -1,
        .mcpwm_fault1_in_num = -1, // Not used
        .mcpwm_fault2_in_num = -1  // Not used
    };
    gpio_reset_pin(io_num(2));
    ESP_ERROR_CHECK(mcpwm_set_pin(MCPWM_UNIT_0, &mcpwm_pin));
    gpio_set_direction(io_num(2), GPIO_MODE_INPUT_OUTPUT);

    //设置PWM定时器分辨率
    ESP_ERROR_CHECK(mcpwm_group_set_resolution(MCPWM_UNIT_0, 10000000));               // MCPWM号(0/1)、分辨率(默认:10,000,000)
    ESP_ERROR_CHECK(mcpwm_timer_set_resolution(MCPWM_UNIT_0, MCPWM_TIMER_0, 1000000)); //定时器号(0/1/2)、分辨率(默认:1,000,000)
    ESP_ERROR_CHECK(mcpwm_timer_set_resolution(MCPWM_UNIT_0, MCPWM_TIMER_1, 1000000)); //定时器号(0/1/2)、分辨率(默认:1,000,000)

    mcpwm_config_t mcpwm_conf = {
        .frequency = 10000, //输出pwm波形频率 Hz
        .cmpr_a = 0,        //操作器A输出占空比, i.e duty_a = 62.3
        .cmpr_b = 0,        //操作器B输出占空比, i.e duty_a = 42.8
        /*******************************************
         *duty_mode (占空比类型):
         *	MCPWM_DUTY_MODE_0: 高有效,例如:%20占空比 == 高电平20%
         *	MCPWM_DUTY_MODE_1: 低有效,例如:%20占空比 == 低电平20%
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_LOW: 输出强制为低
         *	MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH:输出强制为高
         *	MCPWM_DUTY_MODE_MAX:Num of duty cycle modes
         ********************************************/
        .duty_mode = MCPWM_DUTY_MODE_0,
        /****************************************
         * counter_mode (计数模式):
         * 	MCPWM_FREEZE_COUNTER: 计数器冻结
         * 	MCPWM_UP_COUNTER:  计数器递增,左对齐,频率不变
         * 	MCPWM_DOWN_COUNTER: 计数器递减,右对齐,频率不变
         * 	MCPWM_UP_DOWN_COUNTER:计数器递增递减,中间对齐,频率减半
         ********************************************/
        .counter_mode = MCPWM_UP_DOWN_COUNTER};

    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &mcpwm_conf)); //启动定时器0
    vTaskDelay(pdMS_TO_TICKS(50));                                         //增加两个定时器的启动延迟,产生明显异步效果便于观察
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_1, &mcpwm_conf)); //启动定时器1

    //同步配置
    mcpwm_sync_config_t sync_cfg = {
        .sync_sig = MCPWM_SELECT_GPIO_SYNC0,          //输入同步信号:MCPWM_SELECT_TIMER0/1/2_SYNC / MCPWM_SELECT_GPIO_SYNC0/1/2
        .timer_val = 0,                               //同步之后要载入的定时器值 0-999
        .count_direction = MCPWM_TIMER_DIRECTION_UP}; // MCPWM_TIMER_DIRECTION_UP(递增)/ MCPWM_TIMER_DIRECTION_DOWN(递减)
    ESP_ERROR_CHECK(mcpwm_sync_configure(
        MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
        MCPWM_TIMER_0, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
        &sync_cfg));   //同步配置
    ESP_ERROR_CHECK(mcpwm_sync_configure(
        MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
        MCPWM_TIMER_1, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
        &sync_cfg));   //同步配置

    //生成同步脉冲
    gpio_set_level(io_num(2), 0); // IO置低
    vTaskDelay(pdMS_TO_TICKS(5));
    gpio_set_level(io_num(2), 1); // IO置高
    vTaskDelay(pdMS_TO_TICKS(5));
    gpio_set_level(io_num(2), 0); // IO置低
    vTaskDelay(pdMS_TO_TICKS(5));

    while (1)
    {
        for (j = 20; j < 80; j = j + 0.1)
        {
            vTaskDelay(pdMS_TO_TICKS(5));
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_0, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_A,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_1, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_A,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
        }
        for (j = 80; j > 20; j = j - 0.1)
        {
            vTaskDelay(pdMS_TO_TICKS(5));
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_0, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_A,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
            ESP_ERROR_CHECK(mcpwm_set_duty(
                MCPWM_UNIT_0,  // MCPWM_UNIT_0 / MCPWM_UNIT_1
                MCPWM_TIMER_1, // MCPWM_TIMER_0 / MCPWM_TIMER_1 / MCPWM_TIMER_2
                MCPWM_GEN_A,   // MCPWM_GEN_A / MCPWM_GEN_B
                j));           // 0.0 to 100.0,精度为小数点后1位,设置0和100等效于强制输出高、低
        }
    }
}

效果:
不同步,示波器1通道—MCPWM0_TIMER0_A; 示波器2通道—MCPWM0_TIMER1_A;
在这里插入图片描述
同步之后:
在这里插入图片描述

参考

https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/peripherals/mcpwm.html

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:58:04  更:2022-10-08 21:02:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 18:10:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码