主题中讨论的其他器件:EK-TM4C1294XL
您好!
我想开发一种应用、其中 ADC 的采样率必须为1MSPS 并且有4个通道需要采样。 我不想错过数据、因此我将使用以太网通过 TCP/IP 协议将数据发送到我的 PC。
我浏览了 enet_adcsensor_client_lwip 示例项目、但无法将 ADC 转换速度配置为1MSPS。
请求您提供指南。
谢谢。
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.
您好!
我想开发一种应用、其中 ADC 的采样率必须为1MSPS 并且有4个通道需要采样。 我不想错过数据、因此我将使用以太网通过 TCP/IP 协议将数据发送到我的 PC。
我浏览了 enet_adcsensor_client_lwip 示例项目、但无法将 ADC 转换速度配置为1MSPS。
请求您提供指南。
谢谢。
您好!
默认情况下、ADC 使用 PIOSC (16MHz)作为时钟源以推算 ADCCLK。 由于 PIOSC 为16MHz、因此最大 ADCCLK 只能为16MHz。 您应该能够获得1MSPS 及16MHz ADCCLK。
请参阅以下说明。 ADC 时钟源默认源自 ALTCLKCFG。 默认情况下、ALTCLKCFG 为 PIOSC。


15.3.2.7模块计时
ADC 数字模块由系统时钟计时、ADC 模拟模块由
独立转换时钟(ADC 时钟)。 ADC 时钟频率可高达32 MHz、
转换速率为2MSPS。 16 MHz ADC 时钟提供1Msps 的采样率。 有三种
ADC 时钟源:
■Ω 除以 PLL VCO。 PLL VCO 频率可配置为生成高达32MHz 的时钟
转换速率为2MSPS。 必须将 ADCCC 寄存器的 CS 域编程为
0x0以选择 PLL VCO、CLKDIV 域用来设置适当的时钟分频器、用于:
频率的一半。
■16 MHz PIOSC。 使用 PIOSC 可提供接近1MSPS 的转换速率。 使用 PIOSC
要为 ADC 提供时钟、首先为 PLL 上电、然后通过
ADCCC 寄存器、再禁用 PLL。
■μ A MOSC。 对于1Msps 转换率、MOSC 时钟源必须为16 MHz、对于1Msps 转换率、MOSC 时钟源必须为32 MHz
转换率是2 MSPS。
系统时钟的频率必须与 ADC 时钟相同或更高。 所有 ADC 模块
使用相同的时钟源、以促进转换间的数据样本同步
具体选项由 ADC0的 ADCCC 寄存器提供。 该 ADC
模块无法以不同的转换速率运行。
要实现2MSPS 等更高采样率、您需要从 PLL VCO 获取 ADCCLK。 在本例中、您可以将 ADCCLK 配置为32MHz。 使用 Bob 提供的示例代码参考此帖子。
我运行 bob 的代码、它运行正常。 但我在 Bob 的回复中看到了一些困惑->
很抱歉、文档有问题。 ADC 转换器时钟实际上是 PLL VCO 的2分频、然后除以 ADCCC 寄存器的 CLKDIV 字段(CLKDIV+1)中的值。 您无法使32MHz ADC 时钟在480MHz 上运行 PLL VCO、但在320MHz 上运行 PLL VCO、您可以通过使用5分频获得2MSPS。
2MSPS 的时间不足以在中断服务例程中使用 TivaWare 调用来切换 GPIO 引脚和清除中断、这一事实使问题变得更加复杂。 (更重要的是、读取并存储样本。) 在下面的示例中、我用直接寄存器写入替换了一些 TivaWare 调用、以避免子例程调用的开销。
但在我的应用程序中、我想在使用 TCP/IP 协议的情况下将数据发送到我的笔记本电脑。 但是根据 Bob 的回复、我们无法使用 tivaware 库来处理和发送数据。
是否有可用的解决方案? 因为在以1 MHz 频率转换 ADC 并通过以太网发送时、我不想错过任何数据。
谢谢。
您好!
Bob 的意思是、在2MSPS 下、在进行下一次采样之前、您将没有足够的时间来处理中断中的 ADC 数据。 如果它为2MSPS、那么有一个最大值为120MHz/2MHz=60的周期。 当您接收到一个 ADC 中断时、从一个中断产生的时间开始、直到 CPU 进入 ISR、首先有一个一定的延迟。 在 ISR 内部、您将需要读取和清除 ADC 状态、同时读取 ADC 数据或执行任何您想执行的任务。 在 Bob 的案例中、他尝试切换 GPIO 引脚。 所有这些操作都需要几个周期。 在 ISR 内部执行这些操作时、可能会有另一个 ADC 采样到达、中断会再次生成、直到您退出当前的 ADC ISR。 我想您可以通过将采样率降至1MSPS 而不是2MSPS 以及使用 uDMA 而不是使用 CPU 来传输 ADC 数据来解决这个问题。
请参考以下示例 :C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\adc_udma_pingpong 有关如何在乒乓模式下使用 uDMA 将 ADC 数据传输到临时缓冲区的信息。 我建议您在添加代码将数据从缓冲区传输到以太网之前、按原样运行此示例以了解如何使用 uDMA。
我应该得到值1MHz/64 = 15625Hz 正确吗?
64源自何处? 为什么是1MHz? 您的 VCO 为240Mhz、在您的 以下调用中、您将 VCO 除以8、这将为 ADCCLK 提供30Mhz。 这定义了转换输入数据时的 ADCCLK 时钟速度。
ADCClockConfigSet (ADC0_BASE、ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL、8);
下面的调用定义输入采样的速率。 计时器每隔1uS 向 ADC 发送一个触发信号、以转换输入。
//
//将 ADC 采样频率设置为1MHz,即每1uS 一次。
//
TimerLoadSet (TIMER0_BASE、TIMER_A、(g_ui32SysClock/1000000)- 1);
感谢 Charles 的建议。 我根据您的反馈进行了更改。
现在、我已经将 ADC_PING_PONG 逻辑与 TCP/IP 客户端代码进行了集成。 为了测试我的代码,我正在使用 Hercules 3.2.8。 但是、每次我收到数据时、Hercules 都会崩溃。 据我所知、我发送数据的速度太快。 一旦我的 pcBuf 已满、有什么方法可以发送数据吗?
//检查第一个缓冲区是否已满,如果是,则处理数据。
//
if (pui32BufferStatus[0]==满)
{
//
//处理 pui16ADCBuffer1中的数据并清除缓冲区条目。
//
for (ui32Count =0;ui32Count < sizeof (pui16ADCBuffer1)/ sizeof (pui16ADCBuffer1[0]);ui32Count++)
{
sprintf (pcBuf、"Data[%d]:%d\n"、ui32Count、pui16ADCBuffer1);
TcpSendPacket (pcBuf);
pui16ADCBuffer2[ui32Count]= 0;
}
以太网有效载荷约为1500字节。 但我发送的是<5字节。 是否有任何方法可以增加帧大小。 附上完整代码。
e2e.ti.com/.../enet_5F00_adcsensor_5F00_client_5F00_lwip.zip
我认为您的问题很可能是由于您在以太网中断处理程序的上下文中调用 lwIP API。 请参阅以下帖子中 David Wilson 的评论、这些评论将非常有用。
"这里最大的问题是、您是从以太网中断处理程序之外的运行环境调用 lwIP。 lwIP 不可重入、因此只能从一个上下文中调用它。 使用 RTOS 时、这意味着仅从单线程调用 lwIP API。 当不使用 RTOS 时(如我们的大多数示例)、您必须在以太网中断处理程序的上下文中进行调用。 这可能有点复杂、但通过实现计时器回调、使操作更加简单。 请确保将 HOST_TMR_INTERVAL 设置为某个非零值(我想是几毫秒)并在应用中实施 lwIPHostTimerHandler、然后从 lwIPHostTimerHandler 函数中调用所有 lwIP。
这听起来可能很尴尬,但它是至关重要的。 从主循环调用 udp_send 可能需要一段时间、但我保证、它会在一段时间后崩溃、因为 lwIP 中的一些内部数据结构会损坏。 这种问题很难调试、所以现在解决这个问题要比试图假设一切正常并让它灾难性地失败好得多。"
您好!
我将建议您打开调试信息以调查问题的原因。 请参阅以下代码段以更新 lwipopts.h 文件中的调试日志记录。
//*****
//
//------- 调试选项-------------------------------------------------------
//
//*****
#IF 1
#define U8_F "c"
#define S8_F "c"
#define x8_F "x"
#define U16_F "u"
#define S16_F "d"
#define X16_F "x"
#define U32_F "u"
#define S32_F "d"
#define X32_F "x"
extern void UARTprintf (const char * pcString、...);
#define LWIP_platform_DIAG (msg) UARTprintf msg
#define LWIP_platform_assert (msg)\
UARTprintf ("assert_Fail at line %d of %s:\%s\n"、__line__、__FILE__、msg)
#define LWIP_DEBUG 1
#endif