该文档记述了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 = de***step,传输一
个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);
- }
复制代码
|