ePWM配置与使用

目录

  1. ePWM基础
  2. 与STM32对比
  3. ePWM寄存器
  4. 手动配置ePWM
  5. SysConfig配置ePWM
  6. 实战示例

ePWM基础

F280049C的ePWM (Enhanced Pulse Width Modulator) 是专为电机控制和数字电源设计的高级PWM模块。

ePWM特性

  • ePWM数量: 8个独立的ePWM模块
  • 输出通道: 每个模块2个输出(A和B)
  • 分辨率: 16位时基计数器
  • 频率: 最高可达SYSCLK频率
  • 死区控制: 硬件死区生成
  • 故障保护: Trip-Zone保护
  • 相位同步: 多个ePWM模块可同步

ePWM模块组成

  1. 时基模块 (TB) - 时基计数器和周期控制
  2. 计数比较模块 (CC) - 比较值设置
  3. 动作限定模块 (AQ) - 输出动作控制
  4. 死区模块 (DB) - 死区时间生成
  5. 斩波模块 (PC) - 高频斩波
  6. Trip-Zone模块 (TZ) - 故障保护
  7. 事件触发模块 (ET) - ADC触发和中断

与STM32对比

PWM功能对比

功能 STM32 TIM F280049C ePWM
基本PWM
互补PWM
死区控制 ✓ (更强大)
相位同步 有限 ✓ (完整支持)
故障保护 基本 ✓ (Trip-Zone)
ADC触发 ✓ (更灵活)

配置流程对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// STM32 HAL库
TIM_HandleTypeDef htim1;
TIM_OC_InitTypeDef sConfigOC = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.Period = 999;
HAL_TIM_PWM_Init(&htim1);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

// F280049C DriverLib
EPWM_setTimeBasePeriod(EPWM1_BASE, 1000);
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 500);
EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

ePWM寄存器

时基模块寄存器

1. TBCTL - 时基控制寄存器

1
2
3
4
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;      // 向上计数
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // 禁用相位同步
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // 时钟不分频
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // 高速时钟不分频

2. TBPRD - 时基周期寄存器

1
EPwm1Regs.TBPRD = 1000;  // 设置PWM周期

3. TBPHS - 时基相位寄存器

1
EPwm1Regs.TBPHS.bit.TBPHS = 0;  // 设置相位偏移

计数比较模块寄存器

4. CMPA/CMPB - 比较寄存器

1
2
EPwm1Regs.CMPA.bit.CMPA = 500;  // 设置比较值A
EPwm1Regs.CMPB.bit.CMPB = 500; // 设置比较值B

动作限定模块寄存器

5. AQCTLA/AQCTLB - 动作控制寄存器

1
2
3
4
// 计数器为0时,输出高电平
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
// 计数器等于CMPA时,输出低电平
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;

死区模块寄存器

6. DBCTL - 死区控制寄存器

1
2
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;  // 使能死区
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // 极性选择

7. DBRED/DBFED - 死区延时寄存器

1
2
EPwm1Regs.DBRED.bit.DBRED = 100;  // 上升沿死区
EPwm1Regs.DBFED.bit.DBFED = 100; // 下降沿死区

手动配置ePWM

方法1: 直接寄存器操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "F28x_Project.h"

void EPWM1_Init_Register(void)
{
EALLOW;

// 1. 配置GPIO引脚
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // EPWM1B

// 2. 停止时基计数器
EPwm1Regs.TBCTL.bit.CTRMODE = TB_FREEZE;

// 3. 配置时基模块
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // TBCLK = SYSCLK
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // 禁用相位加载
EPwm1Regs.TBPRD = 1000; // 设置周期

// 4. 配置比较模块
EPwm1Regs.CMPA.bit.CMPA = 500; // 50%占空比

// 5. 配置动作限定模块
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // CTR=0时,输出高
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // CTR=CMPA时,输出低

// 6. 启动时基计数器
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;

EDIS;
}

方法2: DriverLib库函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "driverlib.h"
#include "device.h"

void EPWM1_Init_DriverLib(void)
{
// 1. 配置GPIO引脚
GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_0_EPWM1_A);

GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_1_EPWM1_B);

// 2. 禁用时基计数器
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);

// 3. 配置时基模块
EPWM_setClockPrescaler(EPWM1_BASE,
EPWM_CLOCK_DIVIDER_1,
EPWM_HSCLOCK_DIVIDER_1);
EPWM_setTimeBasePeriod(EPWM1_BASE, 1000);
EPWM_setPhaseShift(EPWM1_BASE, 0);
EPWM_disablePhaseShiftLoad(EPWM1_BASE);

