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.

[参考译文] CCS/TMS320F28335:通过 ADC_ISR 和 ePWM_ISR 对 CMPA 寄存器进行连续更新的问题

Guru**** 2537080 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/611307/ccs-tms320f28335-issues-with-cmpa-register-contiuous-update-via-adc_isr-and-epwm_isr

器件型号:TMS320F28335

工具/软件:Code Composer Studio

您好!

我尝试处理 ADC_SoC 示例。 我计划生成 ADC_ISR 和 ePWM_ISR、这样 ADC_ISR 将为我提供平均10次连续读取、而 ePWM_ISR 将使用该平均值更新其 CMPA 寄存器。 代码看起来还可以 、但其性能相当糟糕。 我始终获得100%占空比。 就好像 cmpa 没有真正得到更新一样。 我已经反复遍读了代码、我根本不知道我哪里出错了... 但我觉得这个问题会很小。

顺便说一下、我在某个地方读出 ADC_ISR 的优先级高于 ePWM_ISR、 但是、由于 ADC 应由 ePWM SOCA 触发、这是否意味着在首次转换中、ADC 的输出将为零、因为它尚未合法触发、因此不会进行转换?

如果有任何建议和指示、我将不胜感激。

谢谢。

David

#include "DSP28x_Project.h" //设备头文件和示例包括文件

//此文件中找到的函数的原型语句。
_interrupt void ADC_ISR (void);
__interrupt void epwm4_ISR (void);
void GPIO_select (void);
//void Setup_ePWM1A (void);
//void Setup_ePWM2A (void);
//void Setup_ePWM3A (void);
void Setup_ePWM4A (void);
//本示例中使用的全局变量:
uint16 i;
uint16 LoopCount;
uint16 Voltage1[10];
float VoltageAve;

