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.

[参考译文] EK-TM4C123GXL:在 TM4C123G 上使用 UDMA 读取多通道 ADC 数据时出现问题

Guru**** 1999175 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1455480/ek-tm4c123gxl-issue-with-reading-multi-channel-adc-data-using-udma-on-tm4c123g

器件型号:EK-TM4C123GXL

工具与软件:

您好!

在 TM4C123G 上、我的目标是使用计时器中断触发 ADC 并采用 UDMA 来存储从6通道 ADC 读取的数据。 但是、在我所做的配置下、我只能看到 uDMA 目标缓冲区中第一个通道的值。

我知道、属于 ADC 0的 FIFO 按照"简单循环缓冲器"的原理工作、并且我可以使用状态寄存器看到检索到的数据的起点和终点。 然而、我是否需要在 uDMA-ADC 设置中执行任何其他配置来同步这些起点和终点? 或者 FIFO 中的数据应该在突发模式中同步传输到 UDMA?

我是根据"adc_udma_pingpong"示例代码构建的、并在下面分享了一些重要部分:

MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_ADC0);
MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_UDMA);
ROM_SysCtlPeripheralEnable (SYSCTL_PERIPH_TIMER0);
MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_Timer1);
MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOE);

GPIOPinTypeADC (GPIO_PORTD_base、GPIO_PIN_0);//AIN7
GPIOPinTypeADC (GPIO_PORTD_base、GPIO_PIN_1);//AIN6
GPIOPinTypeADC (GPIO_PORTD_base、GPIO_PIN_2);//AIN5
GPIOPinTypeADC (GPIO_PORTB_BASE、GPIO_PIN_4);//AIN10
GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_4);//AIN9
GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3);//AIN0

// ConfigureUART();


uDMAEnable();
IntEnable (uDMA_channel_ADC0);

uDMAControlBaseSet (pui8ControlTable);

ROM_IntEnable (INT_UDMA);

uDMAChannelAttributeDisable (UDMA_CHANNEL_ADC0、
uDMA_ATTR_ALTSELECT | uDMA_ATTR_HIGH_PRIORITY |
uDMA_ATTR_REQMASK);

uDMAChannelControlSet (UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT、UDMA_SIZE_16 |
UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);

uDMAChannelControlSet (UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT、UDMA_SIZE_16 |
UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);

uDMAChannelTransferSet (UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT、
udma_mode_pingpong、
(void *)(ADC0_BASE + ADC_O_SSFIFO0)、
&pui16ADCBuffer1、ADC_SAMPLE_BUF_SIZE);

uDMAChannelTransferSet (UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT、
udma_mode_pingpong、
(void *)(ADC0_BASE + ADC_O_SSFIFO0)、
&pui16ADCBuffer2、ADC_SAMPLE_BUF_SIZE);

uDMAChannelAttributeEnable (UDMA_CHANNEL_ADC0、UDMA_ATTR_USEBURST);

uDMAChannelEnable (UDMA_CHANNEL_ADC0);

ADCClockConfigSet (ADC0_BASE、ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_HALF、1);

SysCtlDelay (10);

IntDisable (INT_ADC0SS0);

ADCIntDisable (ADC0_BASE、0);

ADCHardwareOversampleConfigure (ADC0_BASE、4);

ADCSequenceDisable (ADC0_BASE、0);

ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_TIMER、0);


ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_CH7);//Sira onemli
ADCSequenceStepConfigure (ADC0_BASE、0、1、ADC_CTL_CH6);
ADCSequenceStepConfigure (ADC0_BASE、0、2、ADC_CTL_CH5);//IE ve end sadece Sonda
ADCSequenceStepConfigure (ADC0_BASE、0、3、ADC_CTL_CH10);
ADCSequenceStepConfigure (ADC0_BASE、0、4、ADC_CTL_CH9);
ADCSequenceStepConfigure (ADC0_BASE、0、5、ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);

ADCSequenceEnable (ADC0_BASE、0);

ADCIntClear (ADC0_BASE、0);

ADCSequenceDMAEnable (ADC0_BASE、0);
ADCIntEnable (ADC0_BASE、0);

IntEnable (INT_ADC0SS0);


ROM_TimerConfigure (TIMER0_BASE、TIMER_CFG_PERIODICE)
TimerConfigure (Timer1_BASE、TIMER_CFG_SPLIT_PAIR |TIMER_CFG_B_PERIODICENT);


ROM_TimerLoadSet (TIMER0_BASE、TIMER_A、ROM_SysCtlClockGet ()/ 100000);//10us
TimerLoadSet (Timer1_base、Timer_B、ROM_SysCtlClockGet ()/ 10000);


TimerControlTrigger (Timer1_base、timer_B、true);

IntMasterEnable();
ROM_IntEnable (INT_TIMER0A);
ROM_TimerIntEnable (TIMER0_BASE、TIMER_TIMA_TIMEOUT)
ROM_TimerEnable (TIMER0_BASE、TIMER_A)

TimerEnable (Timer1_base、Timer_B);

(包括详细的代码片段、可以将其添加到上面的文本中。)

我执行了如上所述的初始配置。 我按如下方式配置了 ADC 序列0中断:

void ADCSeq0Handler (void)

ADCIntClear (ADC0_BASE、0);

如果((uDMAChannelModeGet (UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT)= UDMA_MODE_STOP)&&
(pui32BufferStatus[0]=>=填充)){
pu32BufferStatus[0]=已满;
pui32BufferStatus[1]=填充;
}