// 4. 配置比较模块
EPWM_setCounterCompareValue(EPWM1_BASE,
EPWM_COUNTER_COMPARE_A,
500);

// 5. 配置动作限定模块
EPWM_setActionQualifierAction(EPWM1_BASE,
EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_HIGH,
EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM1_BASE,
EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_LOW,
EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

// 6. 启动时基计数器
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
}

PWM频率和占空比计算

频率计算

1
PWM频率 = SYSCLK / (CLKDIV × HSPCLKDIV × TBPRD)

示例

1
2
3
4
5
6
7
8
9
10
// SYSCLK = 100MHz
// 需要20kHz PWM

// 方法1: 不分频
TBPRD = 100MHz / 20kHz = 5000
CLKDIV = 1, HSPCLKDIV = 1

// 方法2: 2分频
TBPRD = 100MHz / (2 × 20kHz) = 2500
CLKDIV = 2, HSPCLKDIV = 1

占空比计算

1
占空比 = CMPA / TBPRD × 100%

SysConfig配置ePWM

步骤1: 添加ePWM模块

  1. 在SysConfig中找到 EPWM
  2. 点击 “+” 添加ePWM实例
  3. 选择 EPWM1-EPWM8

步骤2: 配置参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
EPWM Instance: EPWM1
├── Time Base
│ ├── Period: 5000 (20kHz @ 100MHz)
│ ├── Counter Mode: Up Count
│ └── Clock Divider: 1
├── Counter Compare
│ ├── CMPA: 2500 (50% duty)
│ └── CMPB: 2500
├── Action Qualifier
│ ├── EPWM1A: Set on Zero, Clear on CMPA
│ └── EPWM1B: Set on Zero, Clear on CMPB
└── Dead Band
├── Enable: ✓
├── Rising Edge Delay: 100
└── Falling Edge Delay: 100

步骤3: 使用生成的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "board.h"

void main(void)
{
Device_init();
Device_initGPIO();

// 调用SysConfig生成的初始化
Board_init();

while(1)
{
// 主循环
}
}

实战示例

示例1: 基本PWM输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "driverlib.h"
#include "device.h"

void EPWM1_Init_Basic(void)
{
// 配置GPIO
GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_0_EPWM1_A);

// 配置ePWM(20kHz, 50%占空比)
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setTimeBasePeriod(EPWM1_BASE, 5000); // 20kHz
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 2500); // 50%

EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
}

void main(void)
{
Device_init();
Device_initGPIO();

EPWM1_Init_Basic();

while(1);
}

示例2: 互补PWM带死区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "driverlib.h"
#include "device.h"

void EPWM1_Init_Complementary(void)
{
// 配置GPIO
GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_0_EPWM1_A);
GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_1_EPWM1_B);

// 配置时基
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setTimeBasePeriod(EPWM1_BASE, 5000);
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 2500);

// 配置动作限定(互补输出)
EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

// 配置死区(1us死区时间)
EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_RED, true);
EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_FED, true);
EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
EPWM_setRisingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_DB_INPUT_EPWMA);
EPWM_setFallingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_DB_INPUT_EPWMA);
EPWM_setRisingEdgeDelayCount(EPWM1_BASE, 100); // 1us @ 100MHz
EPWM_setFallingEdgeDelayCount(EPWM1_BASE, 100);
EPWM_setDeadBandCounterClock(EPWM1_BASE, EPWM_DB_COUNTER_CLOCK_FULL_CYCLE);

EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
}

void main(void)
{
Device_init();
Device_initGPIO();

EPWM1_Init_Complementary();

while(1);
}

示例3: 动态调整占空比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "driverlib.h"
#include "device.h"

void EPWM1_Init(void)
{
GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_0_EPWM1_A);

EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setTimeBasePeriod(EPWM1_BASE, 5000);
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 0);

EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
}

void EPWM1_SetDutyCycle(float duty)
{
// duty: 0.0 - 100.0
uint16_t cmpa = (uint16_t)(5000 * duty / 100.0f);
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, cmpa);
}

void main(void)
{
Device_init();
Device_initGPIO();

EPWM1_Init();

float duty = 0.0f;
while(1)
{
// 占空比从0%渐变到100%
for(duty = 0.0f; duty <= 100.0f; duty += 1.0f)
{
EPWM1_SetDutyCycle(duty);
DEVICE_DELAY_US(10000); // 10ms延时
}

// 占空比从100%渐变到0%
for(duty = 100.0f; duty >= 0.0f; duty -= 1.0f)
{
EPWM1_SetDutyCycle(duty);
DEVICE_DELAY_US(10000);
}
}
}

