打印

28335 使用DMA存储ADC结果

[复制链接]
1785|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhangleiii|  楼主 | 2016-6-19 21:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ADC, DMA, ST, se, TE
本帖最后由 zhangleiii 于 2016-6-19 21:13 编辑

该文档记述了ADC在使用EPWM1的SOCA触发情况下,用DMA直接将Result0-16搬到存储区的方法。此方法而不需要使用ADC中断来存出结果,从而节约了CPU资源。使用该方法需注意以

下几点:
   1.DMA是从Result0-16的映射区取转化结果,即DMASource= &AdcMirror.ADCRESULT0;
   2.目的地址需要在RAML4-RAML7,即#pragma DATA_SECTION(DMABuf1,"DMARAML4");DMABuf1是目的变量名,即DMADest=&DMABuf1[0];
   3.DMA如果采用SEQ1触发,需将SEQ1的中断打开,即AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1=1;但是不需要手动清除SEQ1的中断标志,ADC工作在启停模式下,每次转化完成后也不

需要复位排序器,即不需要每次设置AdcRegs.ADCTRL2.bit.RST_SEQ1=1;因为DMA每次存储后他会自动清除中断标志和复位排序器。
   4.DMA传输结果时,对于原地址和目的地址的移动主要通过三种方式来执行,
   1)burst传输;burst传输是由每一个ADC中断标志触发,ADC每次转化完成,该传输模式启动,原地址和目的地址的移动通过计数方式执行,首先要告诉原地址的首地址,即

DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (Uint32)DMA_Source;= &AdcMirror.ADCRESULT0;其次得告知每次出发传输多少数据,即DmaRegs.CH1.BURST_SIZE.all = bsize,如bsize=9,

就是一次burst传输10个数据;然后要告诉下次发送数据的地址和接收数据的地址,即DmaRegs.CH1.SRC_BURST_STEP = srcbstep;DmaRegs.CH1.DST_BURST_STEP = desbstep,传输一

个16位或32位数据,将执行一次地址偏移(原地址的首地+DmaRegs.CH1.SRC_BURST_STEP和目的首地址+DmaRegs.CH1.DST_BURST_STEP), DmaRegs.CH1.BURST_SIZE.all也将减1,

当 DmaRegs.CH1.BURST_SIZE.all=0时,本次burst传输完成。
   2)transfer传输,transfer传输有两个功能。一是确定多少次transfer传输后来执行DMA中断,二是确定下次burst传输的原首地址和目的首地址,他都是在上一次burst传输完

成后,源和目的地址的基础上进行偏移,transfer传输由三个寄存器管理,DmaRegs.CH1.TRANSFER_SIZE = tsize;
他告诉DSP多少次burst传输,执行DMA中断一次,如tsize=9,就是10次burst传输中断一次。DmaRegs.CH1.SRC_TRANSFER_STEP = srctstep;这个寄存器告诉DSP下次burst传输的源

首地址,他是在上次burst传输的最后一个源数据的地址上进行偏移;DmaRegs.CH1.DST_TRANSFER_STEP = deststep,这个寄存器告诉DSP下次burst传输的目的首地址,他是在上次

burst传输的最后一个目的地址上进行偏移;
   3)wrap传输,可实现循环传输,DmaRegs.CH1.SRC_WRAP_SIZE = srcwsize;是指源burst传输srcwsize+1后,源地址就要返回,下次burst传输源的首地址为

DmaRegs.CH1.SRC_ADDR_SHADOW +DmaRegs.CH1.SRC_WRAP_STEP;DmaRegs.CH1.SRC_ADDR_SHADOW是本轮wrap传输DmaRegs.CH1.SRC_BEG_ADDR_SHADOW的映射寄存器值,

DmaRegs.CH1.SRC_WRAP_STEP为wrap传输源的首地址偏移量。DmaRegs.CH1.DST_WRAP_SIZE = deswsize;是指burst传输deswsize+1后,目的地址就要返回,下次burst传输目的首地

址为DmaRegs.CH1.DST_ADDR_SHADOW+DmaRegs.CH1.DST_WRAP_STEP;DmaRegs.CH1.DST_ADDR_SHADOW,是本轮wrap传输DmaRegs.CH1.DST_ADDR_SHADOW的映射寄存器值,