否则为((uDMAChannelModeGet (UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT)= UDMA_MODE_STOP)&&
(pui32BufferStatus[1]=填充)){
pui32BufferStatus[0]=填充;
pu32BufferStatus[1]=已满;
}

if (pui32BufferStatus[0]=>= Full){
pu32BufferStatus[0]=空;
uDMAChannelTransferSet (UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT、
udma_mode_pingpong、
(void *)(ADC0_BASE + ADC_O_SSFIFO0)、
&pui16ADCBuffer1、ADC_SAMPLE_BUF_SIZE);
uDMAChannelEnable (UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);
}

否则、if (pui32BufferStatus[1]== full){
pu32BufferStatus[1]=空;
uDMAChannelTransferSet (UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT、
udma_mode_pingpong、
(void *)(ADC0_BASE + ADC_O_SSFIFO0)、
&pui16ADCBuffer2、ADC_SAMPLE_BUF_SIZE);
uDMAChannelEnable (UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);
}
}

如果此流程中有任何错误或缺失器件、我将非常感谢您提供建议和帮助。

谢谢!
Yusuf EKER



  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

     我看到 您的代码有问题。  

     根据以下代码和插入的注释、您似乎想要对 AIN7、6、5、10、9、0进行采样。 对于 AIN7、6、5、它们位于端口 D 上。对于 AIN 10、它位于端口 B 上。否、在代码中的哪个位置、我看到您启用了端口 D 和端口 B。我只看到您启用了端口 E。这是第一个问题。  

    [报价用户 id="630335" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1455480/ek-tm4c123gxl-issue-with-reading-multi-channel-adc-data-using-udma-on-tm4c123g "]

    MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_ADC0);
    MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_UDMA);
    ROM_SysCtlPeripheralEnable (SYSCTL_PERIPH_TIMER0);
    MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_Timer1);
    MAP_SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOE);

    GPIOPinTypeADC (GPIO_PORTD_base、GPIO_PIN_0);//AIN7
    GPIOPinTypeADC (GPIO_PORTD_base、GPIO_PIN_1);//AIN6
    GPIOPinTypeADC (GPIO_PORTD_base、GPIO_PIN_2);//AIN5
    GPIOPinTypeADC (GPIO_PORTB_BASE、GPIO_PIN_4);//AIN10
    GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_4);//AIN9
    GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3);//AIN0

    [报价]

    我强烈建议您首先在不使用 uDMA 的情况下运行代码。 一旦使所有通道都能正常工作后、便可添加 uDMA 代码。 此外,不要使用卵泡,直到你得到其他东西工作。 从简单的设置开始并逐渐向其中添加功能始终是一个好主意。   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Charles:

    感谢您的答复。 我共享的代码仅表示我现有代码的特定部分。 当然、必要的 GPIO 已被激活、并且已被定义为 ADC GPIO。 我在不使用 uDMA 的情况下测试了这些 ADC 通道、并且没有遇到任何问题。 事实上、我使用 uDMA 成功传输了单通道 ADC 数据。

    但是、当我增加通道数量时、我认为我分享的配置存在错误。 在以下代码片段中:

    uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);

    我无法理解如何ARB确定价值。 我找不到有关这方面的详细信息。

    此外、我想了解 ADC 寄存器如何ADC_O_SSFIFO0存储所有通道的数据并将其传输到 uDMA。 我在 TI 的文档中几乎没有找到任何相关的解释。

    如果您对该主题有任何了解、如果您能分享、我将不胜感激。

    谢谢!
    Yusuf EKER



  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [报价用户 id="630335" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1455480/ek-tm4c123gxl-issue-with-reading-multi-channel-adc-data-using-udma-on-tm4c123g/5584841 #5584841"]
    uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);

    我无法理解如何ARB确定价值。 我找不到有关这方面的详细信息。

    [报价]

    假设您在应用中设置了多个 uDMA 通道。 uDMA 如何从一个通道切换到另一个通道。 如果您为特定通道设置了一个具有4096字节传输大小的通道、那么 UDMA 会在何时切换到下一个通道? 这取决于仲裁大小(ARB)值。 如果您使用 UDMA_ARB_! 然后、尽管正在设置4096个元件、但 UDMA 将仅传输一个元件、然后切换到下一个通道。 对于只有一个通道设置的应用、ARB 尺寸的意义不大、因为没有其他通道可切换到。 传输一个元素后、如果指定的传输大小已完成、则该元素将在相同的通道上继续传输。  

    在您的特定案例中、由于您有六个样本、我建议您将 ARB 尺寸配置为6。 每当 ADC 生成 DMA 请求时、UDMA 总共会读取6个样本、如果您 可能在将来进行设置、则会在切换到另一个通道之前。  

    [报价用户 id="630335" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1455480/ek-tm4c123gxl-issue-with-reading-multi-channel-adc-data-using-udma-on-tm4c123g/5584841 #5584841"]

    此外、我想了解 ADC 寄存器如何ADC_O_SSFIFO0存储所有通道的数据并将其传输到 uDMA。 我在 TI 的文档中几乎没有找到任何相关的解释。

    [报价]

    ADC_0_SSFIFO0寄存器仅是 FIFO 的正面寄存器。 每次您从该寄存器读取时、内部 FIFO 读取指针都会自动递减。