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);
结果就是每个采样口都采集到一次数据,后面四次数据没有采集到。
程序如下:
#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 生成】
要解决该问题,我们需要检查代码中的几个方面:
首先,我们需要确定DMA配置是否正确。根据你提供的配置参数,您使用的是级联模式而不是非级联模式。请将DMACH1WrapConfig函数的参数更改为DMACH1WrapConfig(40,40,40,40)
。
其次,我们需要检查ADC的设置是否正确。在DMACH1_ADC_Init函数中,ADC采样频率由ADCTRL1寄存器的ACQ_PS字段设置。根据您提供的代码,该字段的值为0x0f,这意味着采样周期为16个ADCCLK周期。根据您的需求,每个采样口应该进行五次采样。因此,建议将ACQ_PS字段的值更改为0x04,以将采样周期设置为5个ADCCLK周期。
最后,我们需要检查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配置的代码详细信息,以便我们可以更好地帮助您解决问题。