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.
工具与软件:
您好!
在 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
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 读取指针都会自动递减。