main ()
{
//步骤1。 初始化系统控制:
// PLL、看门狗、启用外设时钟
//此示例函数位于 DSP2833x_sysctrl.c 文件中。
InitSysCtrl();

EALLOW;
#IF (CPU_FRQ_150MHz) //默认- 150MHz SYSCLKOUT
#define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)= 25.0MHz
#endif
(CPU_FRQ_100MHz)
#define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)= 25.0MHz
#endif
EDIS;

//定义 ADCCLK 时钟频率(小于或等于25MHz)
//假设 InitSysCtrl()已将 SYSCLKOUT/




所有 ADCLK 设置为150MHz。 初始化 GPIO:
//此示例函数位于 DSP2833x_GPIO.c 文件中,
//说明了如何将 GPIO 设置为其默认状态。
// InitGpio();//针对本示例跳过
GPIO_select ();

//步骤3。 清除所有中断并初始化 PIE 矢量表:
//禁用 CPU 中断
DINT;

//将 PIE 控制寄存器初始化为默认状态。
//默认状态是禁用所有 PIE 中断并
清除标志//。
//此函数位于 DSP2833x_PIECTRL.c 文件中。
InitPieCtrl();

//禁用 CPU 中断并清除所有 CPU 中断标志:
IER = 0x0000;
IFR = 0x0000;

//使用指向 shell 中断
//服务例程(service routinese, ISR)的指针初始化 PIE 矢量表。
//这将填充整个表,即使在
本示例中未使用中断//也是如此。 这对于调试很有用。
//可以在 DSP2833x_DefaultIsr.c 中找到 shell ISR 例程
//此函数可在 DSP2833x_PieVect.c 中找到
InitPieVectTable();

//此示例中使用的中断被重新映射到
这个文件中的// ISR 函数。
EALLOW;//这是写入 EALLOW 受保护寄存
器 PieVectTable.ADCINT =&ADC_ISR;
PieVectTable.EPWM4_INT =&epwm4_ISR;
EDIS;//这是禁用写入 EALLOW 受保护寄存器

所必需的//步骤4。 初始化所有器件外设:
//此函数可在 DSP2833x_InitPeripherals.c
中找到// InitPeripherals ();//此示例
InitAdc ()不需要;//对于此示例,初始化 ADC

//步骤5。 用户特定代码、启用中断:

//在 PIE
PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
PieCtrlRegs.PIEIER3.bit.INTx4 = 1;
IER |= 5;//启用 CPU 中断1和3
EINT;//启用全局中断 INTM
ERTM;//启用全局实时中断 DBGM

LoopCount = 0;
//转换计数= 0;

//配置 ADC
AdcRegs.ADCMAXCONV.ALL = 0;//在 SEQ1上设置1个转换数- 1
个 AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x4;//将 ADCINA4设置为第一个 SEQ1转换数
AdcRegs.ADCTRL1.bit.ACQ_PS = 15;//多路复用器切换和样本冻结之间的时间
AdcRegs.ADCTRL1.bit.CONT_RUN = 1;//在第一次转换结束时重新开始全部等待另一个触发输入信号
AdcRegs.ADCTRL1.bit.SECLK=1MHz;ADCCLQ+ADCCLK=1MHz = ADCCLK+ADCCLK=1MHz;ADCCLK+ADCCLK=1MHz = ADCCLK+ADCCLK+ADCCLK=1MHz

//从 ePWM 启用 SOCA 以启动 SEQ1
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;//启用 SEQ1中断
AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0;//启用 SEQ1中断每个 EOS AdcRegs.ADCTRKPS.bit.SMOCLKS.bit.INCLK

= 0;//

启用 ADCMOCLK=0;// ADCTRL = 0 = ADCTRL = 0;// ADCTRL = ADCTRL = 0;ADCTRL = ADCK_= 0;ADCTRL = ADCTRL = 0;ADCTRL = ADCTRL = 0;// ADCTRL = ADCTRL = ADCK_= ADCTRL = 0;ADCTRL = ADCTRL = ADCK_=


//等待 ADC 中断
(;;)
{
LoopCount++;
}


}void GPIO_select (void)
{
EALLOW;
GpioCtrlRegs.GPAMUX1.ALL = 0;// GPIO15... GPIO0 =通用向




控制器 I/O //GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;//GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1;//GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1;GpioX1.Gpio1.GAMUX2.Gpio1.GAMUX2.Gpio1.GAMU6 = 1;GPAMUX1.Gpio1.Gpio1.Gpio1.Gpio1.GAMU2.GAMU2.GAMUX2.GAMUX1.GAM所有人 Gpio1.// GPIO31... GPIO16 =通用 I/O
GpioCtrlRegs.GPBMUX1.ALL = 0;// GPIO47... GPIO32 =通用 I/O
GpioCtrlRegs.GPBMUX2.ALL = 0;// GPIO63... GPIO48 =通用 I/O
GpioCtrlRegs.GPCMUX1.ALL = 0;// GPIO79... GPIO64 =通用 I/O
GpioCtrlRegs.GPCMUX2.ALL = 0;// GPIO87... GPIO80 =通用 I/O

GpioCtrlRegs.GPADIR.ALL = 0;
//GpioCtrlRegs.GPADIR.bit.GPIO0 = 1;//外设资源管理器:GPIO0上的 LED LD1
//GpioCtrlRegs.GPADIR.bit.GPIO2 = 1;//外设资源管理器:GPIO1.bit/GPIO1.4=GPIO1.r.piDIR
1
上的 LED LDO1.GPIO1.GPIO1.GPIO1.bit.GPIO1.GPIO1.GPIO1.GPIO1.bit.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1.GPIO1. GPIO6

GpioCtrlRegs.GPBDIR.ALL = 0;// GPIO63-32作为输入
GpioCtrlRegs.GPCDIR.ALL = 0;// GPIO87-64作为输入
EDIS;
}

