PWM.h文件的建立
PWM的头文件配置较为简单,仅用来申明源文件中会用到的初始函数以及中断函数还有初始函数中用到的计算参数。
/*
* PWM.h
*
* Created on: 2023年7月10日
* Author: 24460
*/
#ifndef USER_INC_PWM_H_
#define USER_INC_PWM_H_
#define Tsw 0.0002 //PWM周期时间
#define tbprd Tsw*1000000*12.5 //PWM频率计算参数
void EPWM1_int(void);
__interrupt void pwm_isr (void);
#endif /* USER_INC_PWM_H_ */
PWM.c文件的建立
在PWM源文件中,将会对PWM进行初始化,以及在中断函数中周期调用前篇文章所介绍到的开环FOC控制函数。
/*
* PWM.c
*
* Created on: 2023年7月10日
* Author: 24460
*/
#include "F28x_Project.h"
#include "PWM.h"
#include "FOC.h"
/*-----------------------<PWM相关函数>-------------------------------------------------------------------------*/
//周期时间T=2*tbprd*TBCLK;频率P=1/T;tbprd=6.25*10^6/(2*P);
//FSYSCLK=100MHZ 若FSYSCLK=100MHZ
//FTBCLK=FSYSCLK/16=6.25M 则FTBCLK=FSYSCLK/4=25MHZ
void EPWM1_int(void)
{
//第一步时钟配置
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0; // 失能时基模块时钟TBCLK
CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; // 使能ePWM1CLK
CpuSysRegs.PCLKCR2.bit.EPWM2 = 1; // 使能ePWM2CLK
CpuSysRegs.PCLKCR2.bit.EPWM3 = 1; // 使能ePWM3CLK
EDIS;
//第二步GPIO配置
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1; // Disable pull-up on GPIO0 (EPWM1A)
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1; // Disable pull-up on GPIO1 (EPWM1B)
GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1; // Disable pull-up on GPIO2 (EPWM2A)
GpioCtrlRegs.GPAPUD.bit.GPIO3 = 1; // Disable pull-up on GPIO3 (EPWM2B)
GpioCtrlRegs.GPAPUD.bit.GPIO4 = 1; // Disable pull-up on GPIO4 (EPWM3A)
GpioCtrlRegs.GPAPUD.bit.GPIO5 = 1; // Disable pull-up on GPIO5 (EPWM3B)
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // Configure GPIO1 as EPWM1B
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; // Configure GPIO2 as EPWM2A
GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1; // Configure GPIO3 as EPWM2B
GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1; // Configure GPIO4 as EPWM3A
GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1; // Configure GPIO5 as EPWM3B
EDIS;
//第三步初始化时基模块TB
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; //SYNCO失能
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; //相位失能(因为并不用到同位功能)
EPwm1Regs.TBPHS.bit.TBPHS = 0x0000; //设置计数器相位为0
EPwm1Regs.TBCTR = 0x0000; //初始化计数器计数值
EPwm1Regs.TBPRD = tbprd-1; //设置周期值,
EPwm1Regs.TBCTL.bit.CTRMODE = 2; //0:增计数 1:减计数 2:增减计数 3:停止计数
EPwm1Regs.TBCTL.bit.CLKDIV=1; //TBCLK=SYSCLKOUT/2^(CLKDIV+HSPCLKDIV)
EPwm1Regs.TBCTL.bit.HSPCLKDIV=1; //TBCLK=SYSCLKOUT/2^(CLKDIV+HSPCLKDIV)
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; //SYNCO失能
EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; //相位失能(因为并不用到同位功能)
EPwm2Regs.TBPHS.bit.TBPHS = 0x0000; //设置计数器相位为0
EPwm2Regs.TBCTR = 0x0000; //初始化计数器计数值
EPwm2Regs.TBPRD = tbprd-1; //设置周期值,
EPwm2Regs.TBCTL.bit.CTRMODE = 2; //0:增计数 1:减计数 2:增减计数 3:停止计数
EPwm2Regs.TBCTL.bit.CLKDIV=1; //TBCLK=SYSCLKOUT/2^(CLKDIV+HSPCLKDIV)
EPwm2Regs.TBCTL.bit.HSPCLKDIV=1; //TBCLK=SYSCLKOUT/2^(CLKDIV+HSPCLKDIV)
EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; //SYNCO失能
EPwm3Regs.TBCTL.bit.PHSEN = TB_ENABLE; //相位失能(因为并不用到同位功能)
EPwm3Regs.TBPHS.bit.TBPHS = 0x0000; //设置计数器相位为0
EPwm3Regs.TBCTR = 0x0000; //初始化计数器计数值
EPwm3Regs.TBPRD = tbprd-1; //设置周期值,
EPwm3Regs.TBCTL.bit.CTRMODE = 2; //0:增计数 1:减计数 2:增减计数 3:停止计数
EPwm3Regs.TBCTL.bit.CLKDIV=1; //TBCLK=SYSCLKOUT/2^(CLKDIV+HSPCLKDIV)
EPwm3Regs.TBCTL.bit.HSPCLKDIV=1; //TBCLK=SYSCLKOUT/2^(CLKDIV+HSPCLKDIV)
//第四步初始化计数比较模块CC
EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0; //将CMPA寄存器设置为映射加载模式
EPwm1Regs.CMPCTL.bit.SHDWBMODE = 0; //将CMPB寄存器设置为映射加载模式
EPwm1Regs.CMPCTL.bit.LOADAMODE = 0; //将在TBCTR=0时重装载映射寄存器中的值
EPwm1Regs.CMPCTL.bit.LOADBMODE = 0; //将在TBCTR=0时重装载映射寄存器中的值
EPwm1Regs.CMPA.bit.CMPA = (EPwm1Regs.TBPRD+1)* (1-0);//占空比设定0
EPwm1Regs.CMPB.bit.CMPB = (EPwm1Regs.TBPRD+1) * (1-0);//占空比设定0
EPwm2Regs.CMPCTL.bit.SHDWAMODE = 0; //将CMPA寄存器设置为映射加载模式
EPwm2Regs.CMPCTL.bit.SHDWBMODE = 0; //将CMPB寄存器设置为映射加载模式
EPwm2Regs.CMPCTL.bit.LOADAMODE = 0; //将在TBCTR=0时重装载映射寄存器中的值
EPwm2Regs.CMPCTL.bit.LOADBMODE = 0; //将在TBCTR=0时重装载映射寄存器中的值
EPwm2Regs.CMPA.bit.CMPA = (EPwm2Regs.TBPRD+1)* (1-0);//占空比设定0
EPwm2Regs.CMPB.bit.CMPB = (EPwm2Regs.TBPRD+1)* (1-0);//占空比设定0
EPwm3Regs.CMPCTL.bit.SHDWAMODE = 0; //将CMPA寄存器设置为映射加载模式
EPwm3Regs.CMPCTL.bit.SHDWBMODE = 0; //将CMPB寄存器设置为映射加载模式
EPwm3Regs.CMPCTL.bit.LOADAMODE = 0; //将在TBCTR=0时重装载映射寄存器中的值
EPwm3Regs.CMPCTL.bit.LOADBMODE = 0; //将在TBCTR=0时重装载映射寄存器中的值
EPwm3Regs.CMPA.bit.CMPA = (EPwm3Regs.TBPRD+1)* (1-0);//占空比设定0
EPwm3Regs.CMPB.bit.CMPB = (EPwm3Regs.TBPRD+1)* (1-0);//占空比设定0
//第五步初始化动作限定模块AQ
EPwm1Regs.AQCTLA.bit.CAU = 2; //当CTR=CMPA且正在递增时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm1Regs.AQCTLA.bit.CAD = 1; //当CTR=CMPA且正在递减时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm1Regs.AQCTLB.bit.CBU = 2; //当CTR=CMPB且正在递增时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm1Regs.AQCTLB.bit.CBD = 1; //当CTR=CMPB且正在递减时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm2Regs.AQCTLA.bit.CAU = 2; //当CTR=CMPA且正在递增时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm2Regs.AQCTLA.bit.CAD = 1; //当CTR=CMPA且正在递减时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm2Regs.AQCTLB.bit.CBU = 2; //当CTR=CMPB且正在递增时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm2Regs.AQCTLB.bit.CBD = 1; //当CTR=CMPB且正在递减时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm3Regs.AQCTLA.bit.CAU = 2; //当CTR=CMPA且正在递增时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm3Regs.AQCTLA.bit.CAD = 1; //当CTR=CMPA且正在递减时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm3Regs.AQCTLB.bit.CBU = 2; //当CTR=CMPB且正在递增时: 0:无动作 1:拉低 2:拉高 3:翻转
EPwm3Regs.AQCTLB.bit.CBD = 1; //当CTR=CMPB且正在递减时: 0:无动作 1:拉低 2:拉高 3:翻转
//第六步死区控制模块DB
EPWM_setDeadBandCounterClock(EPWM1_BASE,EPWM_DB_COUNTER_CLOCK_FULL_CYCLE);//全周期
EPWM_setDeadBandCounterClock(EPWM2_BASE,EPWM_DB_COUNTER_CLOCK_FULL_CYCLE);//全周期
EPWM_setDeadBandCounterClock(EPWM3_BASE,EPWM_DB_COUNTER_CLOCK_FULL_CYCLE);//全周期
EPWM_setRisingEdgeDelayCount(EPWM1_BASE,50);//上升沿延时时间:5*10ns
EPWM_setFallingEdgeDelayCount(EPWM1_BASE,50);//下降沿延时时间:5*10ns
EPWM_setRisingEdgeDelayCount(EPWM2_BASE,50);
EPWM_setFallingEdgeDelayCount(EPWM2_BASE,50);
EPWM_setRisingEdgeDelayCount(EPWM3_BASE,50);
EPWM_setFallingEdgeDelayCount(EPWM3_BASE,50);
EPWM_setDeadBandDelayMode(EPWM1_BASE,EPWM_DB_RED,true);//开启上升沿延迟
EPWM_setDeadBandDelayMode(EPWM1_BASE,EPWM_DB_FED,true);//开启下降沿延迟
EPWM_setDeadBandDelayMode(EPWM2_BASE,EPWM_DB_RED,true);
EPWM_setDeadBandDelayMode(EPWM2_BASE,EPWM_DB_FED,true);
EPWM_setDeadBandDelayMode(EPWM3_BASE,EPWM_DB_RED,true);
EPWM_setDeadBandDelayMode(EPWM3_BASE,EPWM_DB_FED,true);
EPWM_setRisingEdgeDeadBandDelayInput(EPWM1_BASE,EPWM_DB_INPUT_EPWMA);//将PWMA作为上升沿延迟的目标
EPWM_setFallingEdgeDeadBandDelayInput(EPWM1_BASE,EPWM_DB_INPUT_EPWMA);//将PWMB作为下降沿延迟的目标
EPWM_setRisingEdgeDeadBandDelayInput(EPWM2_BASE,EPWM_DB_INPUT_EPWMA);
EPWM_setFallingEdgeDeadBandDelayInput(EPWM2_BASE,EPWM_DB_INPUT_EPWMA);
EPWM_setRisingEdgeDeadBandDelayInput(EPWM3_BASE,EPWM_DB_INPUT_EPWMA);
EPWM_setFallingEdgeDeadBandDelayInput(EPWM3_BASE,EPWM_DB_INPUT_EPWMA);
EPWM_setDeadBandDelayPolarity(EPWM1_BASE,EPWM_DB_RED,EPWM_DB_POLARITY_ACTIVE_HIGH);//A进入上升延迟时,B不翻转:AHL模式
EPWM_setDeadBandDelayPolarity(EPWM1_BASE,EPWM_DB_FED,EPWM_DB_POLARITY_ACTIVE_LOW);//A进入下降延迟时,B翻转
EPWM_setDeadBandDelayPolarity(EPWM2_BASE,EPWM_DB_RED,EPWM_DB_POLARITY_ACTIVE_HIGH);
EPWM_setDeadBandDelayPolarity(EPWM2_BASE,EPWM_DB_FED,EPWM_DB_POLARITY_ACTIVE_LOW);
EPWM_setDeadBandDelayPolarity(EPWM3_BASE,EPWM_DB_RED,EPWM_DB_POLARITY_ACTIVE_HIGH);
EPWM_setDeadBandDelayPolarity(EPWM3_BASE,EPWM_DB_FED,EPWM_DB_POLARITY_ACTIVE_LOW);
//第七步事件触发模块ET
EPwm1Regs.ETPS.bit.INTPRD = 1; //发生一次事件,触发一次中断
EPwm1Regs.ETSEL.bit.INTEN = 1; //使能产生中断信号EPWM1_INT
EPwm1Regs.ETSEL.bit.INTSEL= 1; //TBCTR=0时触发
EPwm1Regs.ETCLR.bit.INT =1; //手动清零一次INT
EALLOW;
PieVectTable.EPWM1_INT=&pwm_isr; //将中断服务子函数的地址存放到相应的向量地址中
EDIS;
IER|= M_INT3; //CPU级∶使能CPU级的中断信号
PieCtrlRegs.PIEIER3.bit.INTx1=1; //PIE级∶使能 PIE组3中与 PWM1 对应的中断使能位
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
}
__interrupt void pwm_isr (void)
{
Open_FOC_contral();
EPwm1Regs.ETCLR.bit.INT =1; //手动清零一次INT
PieCtrlRegs.PIEACK.all=PIEACK_GROUP3;
}
/*-----------------------<PWM相关函数>-------------------------------------------------------------------------*/
FOC.c文件中进行占空比修改
此处代码插入到开环FOC控制函数的计算完各上桥臂占空比之后的位置。
Tu=Fu/Ts;Tv=Fv/Ts;Tw=Fw/Ts;
EPwm1Regs.CMPA.bit.CMPA = (EPwm1Regs.TBPRD+1)* (1-Tu);//占空比设定
EPwm2Regs.CMPA.bit.CMPA = (EPwm2Regs.TBPRD+1)* (1-Tv);//占空比设定
EPwm3Regs.CMPA.bit.CMPA = (EPwm3Regs.TBPRD+1)* (1-Tw);//占空比设定
/*以上为PWM占空比修改过程*/
main.c文件中进行初始化
/**
* main.c
*/
#include "F28x_Project.h"
#include "IQmathLib.h"
#include "FOC.h"
#include "PWM.h"
int main(void)
{
InitSysCtrl();
DINT;
InitPieCtrl();
IER=0x0000;
IFR=0x0000;
InitPieVectTable();
DELAY_US(1000L);
EPWM1_int();
EINT; //使能全局中断
ERTM;
while (1)
{
}
}
至此,将所有代码进行编译,下载,此时电机就已经能够旋转起来了!