主题中讨论的其他器件:controlSUITE、 C2000WARE、 MOTORWARE
工具/软件:Code Composer Studio
您好!
我最近购买了'Experimenter's Kit - Piccolo F28069'、并开始为永磁电机的三相电流控制器准备代码。 因此、我想使用 EPwm1的中断来读取三个 ADC 通道(读取两相电流和直流链路电压)并执行电流控制(从而修改 PWM 的占空比)。
到目前为止、我已经尝试收集代码来配置 PWM 和 ADC 以及配置其他 GPIO 引脚。 我最初设法点亮 controlCARD 上的 LD2和 LD3 (在 PWM 中断之外)、然后、我想开始在 PWM 中断中执行代码。 我在 PWM 中断中添加的第一行(名为 ePWM1A_ISR)是关闭 LD3。 但是、当我运行代码时、LD3永远不会关闭。 因此、似乎从未触发 PWM 中断(我已经将 PWM 中断设置为以1kHz 更新频率(我认为)触发)。
您能不能帮助我了解如何触发 PWM 中断。 下面是我执行的代码。 请注意、我对这一点非常陌生、在收集来自各种 TI 来源的不同代码段时、可能会误解这些内容。 因此、我所做的评论也可能是错误的、因此我们也希望大家能对改进代码的任何其他评论有所改进。
此致、
Oskar Wallmark
代码(main.c):
//目标配置:
//板或器件:实验板套件- Piccolo F28069 (包括 Piccolo F2806x controlCARD)
//连接:德州仪器 XDS100v1 USB 调试探针
//模数转换器(ADC)将从0V 转换为3.3V,并将其缩放为0--4096
//这假设 Piccolo F2806x controlCARD 上标记为 SW2的两个开关
//设置为其向下位置(向下位置=开关最靠近 DIMM100引脚)
//F28069controlCARD_InfoSheet.pdf 中对此进行了说明
//Piccolo F2806x controlCARD 的引导选项通过标记为 SW1的开关进行设置
//F28069controlCARD_InfoSheet.pdf 中对此进行了说明
//在 Piccolo F2806x controlCARD 上、连接了以下 LED (如"F28069controlCARD_InfoSheet.pdf"中所述)
//LD1 (绿色 LED)–在 controlCARD 通电时亮起
//LD2 (红色 LED)–由 GPIO-31控制
//LD3 (红色 LED)–由 GPIO-34控制
//CCS 工作区路径(在 Window/Preferences/General/Workspace 下选中):
//C:\Users\OWa\Documents\Work\Teaching and Courses \EMaDLab converter\ccs_workspaces\TemplateProjects
//包括位置:
//C:\ti\ccsv8\tools\compiler\ti-cgt-C2000_18.1.4.LTS \include (编译器需要)
//C:\ti\controlSUITE\device_support\f2806x\v151\F2806x_common\include (需要包含"DSP28x_Project.h")
//C:\ti\controlSUITE\device_support\f2806x\v151\F2806x_headers\include (需要包含"DSP28x_Project.h")
//要包括在项目中的文件:
//28069_RAM_lnk.cmd //存储器块特定的链接器命令文件
//F2806x_CodeStartBranch.asm //共享源代码
//F2806x_CpuTimers.c //共享源代码
//F2806x_DefaultIsr.c //共享源代码
//F2806x_GlobalVariableDefs.c //使用头文件需要此源文件
//F2806x_Headers_nonBIOS.cm //Linker 文件、外设特定听说的文件需要该文件
//F2806x_PIECTRL.c //共享源代码
//F2806x_PieVect.c //共享源代码
//F2806x_sysctrl.c //共享源代码
//F2806x_usDelay.asm //共享源代码
#include "DSP28x_Project.h"//此头文件包括 F2806x_Device.h 和 F2806x_Examples.h
#include "math.h"//以便能够执行数学运算(sin、cos、sqrt 等)
浮点 ADC0 = 0.0;//浮点变量用于存储 ADC 的 ADC0输入
浮点 ADC1 = 0.0;//浮点变量用于存储 ADC 的 ADC1输入
浮点 ADC2 = 0.0;//浮点变量用于存储 ADC 的 ADC2输入
extern void InitSysCtrl(void);
extern void InitPieVectTable (void);
extern void InitPieCtrl (void);
void ReadAdc (void);
中断空 ePWM1A_ISR (空);
void configureEPwm (void);
//在向上向下计数模式中,PWM 周期 TS 的时间(以秒为单位)计算为 TS=2*ePWM_PRD*TBCLK。
//Hence、ePWM_PRD = TS/(2*TBCLK)。 相应的 PWM 频率(以 Hz 为单位) Fs 由 Fs = 1/Ts 给出。
//另请参阅"TMS320x280x、2801x、2804x 增强型脉宽调制器(ePWM) Module.pdf"中的图2-3
//微处理器 TMS320F28069的运行频率为 fClock = 90MHz。
//TBCLK = 2/fClock = 22.2ns、其中与2的乘法在 configureEPwm ()中设置
//示例:对于 fs = 10kHz --> ePWM_PRD = 1/(FS*2*TBCLK)= 1/(10e3*2*2/(90e6))= 2250
//fs = 1kHz -> ePWM_PRD = 22500
//fs = 5kHz -> ePWM_PRD = 4500
//fs = 10kHz -> ePWM_PRD = 2250
//fs = 20kHz -> ePWM_PRD = 1125
#define ePWM_PRD 22500 // PWM 周期[#个时钟周期]
//去带周期时间(以秒为单位) TDB 的计算公式为 TDB = ePWM_DB*TBCLK
//示例:对于 TDB = 0.2e-6s,ePWM_DB = TDB/TBCLK = 0.2e-6/(2/90e6)= 0.1e-6*90e6 = 0.25*90= 9
//TDB = 0.2e-6 s->ePWM_DB = 9
//TDB = 0.4e-6 s->ePWM_DB = 18
//TDB = 0.8e-6 s->ePWM_DB = 36
#define ePWM_DB 18 //去带周期[#时钟周期]
//引脚映射("F2806_GPIO.h"中描述的不同 GPIO 引脚的寄存器定义)
//GPIO0 ->EPWM1A (在 InitEPwm1Gpio()中设置)
//GPIO1-->EPWM1B (在 InitEPwm1Gpio()中设置)
//GPIO2 ->EPWM2A (在 InitEPwm2Gpio()中设置)
//GPIO3 ->EPWM2B (在 InitEPwm2Gpio()中设置)
//GPIO4 ->EPWM3A (在 InitEPwm3Gpio()中设置)
//GPIO5 ->EPWM3B (在 InitEPwm3Gpio()中设置)
//GPIO31控制 Piccolo F2806x controlCARD 上的 LD2 (红色 LED)
//GPIO34控制 Piccolo F2806x controlCARD 上的 LD3 (红色 LED)
//GPIO20 --> EQEP1A (eQEP 输入)(在 InitEQep1Gpio ()中设置)
//GPIO21 --> EQEP1B (eQEP 输入)(在 InitEQep1Gpio ()中设置)
//GPIO22 --> EQEP1S (eQEP 选通)(在 InitEQep1Gpio()中设置)
//GPIO23 --> EQEP1I (eQEP 索引)(在 InitEQep1Gpio()中设置)
//使用的模拟输入引脚:
//ADCINA0 -->已激活
//ADCINA1 -->已激活
//ADCINA2 -->已激活
main (空)
{
InitSysCtrl();//将系统控制寄存器初始化为已知状态。
//-禁用看门狗
//将 PLLCR 设置为正确的 SYSCLKOUT 频率
//设置高频和低频外设时钟的预分频器
//启用到外设的时钟
DINT;//禁用所有可屏蔽的 CPU 中断(可屏蔽的 CPU 中断是可以抑制的中断)
InitPieCtrl();//将 PIE 控制寄存器初始化为已知状态
//禁用 CPU 中断并清除所有 CPU 中断标志:
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();//将 PIE 矢量表初始化为已知状态。
//此示例中使用的中断被重新映射到此文件中的 ISR 函数。
EALLOW;//启用对受保护寄存器的写入访问
PieVectTable.EPWM1_INT =&ePWM1A_ISR;
EDIS;//禁用对受保护寄存器的写入访问
InitEQep1Gpio();//将 GPIO20-GPIO23配置为用作 eQEP 引脚
InitEPwm1Gpio();//将 GPIO0-GPIO1配置为用作 EPwm1引脚(并禁用所选 GPIO 引脚的内部上拉)
InitEPwm2Gpio();//将 GPIO2-GPIO3配置为用作 EPwm2引脚(并禁用所选 GPIO 引脚的内部上拉)
InitEPwm3Gpio();//将 GPIO4-GPIO5配置为用作 EPwm3引脚(并禁用所选 GPIO 引脚的内部上拉)
configureEPwm();//配置 EPwm1、EPwm2和 EPwm3通道(EPwm2和 EPwm3与 EPwm1同步)
//配置用于控制 Piccolo F2806x controlCARD 上的 LD2 (红色)的 GPIO31
EALLOW;//启用对受保护寄存器的写入访问
GpioCtrlRegs.GPAPUD.bit.GPIO31 = 1;//1 ->禁用 GPIO31上的上拉电阻(GPIO0-GPIO31 -> GPAPUD (请参阅"F2806_GPIO.h"))
GpioCtrlRegs.GPADIR.bit.GPIO31 = 1;//1 -> GPIO31成为输出引脚(GPIO0-GPIO31 -> GPADIR (请参阅"F2806_GPIO.h"))
GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 0;//GPIO16-GPIO31 -> GPAMUX2 (请参阅"F2806_GPIO.h")
GpioDataRegs.GPADAT.bit.GPIO31 = 0;//0 -> LD2亮起、1 -> LD2未亮起(GPIO0-GPIO31 -> GPADAT (请参阅"F2806_GPIO.h"))
EDIS;//禁用对受保护寄存器的写入访问
//配置用于控制 Piccolo F2806x controlCARD 上的 LD3 (红色)的 GPIO34
EALLOW;//启用对受保护寄存器的写入访问
GpioCtrlRegs.GPBPUD.bit.GPIO34 = 1;//1 ->禁用 GPIO34 (GPIO32-GPIO63)上的上拉电阻器-> GPBPUD (请参阅"F2806_GPIO.h")
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1;//1->GPIO34成为输出引脚(GPIO32-GPIO63)->GPBDIR (请参阅"F2806_GPIO.h")
GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;//GPIO32-GPIO47 --> GPBMUX2 (请参阅"F2806_GPIO.h")
GpioDataRegs.GPBDAT.bit.GPIO34 = 0;//0 -> LD3亮起、1 -> LD3未亮起(GPIO32-GPIO63 -> GPBDAT (请参阅"F2806_GPIO.h"))
EDIS;//禁用对受保护寄存器的写入访问
/*
//在 GPIO8上启用 GPIO 输出(取自"Example_2806xGpioSetup.c")
//EALLOW;//启用对受保护寄存器的写入访问
GpioCtrlRegs.GPAPUD.bit.GPIO8 = 0;//启用 GPIO8上的上拉电阻
GpioDataRegs.GPASET.BIT.GPIO8 = 1;//加载输出锁存(默认情况下、该引脚处于输入模式、且借助上拉使能、输出将为'1'。 如果您将引脚的方向更改为输出、则会将其驱动为"0"。 通过在改变方向前将输出锁存器加载为"1"、引脚上的值在引脚被配置为输出后保持为"1"。)
GpioCtrlRegs.GPAMUX1.bit.GPIO8=0;//GPIO8=GPIO8
GpioCtrlRegs.GPADIR.bit.GPIO8 = 1;//1 -> GPIO8成为输出引脚
//EDIS;//禁用对受保护寄存器的写入访问
//启用 GPIO34中的 GPIO 输入(取自"Example_2806xGpioSetup.c")
//EALLOW;//启用对受保护寄存器的写入访问
GpioCtrlRegs.GPBPUD.bit.GPIO34 = 0;//启用 GPIO34上的上拉
GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;//GPIO34 = GPIO34
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 0;//0 -> GPIO34成为输入引脚
//EDIS;//禁用对受保护寄存器的写入访问
*
InitAdc();//将 ADC 初始化为已知状态
AdcOffsetSelfCal ();//重新校准 ADC 零偏移误差
//EALLOW;//启用对受保护寄存器的写入访问
//SysCtrlRegs.WDCR = 0x00AF;//重新启用看门狗
//EDIS;//禁用对受保护寄存器的写入访问
IER |= 4;//启用 CPU 中断1
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;//在 PIE 中启用 ePWM INTn:组3中断1-6
//启用全局中断和更高优先级的实时调试事件:
EINT;//启用全局中断 INTM
ERTM;//启用全局实时中断 DBGM
//配置 ADC
在"TMS320x2806x Piccolo 技术参考指南(修订版 G).pdf"的表8-18中列出了用于选择特定触发源的 TRIGSEL 值
用于选择特定 ADC 输入通道的 CHSEL 的值也列在"TMS320x2806x Piccolo 技术参考指南(修订版 G).pdf"的表8-18中。
EALLOW;//启用对受保护寄存器的写入访问
AdcRegs.ADCCTL2.bit.ADCNONOVERLAP = 1;//启用非重叠模式
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1;//ADCINT1在 AdcResults 锁存后跳闸
AdcRegs.INTSEL1N2.bit.INT1E = 1;//启用 ADCINT1
AdcRegs.INTSEL1N2.bit.INT1CONT = 0;//禁用 ADCINT1连续模式
AdcRegs.INTSEL1N2.bit.INT1SEL = 1;//设置 EOC1以触发 ADCINT1触发
AdcRegs.ADCSOC0CTL.bit.CHSEL = 0;//将 SOC0通道选择设置为 ADCINA0
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5;//设置 SOC0在 EPWM1A 上启动触发器,因为轮询 SOC0先转换,然后 SOC1
AdcRegs.ADCSOC0CTL.bit.ACQPS = 6;//将 SOC0 S/H 窗口设置为7个 ADC 时钟周期(6个 ACQPS 加1)
AdcRegs.ADCSOC1CTL.bit.CHSEL = 1;//将 SOC1通道选择设置为 ADCINA1
AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5;//设置 EPWM1A 上的 SOC1启动触发器,因为轮询 SOC0先转换,然后 SOC1
AdcRegs.ADCSOC1CTL.bit.ACQPS = 6;//将 SOC1 S/H 窗口设置为7个 ADC 时钟周期(6个 ACQPS 加1)
AdcRegs.ADCSOC2CTL.bit.CHSEL = 3;//将 SOC2通道选择设置为 ADCINA2
AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5;//设置 EPWM1A 上的 SOC2启动触发器,因为轮询 SOC0先转换,然后 SOC1
AdcRegs.ADCSOC2CTL.bit.ACQPS = 6;//将 SOC2 S/H 窗口设置为7个 ADC 时钟周期、(6个 ACQPS 加1)
EDIS;//禁用对受保护寄存器的写入访问
//等待中断
for (;;)
{
}
}// main 结束(void)
void configureEPwm()
{
///EPwm1Regs (主 PWM 模块)
EPwm1Regs.TBPRD = ePWM_PRD;//PWM 周期
EPwm1Regs.TBPHS.Half.TBPHS = 0x0000;//将相位寄存器设置为零
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;//向上向下计数模式
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;//禁用相位加载(用作主 PWM 模块)
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;//同步下流模块
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;// CTR 上的负载=零
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;// CTR 上的负载=零
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;//设置操作
EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;//启用死区模块
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;//高电平有效互补
EPwm1Regs.DBFED = ePWM_DB;//去带周期(下降沿)
EPwm1Regs.DBRED = ePWM_DB;//去带周期(上升沿)
EPwm1Regs.CMPA.half.CMPA =(ePWM_PRD*0.5);//初始占空比设置为50%
EPwm1Regs.TBCTL.ALL = 0;//默认值
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;//TB_DIV1 -> CLKDIV = 1
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;//TB_DIV2 -> TBCLK = SYSCLKOUT/(2*CLKDIV)= SYSCLKOUT/2 (因为 CLKDIV 被设定为1)
EPwm1Regs.TBCTL.bit.PHSDIR = TB_DOWN;
EPwm1Regs.AQCTLA.ALL = 0x0060;//CMPA UP =设置;CMPA DOWN =清除
EPwm1Regs.ETSEL.ALL = 0;
EPwm1Regs.ETSEL.bit.INTEN = 1;//启用 ePWM1 int (仅在主 PWM 模块中置1)
EPwm1Regs.ETSEL.bit.INTSEL = 5;//CMPA 向下匹配
EPwm1Regs.ETPS.bit.INTPRD = 1;//1st 事件
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;//ePWM1
EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;
///EPwm2Regs (从 PWM 模块)
EPwm2Regs.TBPRD = ePWM_PRD;//PWM 周期
EPwm2Regs.TBPHS.Half.TBPHS = 0x0000;//将相位寄存器设置为零
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;//向上向下计数模式
EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE;//启用相位加载(用作从 PWM 模块)
EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;//同步直通
EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;// CTR 上的负载=零
EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;// CTR 上的负载=零
EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;//设置操作
EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR;
EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FUL_ENABLE;//启用死区模块
EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;//高电平有效互补
EPwm2Regs.DBFED = ePWM_DB;//去带周期(下降沿)
EPwm2Regs.DBRED = ePWM_DB;//去带周期(上升沿)
EPwm2Regs.CMPA.half.CMPA =(ePWM_PRD*0.5);//初始占空比设置为50%
EPwm2Regs.TBCTL.ALL = 0;//默认值
EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;//TB_DIV1 -> CLKDIV = 1
EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;//TB_DIV2 -> TBCLK = SYSCLKOUT/(2*CLKDIV)= SYSCLKOUT/2 (因为 CLKDIV 被设定为1)
EPwm2Regs.TBCTL.bit.PHSDIR = TB_DOWN;
EPwm2Regs.AQCTLA.ALL = 0x0060;//CMPA UP =设置;CMPA DOWN =清除
EPwm2Regs.ETSEL.ALL = 0;
EPwm2Regs.DBCTL.bit.IN_MODE = DBA_ALL;
///EPwm3Regs (从 PWM 模块)
EPwm3Regs.TBPRD = ePWM_PRD;//PWM 周期
EPwm3Regs.TBPHS.Half.TBPHS = 0x0000;//将相位寄存器设置为零
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;//向上向下计数模式
EPwm3Regs.TBCTL.bit.PHSEN = TB_ENABLE;//启用相位加载(用作从 PWM 模块)
EPwm3Regs.TBCTL.bit.PRDLD = TB_SHADOW;
EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;//同步直通
EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;// CTR 上的负载=零
EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;// CTR 上的负载=零
EPwm3Regs.AQCTLA.bit.CAU = AQ_SET;//设置操作
EPwm3Regs.AQCTLA.bit.CAD = AQ_CLEAR;
EPwm3Regs.DBCTL.bit.OUT_MODE = DB_FUL_ENABLE;//启用死区模块
EPwm3Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;//高电平有效互补
EPwm3Regs.DBFED = ePWM_DB;//去带周期(下降沿)
EPwm3Regs.DBRED = ePWM_DB;//去带周期(上升沿)
EPwm3Regs.CMPA.half.CMPA =(ePWM_PRD*0.5);//初始占空比设置为50%
EPwm3Regs.TBCTL.ALL = 0;//默认值
EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;//TB_DIV1 -> CLKDIV = 1
EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;//TB_DIV2 -> TBCLK = SYSCLKOUT/(2*CLKDIV)= SYSCLKOUT/2 (因为 CLKDIV 被设定为1)
EPwm3Regs.TBCTL.bit.PHSDIR = TB_DOWN;
EPwm3Regs.AQCTLA.ALL = 0x0060;//CMPA UP =设置;CMPA DOWN =清除
EPwm3Regs.ETSEL.ALL = 0;
EPwm3Regs.DBCTL.bit.IN_MODE = DBA_ALL;
}// void configureEPwm()结束
空 readadc ()
{
ADC0 = AdcResult.ADCRESULT0;
ADC1 = AdcResult.ADCRESULT1;
ADC2 = AdcResult.ADCRESULT2;
}// void readAdc()结束
中断空 ePWM1A_ISR (空)
{
//这里是实际的控制代码
readadC();
EALLOW;//启用对受保护寄存器的写入访问
GpioDataRegs.GPBDAT.bit.GPIO34 = 1;//0 -> LD3亮起、1 -> LD3未亮起(GPIO32-GPIO63 -> GPBDAT (请参阅"F2806_GPIO.h"))
EDIS;//禁用对受保护寄存器的写入访问
EPwm1Regs.ETCLR.bit.INT = 1;//清除该计时器的中断标志
PieCtrlRegs.PIEACK.all = PIEACK_Group3;//确认此中断以接收来自组3的更多中断
}//中断结束 void ePWM1A_ISR (void)