f28335ADC-DMA

f28335adc-dma转换。我用了八个adc采样口,顺序采样,DMA转换非级联模式,想着DMABuf1[0]-DMABuf1[4]保存第adcA0采样口的数据,DMABuf1[5]-DMABuf1[9]存adcA1采样口的数据,10 - 14保adcA2采样口的数据,15 - 19存adcA3采样口的数据,依次这样,八个采样口,每个采样5次。
配置的是DMACH1BurstConfig(7,1,5); DMACH1TransferConfig(4,-7,-40+1);DMACH1WrapConfig(100,100,100,100);

img

结果就是每个采样口都采集到一次数据,后面四次数据没有采集到。

程序如下:

#pragma DATA_SECTION(DMABuf1,"DMARAML4");

#define DMA_BUF_SIZE 40
volatile Uint16 DMABuf1[DMA_BUF_SIZE];


/*******************************************************************************
* 函 数 名         : main
* 函数功能           : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main()
{
    int i=0;


    InitSysCtrl();
    InitPieCtrl();
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();

    LED_Init();//这里面配置了GPIO初始化
    TIM0_Init(150,100);//中频炉最高5000Hz,每个周期需要调节两次,1/10000hz=100us
    UARTa_Init(4800);

    // Initialize Tables    这个应该放入定时器0里面的中断服务程序中
    for (i=0; i<DMA_BUF_SIZE; i++)
    {
        DMABuf1[i] = 0;

    }
    DMACH1_ADC_Init(DMABuf1,&AdcMirror.ADCRESULT0);

    while(1)//这里面应该是进行预警循环检测的。
    {
        while(AdcRegs.ADCST.bit.INT_SEQ1 == 0);  //查询转换是否结束
                AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;      //清除中断标志位
    }
}
void DMACH1_ADC_Init(volatile Uint16 *DMA_Dest,volatile Uint16 *DMA_Source)
{
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;    // ADC
    EDIS;

    // Specific clock setting for this example:
    EALLOW;
    SysCtrlRegs.HISPCP.all = 3;    // HSPCLK = SYSCLKOUT/ADC_MODCLK
    EDIS;

    InitAdc();  // For this example, init the ADC

    // Specific ADC setup for this example:
    AdcRegs.ADCTRL1.bit.ACQ_PS = 0x0f;//设置启动脉冲的宽度
    AdcRegs.ADCTRL3.bit.ADCCLKPS = 0x01;//ADCLK=HSPCLK/2=12.5MHz
    AdcRegs.ADCTRL1.bit.SEQ_CASC = 0;        // 0 Non-Cascaded Mode
    AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0x1;  //                     中断触发源
    AdcRegs.ADCTRL2.bit.RST_SEQ1 = 0x1;   //禁止adc采集

    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;//a0
    AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1;   //下面是我加的
    AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2;//a2
    AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3;
    AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x4;
    AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x5;
    AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x6;
    AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7;

    AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x7;   // Set up ADC to perform 7 conversions for every SOC



    // Start SEQ1
    AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 0x1;   //只用到了adc0-7,属于SEQ1//软件触发,ADC开始工作

#ifdef DMA_INT_ENABLE
    // Interrupts that are used in this example are re-mapped to ISR functions found within this file.
    EALLOW;    // Allow access to EALLOW protected registers
    PieVectTable.DINTCH1= &local_DINTCH1_ISR;
    EDIS;   // Disable access to EALLOW protected registers

    IER = M_INT7 ;                                 //Enable INT7 (7.1 DMA Ch1)
    EnableInterrupts();                          //使能cpu中断

#endif

    EALLOW;
    SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1;       // DMA Clock
    EDIS;
    // Initialize DMA
    DMAInitialize();

    // Configure DMA Channel
    DMACH1AddrConfig(DMA_Dest,DMA_Source);
    DMACH1BurstConfig(7,1,5);         //Will set up to use 32-bit datasize, pointers are based on 16-bit words突发中X传递的字数(X-1//问题:DMACH1BurstConfig(7,1,5)这样是不是就被覆盖了?
    /*
    * burst传输:burst传输是由每一个ADC中断标志触发,ADC每次转化完成,该传输模式启动。
    * void DMACH1BurstConfig(Uint16 bsize, int16 srcbstep, int16 desbstep)
    * bsize    :一帧传输的字数     burst是一帧
    * srcbstep :源地址步长。每次传输完一个字后增加一个步长。
    * desbstep :目的地址步长。每次传输完一个字后增加一个步长。
    */

    DMACH1TransferConfig(4,-7,-40+1);      //so need to increment by 2 to grab the correct location
    //每次传输的突发数,完成传输后将发生DMA中断;srctstep 发生WRAP时忽略TRANSFER_STEP;deststep 发生WRAP时忽略TRANSFER_STEP

    /*
     * transfer传输
     * 在上一次burst传输完成后,源和目的地址的基础上进行偏移。
     * tsize    :每tsize+1帧传输后中断一次
     * srctstep :每次中断后,源地址偏移,可以为负数,负增长。
     * deststep :每次中断后,目的地偏移,可以为负数,负增长。
     */

    DMACH1WrapConfig(100,100,100,100);//N个突发后换行源地址;源包装步骤;N个突发后包裹目标地址;目的地包装步骤
    //因为DMACH1WrapConfig(1,0,0,1)的第一个参数指明了每2帧回绕源地址,所以pDMASource从初值ADCRESULT0增到ADCRESULT7,
    /*
     * wrap传输,实现循环传输
     * srcwsize :传输srcwsize+1帧后,pDMA_Source = pDMA_Source + srcwstep;
     * srcwstep :源地址回绕步长。
     * deswsize :传输deswsize+1帧后,pDMA_Dest = pDMA_Dest + deswstep;
     * deswstep :目的地址回绕步长,每次回绕后目的地址。
     */

    //Use timer0 to start the x-fer.
    //Since this is a static copy use one shot mode, so only one trigger is needed
    //Also using 32-bit mode to decrease x-fer time
    DMACH1ModeConfig(DMA_SEQ1INT,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE,SYNC_DISABLE,
//                        SYNC_SRC,OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);
      //DMACH1ModeConfig(DMA_SEQ1INT,PERINT_ENABLE,ONESHOT_DISABLE,CONT_ENABLE,SYNC_DISABLE,
                          SYNC_SRC,OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);
    //以DMA_SEQ1INT为触发源;使能外设中断;oneshot禁止;禁止连续模式;禁止外围同步;
    //同步效果源或者目标;禁止溢出中断;16位传输;在传输结束时生成对cpu的中断;使能通道中断到cpu;
    StartDMACH1();//这个才是开始DMA转换

}


