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.

TMS320F280039: 如何配置使用timer1触发多路ADC SOC,并在ADC EOC时通过DMA传输到指定RAM区,4轮EOC DMA传输完毕后再触发DMA完成中断

Part Number: TMS320F280039

需求:

1. 使用timer1高频触发多路ADC SOC,但是timer1不用产生中断,自动重载触发采样,以节约CPU开销

2. ADC EOC时通过DMA传输到指定RAM区,4轮EOC DMA传输完毕后再触发DMA传输完成中断。同样的,期间不要触发ADC EOC完成中断,以节约CPU开销

实际撰写上述需求的代码时,发现第一点就无法实现,必须使能timer1中断才能有效触发ADC SOC。

请问上述需求是否可以在280039中实现?

  • timer1可以不在PIE中使能中断,这样应该可以触发ADC SOC,但是不触发CPU中断。不过还是建议用ePWM来做这个功能,它的ET模块可以配置成每四次ADC SOC触发一次CPU中断。

  • ePWM触发速度太慢,我需要采集在一个PWM周期内采集3次电流以得到更准确的平均电流。

    1. 使用timer1高频触发多路ADC SOC,但是timer1不用产生中断,自动重载触发采样,以节约CPU开销

    这个问题已经解决。

    目前出现了第二个问题,只有首次EOC触发了一次DMA搬运,后面EOC无法触发。

    官方提供的例程没有涉及到这类情况,我的DMA代码配置如下,帮忙看看是否有问题

    void configureDMAChannels(void)
    {
    DMA_clearTriggerFlag(DMA_CH1_BASE); // DMA channel 1
    DMA_clearTriggerFlag(DMA_CH2_BASE); // DMA channel 2

    // DMA channel 1 set up for ADCA
    DMA_configAddresses(DMA_CH1_BASE, (uint16_t *)&s_AdcaResult,
    (uint16_t *)ADCARESULT_BASE);

    //该通道单次搬运的DMA_CH1_ADC_NO个ADC结果,以及按多大步长的地址进行搬运,单位为16bit (ADC 结果寄存器为16bit,所以配置为1)
    DMA_configBurst(DMA_CH1_BASE, DMA_CH1_ADC_NO, 1, 1);

    //配置传输N(2 * ADC_OVER_SAMPLE_FACTOR)次,且每次搬运后如何对源地址和目标地址操作,源地址需要回退到ADCA-Result0,目的地址继续累加1
    DMA_configTransfer(DMA_CH1_BASE, 2 * ADC_OVER_SAMPLE_FACTOR, -DMA_CH1_ADC_NO + 1, 1);

    //DMA1的触发源为ADCA1中断标志位
    DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_ADCA1,
    (DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
    DMA_CFG_SIZE_16BIT));

    DMA_enableTrigger(DMA_CH1_BASE);
    DMA_disableOverrunInterrupt(DMA_CH1_BASE);
    DMA_setInterruptMode(DMA_CH1_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(DMA_CH1_BASE);

    // DMA channel 2 set up for ADCB
    DMA_configAddresses(DMA_CH2_BASE, (uint16_t *)&s_AdcbResult,
    (uint16_t *)ADCBRESULT_BASE);

    // Perform enough DMA_CH2_ADC_NO-word bursts to fill the results buffer. Data will be
    // transferred 16 bits at a time hence the address steps below.
    DMA_configBurst(DMA_CH2_BASE, DMA_CH2_ADC_NO, 1, 1);
    DMA_configTransfer(DMA_CH2_BASE, 2 * ADC_OVER_SAMPLE_FACTOR, -DMA_CH2_ADC_NO + 1, 1);
    DMA_configMode(DMA_CH2_BASE, DMA_TRIGGER_ADCB1,
    (DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
    DMA_CFG_SIZE_16BIT));

    DMA_enableTrigger(DMA_CH2_BASE);
    DMA_disableOverrunInterrupt(DMA_CH2_BASE);
    DMA_setInterruptMode(DMA_CH2_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(DMA_CH2_BASE);
    }

  • 1、没有调用DMA_startChannel();,可能你在其他地方配置了,如果没配置的话这儿需要配置。

    2、没看到DMA_configWrap代码,目前看来这个配置没法实现一轮Transfer后回退到最初始地址。

    另外我是用ePWM做的DMA触发,额外配置一路ePWM,将频率配置为你主PWM频率的倍数,这样就可以以固定倍数进行DMA触发了。你的主PWM可以设置触发中断,这样可以实现一个PWM周期内采样多次,并且只触发一次中断。下面是我之前的配置:

        EPwm3Regs.TBPRD = EPWMPeriod_DC;        
        EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;          
        EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
        EPwm3Regs.TBCTL.bit.PHSDIR = TB_UP;
        EPwm3Regs.TBCTL.bit.PRDLD = TB_SHADOW;
        EPwm3Regs.TBCTL.bit.PHSEN = TB_ENABLE;
        EPwm3Regs.TBPHS.bit.TBPHS = 0;
        EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;  
        EPwm3Regs.EPWMSYNCINSEL.bit.SEL = SYNC_IN_SRC_DISABLE_ALL;
        EPwm3Regs.EPWMSYNCOUTEN.bit.ZEROEN = SYNC_OUT_SRC_ENABLE;
        
        EPwm8Regs.TBPRD = EPWMPeriod_DC / 8;         
        EPwm8Regs.TBCTL.bit.CLKDIV = TB_DIV1;         
        EPwm8Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
        EPwm8Regs.TBCTL.bit.PHSDIR = TB_UP;
        EPwm8Regs.TBCTL.bit.PRDLD = TB_SHADOW;
        EPwm8Regs.TBCTL.bit.PHSEN = TB_ENABLE;
        EPwm8Regs.TBPHS.bit.TBPHS = 0;
        EPwm8Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;   
        EPwm8Regs.EPWMSYNCINSEL.bit.SEL = SYNC_IN_SRC_SYNCOUT_EPWM3;
        
        EPwm3Regs.ETSEL.bit.INTEN = 1;
        EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_PRD;
        EPwm3Regs.ETPS.bit.INTPRD = ET_1ST;
        
        EPwm8Regs.ETSEL.bit.SOCAEN = 1;
        EPwm8Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO;
        EPwm8Regs.ETPS.bit.SOCAPRD = ET_1ST;
        ////
    	ADC_setInterruptSource(myADCB_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER2);
    	////
        DMA_setEmulationMode(DMA_EMULATION_STOP);
        DMA_configAddresses(myDMA0_BASE, 5888, 2848);
        DMA_configBurst(myDMA0_BASE, 3U, 1, 16);
        DMA_configTransfer(myDMA0_BASE, 16U, -2, -31);
        DMA_configWrap(myDMA0_BASE, 16U, 0, 16U, 0);
        DMA_configMode(myDMA0_BASE, DMA_TRIGGER_ADCB1, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
        DMA_enableTrigger(myDMA0_BASE);
        DMA_startChannel(myDMA0_BASE);

    ePWM3作为主PWM,每个PWM周期内通过ePWM8触发采样,采样16次,每次采样3个信号:ADCB0,ADCB1,ADCB2。将ADCB0,ADCB1,ADCB2分别存于DMA_Data1,DMA_Data2,DMA_Data3中:
    DMA_Data1 : origin = 0x001700, length = 0x000010
    DMA_Data2 : origin = 0x001710, length = 0x000010
    DMA_Data3 : origin = 0x001720, length = 0x000010

  • 感谢。

    上周末刚发完,加班琢磨了很久后,使用timer触发的方案已经可以了,是因为我没有将

    AdcaRegs.ADCINTSEL1N2.bit.INT1CONT设置为1导致的。
    不过你的方案更优,因为pwm之间可以同步,采样时间控制更佳,今早已经按照你的方案又重新优化了一次