This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器/TMS320F28027:将 ADC 值传递给 PWM 以更改占空比

Guru**** 2601585 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/676459/compiler-tms320f28027-pass-adc-value-to-pwm-for-change-of-duty-cycle

器件型号:TMS320F28027

工具/软件:TI C/C++编译器

尊敬的先生:

请说明如何将 ADC 输出传递到 PWM 函数 InitEPwm2Examples(VV)以更改占空比。

我的 ADC 和 epwm2分别运行正常。 我无法从函数返回值

中断 void ADC_ISR (void)、即使它更改为中断 float ADC_ISR (void)。 返回值不能传递给 main 函数。 此外、如果我在  中断 void ADC_ISR (void)中插入 InitEPwm2Example (Volt)、该中断也不起作用。  

// TI 文件$Revision:/main/4 $

//  PWM+ADC

//  $end_Boot_Table

//

//######################################################################################################################

 

#include "DSP28x_Project.h"    //器件头文件和示例 include 文件

中断 ADC_ISR ();

void ADC_Config (void);//Where defined?

//此示例中使用的全局变量:

uint16环计数;

UINT16转换计数;

uint16 Voltage1[10];

uint16 Voltage2[10];

浮动电压;

 

//此文件中找到的函数的原型语句。

 

中断 void epwm1_tzint_isr (void);

中断 void epwm2_tzint_isr (void);

 

 

//此示例中使用的全局变量

uint32 EPwm1TZIntCount;

uint32 EPwm2TZIntCount;

 

 

MAIN ()

//步骤1. 初始化系统控制:

// PLL、安全装置、启用外设时钟

//此示例函数位于 DSP2802x_SYSCTRL.c 文件中。

  InitSysCtrl()

 

//步骤2. 初始化 GPIO:

//此示例函数位于 DSP2802x_GPIO.c 文件和中

//说明了如何将 GPIO 设置为其默认状态。

// InitGpio();//针对此示例跳过

 

//在这种情况下、只需为 ePWM1、ePWM2和 TZ 引脚初始化 GPIO 引脚

// InitEPwm1Gpio();

  InitEPwm2Gpio()

  InitTzGpio()

 

//步骤3. 清除所有中断并初始化 PIE 矢量表:

//禁用 CPU 中断

  Dint;

 

//将 PIE 控制寄存器初始化为默认状态。

//默认状态为禁用所有 PIE 中断和标志

//被清除。

//此函数位于 DSP2802x_PIECTRL.c 文件中。

  InitPieCtrl()

 

//禁用 CPU 中断并清除所有 CPU 中断标志:

  IER = 0x0000;

  IFR = 0x0000;

 

//使用指向 shell 中断的指针初始化 PIE 矢量表

//服务例程(ISR)。

//这将填充整个表,即使是中断也是如此

//在本例中未使用。 这对于调试很有用。

//可以在 DSP2802x_DefaultIsr.c 中找到 shell ISR 例程

//此函数可在 DSP2802x_PieVect.c 中找到

  InitPieVectTable()

 

//此示例中使用的中断被重新映射到

//此文件中的 ISR 函数。

  EALLOW;//这是写入 EALLOW 受保护寄存器所必需的

// PieVectTable.EPWM1_TZINT =&epwm1_tzint_ISR;

  PieVectTable.EPWM2_TZINT =&epwm2_tzint_ISR;

  PieVectTable.ADCINT1 =&ADC_ISR;

  EDIS;  //这是禁止写入 EALLOW 受保护寄存器所必需的

 

//步骤4. 初始化所有器件外设:

//此函数位于 DSP2802x_InitPeripherals.c 中

// InitPeripherals ();//此示例不需要

  InitAdc ();//对于此示例,初始化 ADC

 

  //在 PIE 中启用 ADCINT1

    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;     //在 PIE 中启用 INT 1.1

    IER |= M_INT1;                                       //启用 CPU 中断1

    EINT;                                               //启用全局中断 INTM

    ERTM;                                               //启用全局实时中断 DBGM

 

    LoopCount = 0;

    ConversionCount = 0;

 

 

 

  EALLOW;

  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   = 4;  //将 SOC0通道选择设置为 ADCINA4

     AdcRegs.ADCSOC1CTL.bit.CHSEL   = 2;  //将 SOC1通道选择设置为 ADCINA2

     AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5;  //设置 SOC0在 EPWM1A 上启动触发器,因为轮询 SOC0先转换,然后 SOC1

     AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5;  //设置 EPWM1A 上的 SOC1启动触发器,因为轮询 SOC0先转换,然后 SOC1

     AdcRegs.ADCSOC0CTL.bit.ACQPS   = 6;  //将 SOC0 S/H 窗口设置为7个 ADC 时钟周期(6个 ACQPS 加1)

     AdcRegs.ADCSOC1CTL.bit.ACQPS   = 6;  //将 SOC1 S/H 窗口设置为7个 ADC 时钟周期、

 

  SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC=0;

  EDIS;

  //假设 ePWM1时钟已在 InitSysCtrl()中启用;

    EPwm1Regs.ETSEL.bit.SOCAEN = 1;         //启用组上的 SOC

    EPwm1Regs.ETSEL.bit.SOCASEL      = 4;         //从 CPMA 中选择 SOC、以进行递增计数

    EPwm1Regs.ETPS.bit.SOCAPRD      = 1;         //在发生第一个事件时生成脉冲

    EPwm1Regs.CMPA.half.CMPA = 0x0080;   //设置比较值

    EPwm1Regs.TBPRD                        = 0xFFFF;   //为 ePWM1设置周期

    EPwm1Regs.TBCTL.bit.CTRMODE     = 0;         //向上计数并启动

 

 

 

    // InitEPwm1Examples();

  // vol=Voltage1[ConversionCount]*3.3/4096;

    InitEPwm2Examples(3.3);

 

  EALLOW;

  SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC=1;

  EDIS;

 