DmaRegs.CH1.DST_WRAP_STEP为传输目的首地址偏移量(transfer传输,DmaRegs.CH1.DST_TRANSFER_STEP是相对于最受一个数据的地址偏移量)。所以wrap传输和transfer传输二

选一与burst传输搭配即可。要想屏蔽wrap传输,需将DmaRegs.CH1.SRC_WRAP_SIZE和DmaRegs.CH1.DST_WRAP_SIZE的值设定的比DmaRegs.CH1.TRANSFER_SIZE大。
   5.即使在使用wrap传输时,只要burst传输次数达到DmaRegs.CH1.TRANSFER_SIZE,在DMA中断开启的情况下,DMA还是会进入中断。
   6.在非持续模式下,如果想在某段地址内采用覆盖式存储,需在中断内对源和目的首地址重新赋值,并要重新令DmaRegs.CH1.CONTROL.bit.RUN = 1。
   7.在持续模式下,如果想在某段地址内采用覆盖式存储,只需在中断内对源和目的首地址重新赋值。

  下面以ADC 6通道,转化50次一次中断为例,来配置地址偏移。
采用transfer传输:
DMACH1AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source);
DMACH1BurstConfig(5,1,50);
DMACH1TransferConfig(49,-5,-250+1);
DMACH1WrapConfig(100,100,100,100);//禁止wrap传输
采用wrap传输
DMACH1AddrConfig(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source);
DMACH1BurstConfig(5,1,50);
DMACH1WrapConfig(0,0,5,1);
DMACH1TransferConfig(49,0,0)//如果要50次一中断,DmaRegs.CH1.TRANSFER_SIZE =49;
#include "DSP2833x_Device.h"     // Headerfile Include File
#include "DSP2833x_Examples.h"

#pragma DATA_SECTION(DMABuf1,"DMARAML4");
volatile Uint16 DMABuf1[60];

volatile Uint16 *DMADest;
volatile Uint16 *DMASource;


Uint16 jieguo[3][10];
Uint16 i=0,j=0;

void pwmset();
void adcset();
void dmaset();
interrupt void dma();
interrupt void adcx();



interrupt void adcx()
{if(j>10)
{EPwm1Regs.ETSEL.bit.SOCAEN=0;
j=0;
        }
DmaRegs.CH1.CONTROL.bit.PERINTFRC=1;
        jieguo[0][j]=((AdcRegs.ADCRESULT0)>>4);
jieguo[1][j]=((AdcRegs.ADCRESULT1)>>4);


j++;

AdcRegs.ADCTRL2.bit.RST_SEQ1=1;
PieCtrlRegs.PIEACK.bit.ACK1=1;
AdcRegs.ADCST.bit.INT_SEQ1_CLR=1;
EINT;
}




interrupt void dma()
{j++;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
DMADest=&DMABuf1[0];

//StartDMACH1();
}


void pwmset()
{EPwm1Regs.TBPRD=50;//4us;
EPwm1Regs.TBCTR=0;
EPwm1Regs.TBPHS.all=0;

EPwm1Regs.TBCTL.bit.FREE_SOFT=1;
EPwm1Regs.TBCTL.bit.CLKDIV=1;//sys/12
EPwm1Regs.TBCTL.bit.HSPCLKDIV=3;
EPwm1Regs.TBCTL.bit.PRDLD=0;
EPwm1Regs.TBCTL.bit.PHSEN=0;
EPwm1Regs.TBCTL.bit.CTRMODE=0;
EPwm1Regs.ETSEL.bit.SOCAEN=1;
EPwm1Regs.ETSEL.bit.SOCASEL=2;
EPwm1Regs.ETSEL.bit.SOCBEN=0;
EPwm1Regs.ETPS.bit.SOCAPRD=1;

        
}