interrupt void local_DINTCH1_ISR(void)     // DMA Channel 1
{
    // To receive more interrupts from this PIE group, acknowledge this interrupt
    PieCtrlRegs.PIEACK.bit.ACK7 = 1;
//    asm ("      ESTOP0");//ok
//    for(;;);
}


【以下回答由 GPT 生成】

要解决该问题,我们需要检查代码中的几个方面:

  1. 首先,我们需要确定DMA配置是否正确。根据你提供的配置参数,您使用的是级联模式而不是非级联模式。请将DMACH1WrapConfig函数的参数更改为DMACH1WrapConfig(40,40,40,40)

  2. 其次,我们需要检查ADC的设置是否正确。在DMACH1_ADC_Init函数中,ADC采样频率由ADCTRL1寄存器的ACQ_PS字段设置。根据您提供的代码,该字段的值为0x0f,这意味着采样周期为16个ADCCLK周期。根据您的需求,每个采样口应该进行五次采样。因此,建议将ACQ_PS字段的值更改为0x04,以将采样周期设置为5个ADCCLK周期。

  3. 最后,我们需要检查ADC中断是否配置正确。在main函数中,当您查询ADC的INT_SEQ1标志位时,我们需要确定ADC的INT_SEQ1位是否在ADC的ADCTRL2寄存器中使能。请将DMACH1_ADC_Init函数中的AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1的值从0x1更改为0x3,以启用中断触发源。

请参考以下代码示例:

void DMACH1_ADC_Init(volatile Uint16 *DMA_Dest, volatile Uint16 *DMA_Source)
{
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC
    EDIS;

    // Specific clock setting for this example:
    EALLOW;
    SysCtrlRegs.HISPCP.all = 3; // HSPCLK = SYSCLKOUT/ADC_MODCLK
    EDIS;

    InitAdc(); // For this example, init the ADC

    // Specific ADC setup for this example:
    AdcRegs.ADCTRL1.bit.ACQ_PS = 0x04; // 设置启动脉冲的宽度
    AdcRegs.ADCTRL3.bit.ADCCLKPS = 0x01; // ADCLK=HSPCLK/2=12.5MHz
    AdcRegs.ADCTRL1.bit.SEQ_CASC = 0; // 0 Non-Cascaded Mode
    AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0x3; // 中断触发源
}

请注意,以上是根据您提供的代码逻辑进行的假设和建议。如果问题仍然存在,请提供更多关于DMA和ADC配置的代码详细信息,以便我们可以更好地帮助您解决问题。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^