This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C123GH6PM的ADC数据用uDMA乒乓模式传输不成功,请帮忙看看哪里配置错误,谢谢!



我的问题中定时器触发ADC转换,转换完后用uDMA将数据搬至缓存区。用乒乓模式,配置了主/副控制结构体。定时器触发是成功的,单独配置下能使ADC正确转换。主要是uDMA搬移数据只能进一次ADC外设中断,即只能搬一次数据。进中断时主/副控制结构体同时会判断传输结束,而不是手册上的无限循环:

程序代码:

//*************************************************程序变量设置*****************************************************

#define ADC0_BUF_SIZE        1024

uint32_t Adc0_Val_RA[ADC0_BUF_SIZE];
uint32_t Adc0_Val_RB[ADC0_BUF_SIZE];

//*************************************************uDMA初始化*****************************************************

uint8_t ucDMAControlTable[1024];//通道控制表
extern uint32_t Adc0_Val_RA[ADC0_BUF_SIZE];
extern uint32_t Adc0_Val_RB[ADC0_BUF_SIZE];
void MyDma_Init(void)
{
 SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
 uDMAEnable();
 uDMAControlBaseSet(ucDMAControlTable);
 //-------------------------
 uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0, UDMA_ATTR_ALL);//失能通道的所有特性
 uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0,UDMA_ATTR_USEBURST|UDMA_ATTR_HIGH_PRIORITY);//使能猝发与高优先级
 //-------------------------
 uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
        UDMA_SIZE_32 |  UDMA_SRC_INC_NONE |UDMA_DST_INC_32 | UDMA_ARB_8);
 uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
        UDMA_SIZE_32 |  UDMA_SRC_INC_NONE |UDMA_DST_INC_32 | UDMA_ARB_8);
 //-------------------------
 uDMAChannelTransferSet(UDMA_CHANNEL_ADC0| UDMA_PRI_SELECT,
        UDMA_MODE_PINGPONG,  (void *)(ADC0_BASE+ADC_O_SSFIFO0), Adc0_Val_RA,ADC0_BUF_SIZE);
 uDMAChannelTransferSet(UDMA_CHANNEL_ADC0| UDMA_ALT_SELECT,
        UDMA_MODE_PINGPONG,  (void *)(ADC0_BASE+ADC_O_SSFIFO0), Adc0_Val_RB,ADC0_BUF_SIZE);
 uDMAChannelEnable(UDMA_CHANNEL_ADC0);
}

//***********************************************ADC初始化与中断***************************************************

void Adc0_Init(void)
{
 SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
 GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ADCSequenceConfigure(ADC0_BASE,0,ADC_TRIGGER_TIMER, 0);//定时器触发ADC转换
 ADCSequenceStepConfigure(ADC0_BASE, 0, 0,  ADC_CTL_CH0);
 ADCSequenceStepConfigure(ADC0_BASE, 0, 1,  ADC_CTL_CH0);
 ADCSequenceStepConfigure(ADC0_BASE, 0, 2,  ADC_CTL_CH0);
 ADCSequenceStepConfigure(ADC0_BASE, 0, 3,  ADC_CTL_CH0);
 ADCSequenceStepConfigure(ADC0_BASE, 0, 4,  ADC_CTL_CH0);
 ADCSequenceStepConfigure(ADC0_BASE, 0, 5,  ADC_CTL_CH0);
 ADCSequenceStepConfigure(ADC0_BASE, 0, 6,  ADC_CTL_CH0);
 ADCSequenceStepConfigure(ADC0_BASE, 0, 7,  ADC_CTL_CH0|ADC_CTL_END|ADC_CTL_IE);//使得uDMA仲裁大小为8
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ADCSequenceDMAEnable(ADC0_BASE, 0);//使能DMA传输
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ADCIntRegister(ADC0_BASE,0,ADC0IntHandler);
 ADCIntEnable(ADC0_BASE, 0);
 ADCIntEnableEx(ADC0_BASE,ADC_INT_DMA_SS0);//代表DMA触发
// IntEnable(INT_ADC0SS0);
// ADCIntClear(ADC0_BASE, ui32SequenceNum);
 ADCSequenceEnable(ADC0_BASE, 0);
//****************************
extern uint32_t Adc0_Val_RA[ADC0_BUF_SIZE];
extern uint32_t Adc0_Val_RB[ADC0_BUF_SIZE];
void ADC0IntHandler(void)
{
   ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS0);
 
  if(uDMAChannelModeGet(UDMA_CHANNEL_ADC0| UDMA_PRI_SELECT) == UDMA_MODE_STOP)
   {
  uDMAChannelTransferSet(UDMA_CHANNEL_ADC0| UDMA_PRI_SELECT,
        UDMA_MODE_PINGPONG,  (void *)(ADC0_BASE+ADC_O_SSFIFO0), Adc0_Val_RA,ADC0_BUF_SIZE);
   }
 
  if(uDMAChannelModeGet(UDMA_CHANNEL_ADC0| UDMA_ALT_SELECT) == UDMA_MODE_STOP)
   {
  uDMAChannelTransferSet(UDMA_CHANNEL_ADC0| UDMA_ALT_SELECT,
        UDMA_MODE_PINGPONG,  (void *)(ADC0_BASE+ADC_O_SSFIFO0), Adc0_Val_RB,ADC0_BUF_SIZE);
   }
}
//*********************************************************main.c**************************************************************
int main(void)

 //~~~~~~~~~~~~~~~~~~~
 SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
 //~~~~~~~~~~~~~~~~~~~ 
 Adc0_Init(0);
 MyDma_Init();
 My_Timer_Trigger_Init();//定时器触发ADC转换
 IntMasterEnable();
 while(1)
 { 
 }
}