示例4: 三相PWM(电机控制)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include "driverlib.h"
#include "device.h"

#define PWM_PERIOD 5000 // 20kHz

void EPWM_Init_ThreePhase(void)
{
// 配置EPWM1(U相)
GPIO_setPinConfig(GPIO_0_EPWM1_A);
GPIO_setPinConfig(GPIO_1_EPWM1_B);

// 配置EPWM2(V相)
GPIO_setPinConfig(GPIO_2_EPWM2_A);
GPIO_setPinConfig(GPIO_3_EPWM2_B);

// 配置EPWM3(W相)
GPIO_setPinConfig(GPIO_4_EPWM3_A);
GPIO_setPinConfig(GPIO_5_EPWM3_B);

// 初始化EPWM1(主模块)
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setTimeBasePeriod(EPWM1_BASE, PWM_PERIOD);
EPWM_setPhaseShift(EPWM1_BASE, 0);
EPWM_disablePhaseShiftLoad(EPWM1_BASE);
EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);

// 初始化EPWM2(从模块,相位120度)
EPWM_setTimeBaseCounterMode(EPWM2_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
EPWM_setClockPrescaler(EPWM2_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setTimeBasePeriod(EPWM2_BASE, PWM_PERIOD);
EPWM_setPhaseShift(EPWM2_BASE, PWM_PERIOD / 3); // 120度相位
EPWM_enablePhaseShiftLoad(EPWM2_BASE);
EPWM_setPhaseShiftLoadMode(EPWM2_BASE, EPWM_PHASE_SHIFT_LOAD_ON_SYNC_IN);

// 初始化EPWM3(从模块,相位240度)
EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
EPWM_setClockPrescaler(EPWM3_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setTimeBasePeriod(EPWM3_BASE, PWM_PERIOD);
EPWM_setPhaseShift(EPWM3_BASE, PWM_PERIOD * 2 / 3); // 240度相位
EPWM_enablePhaseShiftLoad(EPWM3_BASE);
EPWM_setPhaseShiftLoadMode(EPWM3_BASE, EPWM_PHASE_SHIFT_LOAD_ON_SYNC_IN);

// 配置动作限定(所有三相相同)
uint32_t epwm_bases[] = {EPWM1_BASE, EPWM2_BASE, EPWM3_BASE};
for(int i = 0; i < 3; i++)
{
EPWM_setActionQualifierAction(epwm_bases[i], EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(epwm_bases[i], EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

// 配置死区
EPWM_setDeadBandDelayMode(epwm_bases[i], EPWM_DB_RED, true);
EPWM_setDeadBandDelayMode(epwm_bases[i], EPWM_DB_FED, true);
EPWM_setRisingEdgeDelayCount(epwm_bases[i], 100);
EPWM_setFallingEdgeDelayCount(epwm_bases[i], 100);
}

// 启动所有ePWM
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
EPWM_setTimeBaseCounterMode(EPWM2_BASE, EPWM_COUNTER_MODE_UP);
EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_UP);
}

void main(void)
{
Device_init();
Device_initGPIO();

EPWM_Init_ThreePhase();

// 设置初始占空比(50%)
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, PWM_PERIOD / 2);
EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_A, PWM_PERIOD / 2);
EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_A, PWM_PERIOD / 2);

while(1);
}

常见问题

1. PWM输出不正常?

  • 检查GPIO引脚配置
  • 检查时基计数器是否启动
  • 检查CMPA值是否在有效范围内(0-TBPRD)

2. 如何提高PWM分辨率?

  • 增大TBPRD值
  • 降低PWM频率
  • 使用高分辨率PWM(HRPWM)模块

3. 死区时间如何计算?

1
死区时间(ns) = 死区计数值 × (1 / TBCLK频率)

4. 如何同步多个ePWM?

  • 设置主模块的SYNC_OUT
  • 从模块使能相位加载
  • 设置相位偏移值

5. Trip-Zone故障保护?

1
2
3
4
// 配置Trip-Zone
EPWM_enableTripZoneSignals(EPWM1_BASE, EPWM_TZ_SIGNAL_CBC1);
EPWM_setTripZoneAction(EPWM1_BASE, EPWM_TZ_ACTION_EVENT_TZA,
EPWM_TZ_ACTION_LOW);

下一步

学习完ePWM后,继续学习:


参考资料

  • TMS320F28004x Technical Reference Manual - ePWM Module
  • C2000Ware DriverLib API Guide - EPWM Module
  • ePWM Example Code in C2000Ware
  • C2000 Motor Control SDK