//步骤5. 特定于用户的代码、启用中断

//初始化计数器:

//  EPwm1TZIntCount = 0;

  EPwm2TZIntCount = 0;

 

//启用连接到 EPWM1-3 INT 的 CPU INT3:

  IER |= M_INT2;

 

//在 PIE 中启用 ePWM INTn:组2中断1-3

  PieCtrlRegs.PIEIER2.bit.INTx1 = 1;

  PieCtrlRegs.PIEIER2.bit.INTx2 = 1;

 

//启用全局中断和更高优先级的实时调试事件:

  EINT;  //启用全局中断 INTM

  ERTM;  //启用全局实时中断 DBGM

 

 

 

//步骤6. 空闲循环。 只需坐下来循环(可选):

  for (;;)

  {

      asm ("        NOP");

  }

 

 

中断 epwm1_tzint_isr ()

  EPwm1TZIntCount++;

 

//将这些标志保留为设置,这样我们就只接受它

//中断一次

//

// EALLOW;

// EPwm1Regs.TZCLR.bit.OST = 1;

// EPwm1Regs.TZCLR.bit.INT = 1;

// EDIS;

 

  //确认此中断以接收来自组2的更多中断

  PieCtrlRegs.PIEACX.ALL = PIEACK_group2;

 

 

中断 epwm2_tzint_ISR ()

 

  EPwm2TZIntCount++;

 

//清除标记-我们将继续执行

//此中断直到 TZ 引脚变为高电平

//

  EALLOW;

  EPwm2Regs.TZCLR.bit.CBC = 1;

  EPwm2Regs.TZCLR.bit.INT = 1;

  EDIS;

 

  //确认此中断以接收来自组2的更多中断

  PieCtrlRegs.PIEACX.ALL = PIEACK_group2;

 

 

 

InitEPwm1Examples()

  //启用 TZ1和 TZ2作为单次触发源

  EALLOW;

  EPwm1Regs.TZSEL.bit.OSHT1 = 1;

  EPwm1Regs.TZSEL.bit.OSHT2=1;

 

  //我们希望 TZ1和 TZ2执行什么操作?

  EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_HI;

  EPwm1Regs.TZCTL.bit.TSB = TZ_FORCE_LO;

 

  //启用 TZ 中断

  EPwm1Regs.TZEINT.bit.OST = 1;

  EDIS;

 

  EPwm1Regs.TBPRD = 6000;                        //设置定时器周期

  EPwm1Regs.TBPHS.Half.TBPHS = 0x0000;          //相位为0

  EPwm1Regs.TBCTR = 0x0000;                      //清除计数器

 

  //设置 TBCLK

  EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;//向上计数

  EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;      //禁用相位加载

  EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV4;      //时钟与 SYSCLKOUT 的比率

  EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV4;

 

  EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADODE;  //每0加载一次寄存器

  EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

  EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;

  EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

 

  //设置比较

  EPwm1Regs.CMPA.half.CMPA = 3000;

 

  //设置操作

  EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;            //将 PWM1A 设置为零

  EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;

 

 

  EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR;        //将 PWM1A 设置为零

  EPwm1Regs.AQCTLB.bit.CAD = AQ_SET;

 

 

 

InitEPwm2Examples(浮点 x)

 

  //启用 TZ1和 TZ2作为一个逐周期触发源

  EALLOW;

  EPwm2Regs.TZSEL.bit.CBC1 = 1;

  EPwm2Regs.TZSEL.bit.CBC2 = 1;

 

  //我们希望 TZ1和 TZ2执行什么操作?

  EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_HI;

  EPwm2Regs.TZCTL.bit.TSB = TZ_FORCE_LO;

 

  //启用 TZ 中断

  EPwm2Regs.TZEINT.BIT.CBC = 1;

  EDIS;

 

  EPwm2Regs.TBPRD = 6000;                      //设置定时器周期

  EPwm2Regs.TBPHS.Half.TBPHS = 0x0000;          //相位为0

  EPwm2Regs.TBCTR = 0x0000;                    //清除计数器

 

  //设置 TBCLK

  EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;//向上计数

  EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;      //禁用相位加载

  EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV4;      //时钟与 SYSCLKOUT 的比率

  EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV4;        //慢、只在示波器上观察

 

  //设置比较

  EPwm2Regs.CMPA.half.CMPA = 6000/x;

 

  //设置操作

  EPwm2Regs.AQCTLA.bit.CAU = AQ_SET;            //将 PWM2A 设置为零

  EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR;

 

 

  EPwm2Regs.AQCTLB.bit.CAU = AQ_CLEAR;          //将 PWM2A 设置为零

  EPwm2Regs.AQCTLB.bit.CAD = AQ_SET;

 

中断 ADC_ISR ()

 

Voltage1[ConversionCount]= AdcResult.ADCRESULT0;

Voltage2[ConversionCount]= AdcResult.ADCRESULT1;

//vol=Voltage1[ConversionCount]*3.3/4096;

//如果记录了20次转换,则重新开始

if (ConversionCount = 9)

    ConversionCount = 0;

else ConversionCount++;

 

AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;      //清除 ADCINT1标志为下一个 SOC 重新初始化

PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;  //确认 PIE 中断

 

返回;

 

 

 

//============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

//不再需要。

//============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Deepak、您好!

    中断函数、至少如 C28x 编译器中定义的那样、需要为 void 返回类型。
    为此、您可以参阅编译器用户指南的第6.5.3节"_interrupt Keyword"。 www.ti.com/.../spru514p.pdf

    此致、
    Elizabeth