本帖最后由 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);
}
|