void adcset()
{InitAdc();
AdcRegs.ADCTRL1.bit.ACQ_PS=1;
AdcRegs.ADCTRL1.bit.CONT_RUN=0;
AdcRegs.ADCTRL1.bit.CPS=1;
AdcRegs.ADCTRL1.bit.SEQ_CASC=1;

AdcRegs.ADCTRL2.bit.EPWM_SOCB_SEQ=0;
AdcRegs.ADCTRL2.bit.RST_SEQ1=1;
AdcRegs.ADCTRL2.bit.SOC_SEQ1=0;
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1=1;
AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1=0;
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1=1;
AdcRegs.ADCTRL2.bit.EXT_SOC_SEQ1=0;
AdcRegs.ADCTRL3.bit.SMODE_SEL=0;
AdcRegs.ADCTRL3.bit.ADCCLKPS=3;//

AdcRegs.ADCTRL3.bit.SMODE_SEL=0;
AdcRegs.ADCTRL3.bit.ADCCLKPS=3;//12.5Mh;




AdcRegs.ADCCHSELSEQ1.bit.CONV00=2;
AdcRegs.ADCCHSELSEQ1.bit.CONV01=11;
AdcRegs.ADCCHSELSEQ1.bit.CONV02=13;

AdcRegs.ADCMAXCONV.bit.MAX_CONV1=2;
        }

void dmaset()
{
        DMAInitialize();

DMADest=&DMABuf1[0];
DMASource= &AdcMirror.ADCRESULT0;
DMACH1AddrConfig(DMADest,DMASource);
DMACH1BurstConfig(2,1,20);
DMACH1TransferConfig(19,0,0);
DMACH1WrapConfig(0,0,0,1);//no use wrap;

EALLOW;

        // Set up MODE Register:
        DmaRegs.CH1.MODE.bit.PERINTSEL =1;            // Passed DMA channel as peripheral interrupt source
        DmaRegs.CH1.MODE.bit.PERINTE = PERINT_ENABLE;               // Peripheral interrupt enable
        DmaRegs.CH1.MODE.bit.ONESHOT = ONESHOT_DISABLE;               // Oneshot enable
        DmaRegs.CH1.MODE.bit.CONTINUOUS =1;                    // Continous enable
        DmaRegs.CH1.MODE.bit.SYNCE = SYNC_DISABLE;                 // Peripheral sync enable/disable
        DmaRegs.CH1.MODE.bit.SYNCSEL = SYNC_SRC;               // Sync effects source or destination
        DmaRegs.CH1.MODE.bit.OVRINTE = OVRFLOW_DISABLE;         // Enable/disable the overflow interrupt
        DmaRegs.CH1.MODE.bit.DATASIZE =SIXTEEN_BIT;              // 16-bit/32-bit data size transfers
        DmaRegs.CH1.MODE.bit.CHINTMODE = CHINT_END ;                // Generate interrupt to CPU at beginning/end of transfer
        DmaRegs.CH1.MODE.bit.CHINTE =CHINT_ENABLE  ;                // Channel Interrupt to CPU enable

        // Clear any spurious flags:
        DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1;                  // Clear any spurious interrupt flags
        DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1;                    // Clear any spurious sync flags
        DmaRegs.CH1.CONTROL.bit.ERRCLR = 1;                      // Clear any spurious sync error flags

        // Initialize PIE vector for CPU interrupt:
               // Enable DMA CH1 interrupt in PIE

        EDIS;



}




void main()
{
        InitSysCtrl();
        DINT;
        InitPieCtrl();
        IER = 0x0000;
        IFR = 0x0000;
        InitPieVectTable();
        EALLOW;        // Allow access to EALLOW protected registers
             PieVectTable.DINTCH1= &dma;
        //     PieVectTable.ADCINT=&adcx;
        EDIS;
         IER |= M_INT7 ;
        // IER|=M_INT1;

        // PieCtrlRegs.PIEIER1.bit.INTx6=1;
         PieCtrlRegs.PIEIER7.bit.INTx1=1;



         for(i=0;i<60;i++)
                   DMABuf1[i]=i;
         for(i=0;i<4000;i++);
         pwmset();
         adcset();
         dmaset();
         EINT;

         EPwm1Regs.ETSEL.bit.SOCAEN=1;

         StartDMACH1();

         while(1);
}


相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

3

帖子

0

粉丝