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.

[参考译文] TMS320F28377D:28377d ADC+DMA

Guru**** 2030840 points
Other Parts Discussed in Thread: CONTROLSUITE, C2000WARE
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/683810/tms320f28377d-28377d-adc-dma

器件型号:TMS320F28377D
Thread 中讨论的其他器件:controlSUITEC2000WARE

在 controlSUITE 中有关 ADC_DMA 的新版本示例中。 我有一个问题。如果我想在重复按 RESUME button.no时连续刷新缓冲区中的数据、而不是只执行一次。我该怎么办?谢谢

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

    您好、Jiang、

    您能给我指一下您所指的示例吗?

    谢谢

    Vasudha

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

    谢谢、以下是代码

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

    //

    //文件: adc_soc _continuous_dma_cpu01.c

    //

    //标题: ADC 连续转换由 DMA 为 F2837xD 读取。

    //

    //! addtogroup cpu01_example_list

    //!

    DMA 读取的 ADC 连续转换(ADC_SoC_Continuous_DMA)

    //!

    //! 此示例设置两个 ADC 通道以同时转换。 。

    //! 结果将由 DMA 传输到 RAM 中的缓冲区中。

    //!

    //! 程序运行后、存储器将包含:

    //!

    //! -\b adcData0 \b:引脚 A3\n 上电压的数字表示

    //! -\b adcData1 \b:引脚 B3\n 上电压的数字表示

    //!

    //

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

    //$TI 发行版:F2837xD 支持库 v3.04.00.00 $

    //$Release Date:Sun Mar 25 13:26:04 CDT 2018 $

    //版权所有:

    //版权所有(C) 2013-2018 Texas Instruments Incorporated -

    //

    //以源代码和二进制形式重新分发和使用,有无

    //如果满足以下条件,则允许进行修改

    //满足:

    //

    // 重新分发源代码必须保留上述版权

    // 注意、此条件列表和以下免责声明。

    //

    // 二进制形式的重新分发必须复制上述版权

    // 注意、中的条件列表和以下免责声明

    // 随提供的文档和/或其他材料  

    // 分布。

    //

    // 德州仪器公司的名称和的名称都不是

    // 其贡献者可用于认可或推广衍生产品

    // 未经特定的事先书面许可,从该软件下载。

    //

    //本软件由版权所有者和作者提供

    //“原样”以及任何明示或暗示的保证,包括但不包括

    //限于对适销性和适用性的暗示保证

    //一个特定的目的是免责的。 在任何情况下、版权均不得

    //所有者或贡献者应对任何直接、间接、偶然、

    //特殊、典型或必然的损害(包括但不包括)

    //仅限于采购替代货物或服务;

    //数据或利润;或业务中断)

    //责任理论,无论是合同责任、严格责任还是侵权行为

    //(包括疏忽或其他)以任何方式因使用而产生

    //此软件,即使已被告知可能会发生此类损坏。

    //$

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

    //

    //包含的文件

    //

    #include "F28x_Project.h"

    //

    //函数原型

    //

    _interrupt void adca1_ISR (void);

    _interrupt void dmach1_isr (void);

    void ConfigureEPWM (void);

    void ConfigureADC (void);

    void SetupADCContinuid (volatile struct adc_regs * adcRegs、uint16通道);

    void DMAInit (void);

    //

    //定义

    //

    #define Results_buffer_size 1024  //用于存储转换结果的缓冲器

                      //(大小必须是16的倍数)

    //

    //全局

    //

    #pragma DATA_SECTION (adcData0、"ramgs0");

    #pragma DATA_SECTION (adcData1、"ramgs0");

    uint16 adcData0[results_buffer_size];

    uint16 adcData1[results_buffer_size];

    易失性 uint16完成;

    void main (void)

      uint16结果索引;

    //

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

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

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

    //

      InitSysCtrl();

    //

    //步骤2. 初始化 GPIO:

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

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

    //

      InitGpio();

    //

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

    //禁用 CPU 中断

    //

      Dint;

    //

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

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

    //被清除。

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

    //

      InitPieCtrl();

    //

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

    //

      IER = 0x0000;

      IFR = 0x0000;

    //

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

    //服务例程(ISR)。

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

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

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

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

    //

      InitPieVectTable();

    //

    //设置此示例使用的 ISR

    //

    针对 ADCA INT1的// ISR -在首次转换后发生

    针对 DMA CH1的// ISR -在 DMA 传输完成时发生

    //

      EALLOW;

      PieVectTable.ADCA1_INT =&adca1_ISR;

      PieVectTable.DMA_CH1_INT =&dmach1_ISR;

      EDIS;

    //

    //启用特定的 CPU 中断:用于 ADC 的 INT1和用于 DMA 的 INT7

    //

      IER |= M_INT1;

      IER |= M_INT7;

    //

    //启用特定的 PIE 中断

    //

    // ADCA INT1 -组1,中断1

    // DMA 中断-组7,中断1

    //

      PieCtrlRegs.PIEIER1.bit.INTx1 = 1;

      PieCtrlRegs.PIEIER7.bit.INTx1 = 1;

    //

    //停止 ePWM 时钟

    //

      EALLOW;

      CpuSysRegs.PCLKCR0.bit.TBCLKSYNC=0;

      EDIS;

    //

    //调用 ePWM 2的设置功能

    //

      ConfigureEPWM();

    //

    //启动 ePWM 时钟

    //

      EALLOW;

      CpuSysRegs.PCLKCR0.bit.TBCLKSYNC=1;

      EDIS;

    //

    //配置 ADC 并为其加电

    //

      ConfigureADC();

    //

    //在通道 A3和 B3上设置用于连续转换的 ADC

    //

      SetupADCContinuimal(&AdcRegs, 3);

      SetupADCContinuimal(&AdcbRegs, 3);

    //

    //初始化 DMA

    //

      DMAInit();

    //

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

    //

      EINT; //启用全局中断 INTM

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

    //

    //初始化结果缓冲区

    //

      for (resultsIndex = 0;resultsIndex < results_buffer_size;resultsIndex++)

      {

        adcData0[resultsIndex]= 0;

        adcData1[resultsIndex]= 0;

      }

    //

    //清除所有挂起的中断标志

    //

      EALLOW;

      DmaRegs.ch1.control.bit.PERINTCLR = 1;

      DmaRegs.ch2.control.bit.PERINTCLR = 1;

      AdcaRegs.ADCINTFLGCLR.ALL = 0x3;

      AdcbRegs.ADCINTFLGCLR.ALL = 0x3;

      EPwm2Regs.ETCNTINITCTL.bit.SOCAINITFRC= 1;

      EPwm2Regs.ETCLR.bit.SOCA = 1;

    //

    //通过将最后一个 SOC 设置为重新触发第一个 SOC 来启用连续操作

    //

      AdcaRegs.ADCINTSOCSEL1.bit.SOC0 = 2;

      AdcbRegs.ADCINTSOCSEL1.bit.SOC0 = 2;

      EDIS;

    //

    //启动 DMA

    //

      完成= 0;

      StartDMACH1();

      StartDMACH2();

    //

    //最后,从 ePWM 启用 SOCA 触发器。 这将启动

    在下一个 ePWM 事件上进行//转换。

    //

      EPwm2Regs.ETSEL.bit.SOCAEN = 1;

    //

    //循环、直到 ISR 发出传输完成的信号

    //

      while (done = 0)

      {

        _asm (" NOP");

      }

      ESTOP0;

    //

    // adca1_ISR -这在第一次转换后调用并将禁用

    //       以避免重新触发问题。

    //

    #pragma CODE_SECTION (adca1_ISR、".TI.ramfunc");

    _interrupt void adca1_ISR (void)

      //

      //删除 ePWM 触发器

      //

      EPwm2Regs.ETSEL.bit.SOCAEN = 0;

      //

      //禁止再次发生此中断

      //

      PieCtrlRegs.PIEIER1.bit.INTx1 = 0;

      //

      //确认

      //

      PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;

    //

    // dmach1_ISR -在 DMA 传输、转换结束时调用

    //        通过从中删除第一个 SOC 的触发器来停止

    //        最后一个。

    //

    #pragma CODE_SECTION (dmach1_ISR、".TI.ramfunc");

    _interrupt void dmach1_ISR (void)

      //

      //通过移除 SOC0的触发器来停止 ADC

      //

      EALLOW;

      AdcaRegs.ADCINTSOCSEL1.bit.SOC0 = 0;

      AdcbRegs.ADCINTSOCSEL1.bit.SOC0 = 0;

      EDIS;

      DONE = 1;

      //

      //确认

      //

      PieCtrlRegs.PIEACX.ALL = PIEACK_group7;

    //

    // ConfigureEPWM -设置 ePWM2模块,使 A 输出具有一个周期

    //         占空比为50%。 SOCA 信号与保持一致

    //         它的上升沿。

    //

    空配置 EPWM (空)

      //

      //使计时器计数的周期为40us

      //

      EPwm2Regs.TBCTL.ALL = 0x0000;

      EPwm2Regs.TBPRD = 4000;

      //

      //将 A 输出设置为零并在 CMPA 上复位

      //

      EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;

      EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;

      //

      //将 CMPA 设置为20us 以获得50%的占空比

      //

      EPwm2Regs.CMPA.bit.CMPA = 2000;

      //

      //在计时器等于零时启动 ADC (注:尚未启用)

      //

      EPwm2Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO;

      EPwm2Regs.ETPS.bit.SOCAPRD = ET_1ST;

      //

      //启用 SOCA 事件计数器的初始化。 因为我们是这样

      //禁用 ETSEL.SOCAEN 位,我们需要一种复位 SOCACNT 的方法。

      // Hence、启用计数器初始化控制。

      //

      EPwm2Regs.ETCNTINITCTL.bit.SOCAINITEN = 1;

    //

    // ConfigureADC -写入 ADC 配置并为两者加电

    //         ADC A 和 ADC B

    //

    空配置 ADC (空)

      EALLOW;

      //

      //写入预分频配置

      //

      AdcaRegs.ADCCTL2.bit.prescale = 6;//将 ADCCLK 分频器设置为/4

      AdcbRegs.ADCCTL2.bit.prescale = 6;

      //

      //设置模式

      //

      AdcSetMode (ADC_ADCA、ADC_resolution_12位、ADC_SIGNALMODE_SINGLE);

      AdcSetMode (ADC_ADCB、ADC_Resolution、12位、ADC_SIGNALMODE_SINGLE);

      //

      //将脉冲位置设置为晚期

      //

      AdcaRegs.ADCCTL1.bit.INTPULSEPOS=1;

      AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;

      //

      //为 ADC 加电

      //

      AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;

      AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;

      //

      //延迟1ms 以允许 ADC 有时间上电

      //

      DELAY_US (1000);

      EDIS;

    //

    // SetupADCContinuously -设置 ADC 在一个通道上持续转换

    //

    void SetupADCContinuid (volatile struct adc_regs * adcRegs、uint16通道)

      uint16 acqps;

      //

      //根据分辨率确定最小采集窗口(在 SYSCLKS 中)

      //

      if (adc_resolution_12bit = AdcaRegs.ADCCTL2.bit.resolution)

      {

        acqps = 14;// 75ns

      }

      否则//分辨率为16位

      {

        acqps = 63;// 320ns

      }

      EALLOW;

      //

      // SOC 将在同一指定通道上转换

      //

      adcRegs->ADCSOC0CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC1CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC2CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC3CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC4CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC5CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC6CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC7CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC8CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC9CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC10CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC11CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC12CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC13CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC14CTL.bit.CHSEL =通道;

      adcRegs->ADCSOC15CTL.bit.CHSEL =通道;

      //

      //采样窗口为 acqps + 1个 SYSCLK 周期

      //

      adcRegs->ADCSOC0CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC1CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC2CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC3CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC4CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC5CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC6CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC7CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC9CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC10CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC11CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC12CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC13CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC14CTL.bit.ACQPS = acqps;

      adcRegs->ADCSOC15CTL.bit.ACQPS = acqps;

      //

      //从 EPWM2SOCA 触发 SCO0

      //

      adcRegs->ADCSOC0CTL.bit.TRIGSEL = 7;

      //

      //从 INT1触发所有其他 SOC (SOC0上的 EOC)

      //

      adcRegs->ADCINTSOCSEL1.bit.SOC1 = 1;

      adcRegs->ADCINTSOCSEL1.bit.SOC2 = 1;

      adcRegs->ADCINTSOCSEL1.bit.SOC3 = 1;

      adcRegs->ADCINTSOCSEL1.bit.SOC4 = 1;

      adcRegs->ADCINTSOCSEL1.bit.SOC5 = 1;

      adcRegs->ADCINTSOCSEL1.bit.SOC6 = 1;

      adcRegs->ADCINTSOCSEL1.bit.SOC7 = 1;

      adcRegs->ADCINTSOCSEL2.bit.SOC8 = 1;

      adcRegs->ADCINTSOCSEL2.bit.SOC9 = 1;

      adcRegs->ADCINTSOCSEL2.bit.SOC10 = 1;

      adcRegs->ADCINTSOCSEL2.bit.SOC11 = 1;

      adcRegs->ADCINTSOCSEL2.bit.SOC12=1;

      adcRegs->ADCINTSOCSEL2.bit.SOC13 = 1;

      adcRegs->ADCINTSOCSEL2.bit.SOC14 = 1;

      adcRegs->ADCINTSOCSEL2.bit.SOC15 = 1;

      adcRegs->ADCINTSEL1N2.bit.INT1E = 1;  //启用 INT1标志

      adcRegs->ADCINTSEL1N2.bit.INT2E = 1;  //启用 INT2标志

      adcRegs->ADCINTSEL3N4.bit.INT3E = 0;  //禁用 INT3标志

      adcRegs->ADCINTSEL3N4.bit.INT4E = 0;  //禁用 INT4标志

      adcRegs->ADCINTSEL1N2.bit.INT1CONT = 1;

      adcRegs->ADCINTSEL1N2.bit.INT2CONT = 1;

      adcRegs->ADCINTSEL1N2.bit.INT1SEL = 0; // SOC0结束

      adcRegs->ADCINTSEL1N2.bit.INT2SEL = 15;// SOC15结束

      EDIS;

    //

    // DMAInit -初始化 DMA 通道1以将 ADCA 结果和 DMA 通道2传输到

    //      传输 ADCB 结果

    //

    空 DMAInit (空)

      //

      //初始化 DMA

      //

      DMAInitialize();

      //

      //为第一个 ADC 设置 DMA

      //

      DMACH1AddrConfig (adcData0、&AdcResultRegs.ADCRESULT0);

      //

      //执行足够的16字突发来填充结果缓冲区。 数据将是

      //一次传输32位,因此地址步进如下。

      //

      //启用 DMA 通道1中断

      //

      DMACH1BurstConfig (15、2、2);

      DMACH1TransferConfig ((results_buffer_size >> 4)- 1、-14、2);

      DMACH1ModeConfig (

                DMA_ADCAINT2、

                PERINT_ENABLE、

                OneShot_disable、

                CONT_DISABLE、

                SYNC_DISABLE、

                SYNC_SRC、

                OVRFLOW_DISABLE、

                三十二位、

                Chint_end、

                Chint_enable

              );

      //

      //为第二个 ADC 设置 DMA

      //

      DMACH2AddrConfig (adcData1、&AdcbResultRegs.ADCRESULT0);

      //

      //执行足够的16字突发来填充结果缓冲区。 数据将是

      //一次传输32位,因此地址步进如下。

      //

      DMACH2BurstConfig (15、2、2);

      DMACH2TransferConfig (((results_buffer_size >> 4)- 1、-14、2);

      DMACH2ModeConfig (

                DMA_ADCAINT2、

                PERINT_ENABLE、

                OneShot_disable、

                CONT_DISABLE、

                SYNC_DISABLE、

                SYNC_SRC、

                OVRFLOW_DISABLE、

                三十二位、

                Chint_end、

                Chint_disable

              );

    //

    //文件结束

    //

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

    e2e.ti.com/.../continous_5F00_adc_5F00_dma_5F00_capture.c

    您好、Jiang、

    很抱歉耽误你的回答。 请查找随附的用于执行连续转换的更新代码。 基本上、当前示例删除了 DMA ISR 中的 SOC0触发器并将 DONE 置为1、应从示例中删除该触发器。 此外、还应为 DMA 启用连续模式。 请告诉我这是否解决了您的问题。

    此示例是 C2000Ware 的一部分、因此会造成混淆。

    谢谢

    Vasudha

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

    Vasudha.非常感谢。它工作正常。我可以在 DMA 中更新数组中的值。但我遇到了另一个问题。当我在 ADC 中调整16位模式的代码时。该值始终定期在特殊位中保持相同的值。例如 adcResultx[8] adcResultx[24] adcultx[40] adcResultx[72] adcResultrx[56] 、 Resultrx[56] adcResultx[72] 始终为42286。因此数组的图形不能是 continuous.it、这不是一个平滑的图形、每16个数字就会损坏一次。顺便说一下、我只能在"  AdcSetMode (ADC_ADCA、ADC_Resolution _12bit、 ADC_SIGNALMODE_SINGLE);"对于16位 ADC、我将12位更改为16位、将 SIGNALMODE 更改为 DIFFRERNTMODE。我认为是在12位 ADC 上探测 caused.no。所以我有 confused.ca、您会给我一些建议吗?