_ mirror_interrupt void ADC_ISR (void)
{

for (i=0;i<10;i<10;i_volageAve

= 3*ADvoltagedr1+

);

// ADvoltvoltageR1+= 0[volt.ADC1+= 0* voltagedr1+;}
//重置 SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; //清除 INT SEQ1位
PieCtrlRegs.PIEACK.all = PIEACK_Group1;//确认中断以返回 PIE
;
}
__INTERRUPT void epwm4_ISR (void)
{
EPwm4Regs.CMPA.half.CMPA = VoltageAve*(EPwm4Regs.TBPRD);
//重新初始化下
一个 EPwm4Regs.TCLR 位;/EPwm4INT.Et //清除 INT SEQ1位
PieCtrlRegs.PIEACK.all = PIEACK_Group3;//确认中断以返回 PIE
;
}
void Setup_ePWM4A (void)
{
EPwm4Regs.TBCTL.bit.CLKDIV = 0;//SysClkOut/1 ie 默认
EPwm4Regs.TBCLT.TBRL =/SysClkOut/2 0


;/TBRDCTRL = 0;/TBIT.TBIT.TBIT.TBIG 位数= 0;/TBR4TBIT.TBIT.TBIG = 0;/TBIT.TBIT.TBIT.TBIG = 0;/TBIT.TBIT.TBIT.TBIG = 0//禁用同步输出选择
EPwm4Regs.TBPRD = 4989/22;//330kHz
EPwm4Regs.CMPA.half.CMPA = 0;//初始 CMPA = 0
EPwm4Regs.AQCTLA.all = 0x0012;//CTR = 0 (设置)、CTR = cmpa on up (up.EN.EPTL.TCASEL
= 0);EPwm4Regs.ePl = 0x0012 (EPmCtcmpa) //在组
EPwm4Regs.ETSEL.bit.SOCASEL = 1上启用 SOC; //从 CTR=0
EPwm4Regs.ETPS.bit.SOCAPRD =1选择 SOC; //在发生第一个事件
EPwm4Regs.ETSEL.bit.INTEN 时生成脉冲= 1; //启用 PWM 中断
EPwm4Regs.ETSEL.bit.INTSEL = 2; //在 CTR = PRD
EPwm4Regs.ETPS.bit.INTPRD = 1上启用中断; //第一个事件发生中断
} 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    我写信告诉您、C2000团队成员已被分配到此帖子、应该很快回答。

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

    尊敬的 David:

    关于 CMPA 更新问题、您是否已检查 Voltage1和 VoltageAve 变量是否按预期更新? 如果没有、您可以考虑为这些变量添加 volatile 关键字。
    您能否确认通过在 ISR 内部放置断点并查看是否达到断点来生成 ADC 和 ePWM ISR?

    此致、
    Elizabeth

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

    生成两个 ISR。 ADC_ISR 首先在10个循环前后、它转到 ePWM_ISR。

    此外、这两个变量都在更新中。

    我期待您的答复。

    此致。

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


    对于(i=0;i<10;i++)

    Voltage1[i]= AdcMirror.ADCRESULT0;
    VoltageAve += Voltage1[i];

    VoltageAve =(3*VoltageAve)/10/4096;

    我认为 AdcMirror.ADCRESULT0在求和间隔内不会发生变化、因此通过加10次除以10似乎是多余的。
    当 VoltageAve 从每个中断的开头开始时、看起来它有一个剩余值
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    非常感谢。

    1.遗留问题:我想我可以通过放置来解决这个问题  

    VoltageAve = 0; 

    在 for 循环之前。 我想我只是想它将被覆盖  

    Voltage1[i]= AdcMirror.ADCRESULT0; 

    也许我错了。

    2.关于多余的添加,我的计划是连续采集10个样本并对其求平均值,而不是仅接受单个样本而不进行查询。 也许我的方法是错误的、因为我不是一个真正有经验的程序员。

    您能就更好的方法向我提出建议吗?

    此致。

    David。

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

    尊敬的 David:

    我重点介绍 FPGA、而不是 C 语言编程、但因为您问:

    我的解释是 、AdcMirror.ADCRESULT0不会在求和周期内发生变化。

    你同意吗?  我的解释可能是错误的。

    通常、我不会回答会给我带来更多工作的问题、但情况并非总是如此。

    这是 example_2833xxfor.c 文件

    _interrupt void ADC_ISR (void)

    Voltage1[ConversionCount]= AdcRegs.ADCRESULT0 >> 4;
    Voltage2[ConversionCount]= AdcRegs.ADCRESULT1 >>4;

    //如果记录了40次转换,则重新开始
    if (ConversionCount = 9)

    ConversionCount = 0;

    其他

    ConversionCount++;

    //  插入开始

    //这可能不完全正确,并且尚未经过测试

    // TI 通常会这样做、他们将其称为箱车平均值。

    //它们有一条注释,指出它不是控制循环的一部分,而是用于 GUI

    VoltageAve = 0;

    for(i=0;i<10;i++)
      {
        VoltageAve += Voltage1[i];
      }
    VoltageAve = (3*VoltageAve)/10/4096;

    //*************************************** insert end

    //为下一个 ADC 序列重新初始化
    AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;//复位 SEQ1
    AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;//清除 INT SEQ1位
    PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;//确认 PIE 中断

    返回;

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

    非常感谢您的努力。
    谢谢你。
    我刚刚尝试编译更正后的代码、它一直说"无法识别的令牌"、我真的不知道原因! 我还会继续检查...
    此致。

    David。

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

    它可能需要
    UINT16转换计数;

    uint16 Voltage2[10];


    在本示例中使用的//全局变量之后:朝向文件顶部。

    或者您可以删除对 Voltage2的所有引用;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您的快速回答。
    我适当地添加了这些声明、事实上我只是编辑 ADC_SoC 示例。 我的代码完全有意义、通常应该运行、但我不知道为什么它一直说"无法识别的令牌"。
    David。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    此帖子建议添加-verbose_diagnostics 以查看其来源

    https://e2e.ti.com/support/development_tools/compiler/f/343/p/435084/1557966?tisearch=e2e-sitesearch&keymatch=*F283*%20unrecognized%20token#1557966

    也许、如果您从发布内容中剪切和粘贴代码到编辑器、一些有趣的字符会使编译器感到困惑。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我尝试添加-verbose_diagnostics、但它无法正常工作。 我建议不要使用它。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常感谢您的努力。
    我也一直在努力使它正常工作、但它还没有出现。 如果没有、可能我需要稳定使用这些值、因为这些值是不需要任何平均值计算的。
    此致。
    David。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我将代码片段放入 example_28xAdcc.c 中、并使用原始项目
    _interrupt void
    ADC_ISR (空)

    Voltage1[ConversionCount]= AdcRegs.ADCRESULT0 >> 4;
    Voltage2[ConversionCount]= AdcRegs.ADCRESULT1 >>4;

    //
    //如果记录了40次转换,则重新开始
    //
    if (ConversionCount = 9)

    ConversionCount = 0;

    其他

    ConversionCount++;


    // 插入开始

    //这可能不完全正确,并且尚未经过测试

    // TI 通常会这样做、他们将其称为箱车平均值。

    //它们有一条注释,指出它不是控制循环的一部分,而是用于 GUI

    VoltageAve = 0;

    对于(i=0;i<10;i++)

    VoltageAve += Voltage1[i];

    VoltageAve =(3*VoltageAve)/10/4096;
    //********* 插入端头
    //
    //为下一个 ADC 序列重新初始化
    //
    AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; //重置 SEQ1
    AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; //清除 INT SEQ1位
    PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;//确认 PIE 中断

    返回;


    我不得不说
    int i;
    浮点 VoltageAve;
    全局变量。

    它编译正常、但我无法运行它。

    从长远来看、我认为平均值计算不会产生很大的影响、因为它会使控制环路失真
    如果它包含在控制环路中。

    模拟滤波器恰好位于 A/D 之前、用于抗混叠和降噪
    可能是一种更好的方法。

    祝您好运!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常感谢。 我将导入另一个项目并重试。
    此致。
    David。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    David、
    应该会实现它
    volatile float VoltageAve;

    因此、编译器不会立即对其进行优化
    不会在任何地方使用
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    非常感谢。
    "易失性浮点"确实有帮助很多、但循环仍然无法正常工作
    我现在使用的是如下内容:

    VoltageAve = Voltage1[0]+Voltage1[1]+Voltage1[2]+Voltage1[3]+Voltage1[4]+Voltage1[5]+Voltage1[6]+Voltage1[7]+Voltage1[8]+Voltage1[9];


    我知道它非常粗糙、但我不知道为什么环路不能按预期工作。
    感谢您的所有努力。
    David。

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