28335 使用DMA存储ADC结果

2019-07-22 14:06发布

本帖最后由 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;
  1. #include "DSP2833x_Device.h"     // Headerfile Include File
  2. #include "DSP2833x_Examples.h"

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

  5. volatile Uint16 *DMADest;
  6. volatile Uint16 *DMASource;


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

  9. void pwmset();
  10. void adcset();
  11. void dmaset();
  12. interrupt void dma();
  13. interrupt void adcx();



  14. interrupt void adcx()
  15. {if(j>10)
  16. {EPwm1Regs.ETSEL.bit.SOCAEN=0;
  17. j=0;
  18.         }
  19. DmaRegs.CH1.CONTROL.bit.PERINTFRC=1;
  20.         jieguo[0][j]=((AdcRegs.ADCRESULT0)>>4);
  21. jieguo[1][j]=((AdcRegs.ADCRESULT1)>>4);


  22. j++;

  23. AdcRegs.ADCTRL2.bit.RST_SEQ1=1;
  24. PieCtrlRegs.PIEACK.bit.ACK1=1;
  25. AdcRegs.ADCST.bit.INT_SEQ1_CLR=1;
  26. EINT;
  27. }




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

  32. //StartDMACH1();
  33. }


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

  38. EPwm1Regs.TBCTL.bit.FREE_SOFT=1;
  39. EPwm1Regs.TBCTL.bit.CLKDIV=1;//sys/12
  40. EPwm1Regs.TBCTL.bit.HSPCLKDIV=3;
  41. EPwm1Regs.TBCTL.bit.PRDLD=0;
  42. EPwm1Regs.TBCTL.bit.PHSEN=0;
  43. EPwm1Regs.TBCTL.bit.CTRMODE=0;
  44. EPwm1Regs.ETSEL.bit.SOCAEN=1;
  45. EPwm1Regs.ETSEL.bit.SOCASEL=2;
  46. EPwm1Regs.ETSEL.bit.SOCBEN=0;
  47. EPwm1Regs.ETPS.bit.SOCAPRD=1;

  48.         
  49. }

  50. void adcset()
  51. {InitAdc();
  52. AdcRegs.ADCTRL1.bit.ACQ_PS=1;
  53. AdcRegs.ADCTRL1.bit.CONT_RUN=0;
  54. AdcRegs.ADCTRL1.bit.CPS=1;
  55. AdcRegs.ADCTRL1.bit.SEQ_CASC=1;

  56. AdcRegs.ADCTRL2.bit.EPWM_SOCB_SEQ=0;
  57. AdcRegs.ADCTRL2.bit.RST_SEQ1=1;
  58. AdcRegs.ADCTRL2.bit.SOC_SEQ1=0;
  59. AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1=1;
  60. AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1=0;
  61. AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1=1;
  62. AdcRegs.ADCTRL2.bit.EXT_SOC_SEQ1=0;
  63. AdcRegs.ADCTRL3.bit.SMODE_SEL=0;
  64. AdcRegs.ADCTRL3.bit.ADCCLKPS=3;//

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




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

  70. AdcRegs.ADCMAXCONV.bit.MAX_CONV1=2;
  71.         }

  72. void dmaset()
  73. {
  74.         DMAInitialize();

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

  81. EALLOW;

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

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

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

  99.         EDIS;



  100. }




  101. void main()
  102. {
  103.         InitSysCtrl();
  104.         DINT;
  105.         InitPieCtrl();
  106.         IER = 0x0000;
  107.         IFR = 0x0000;
  108.         InitPieVectTable();
  109.         EALLOW;        // Allow access to EALLOW protected registers
  110.              PieVectTable.DINTCH1= &dma;
  111.         //     PieVectTable.ADCINT=&adcx;
  112.         EDIS;
  113.          IER |= M_INT7 ;
  114.         // IER|=M_INT1;

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



  117.          for(i=0;i<60;i++)
  118.                    DMABuf1[i]=i;
  119.          for(i=0;i<4000;i++);
  120.          pwmset();
  121.          adcset();
  122.          dmaset();
  123.          EINT;

  124.          EPwm1Regs.ETSEL.bit.SOCAEN=1;

  125.          StartDMACH1();

  126.          while(1);
  127. }
复制代码

0条回答

一周热门 更多>