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.

[参考译文] CCS/EK-TM4C1294XL:ADC 未以2MSPS 运行(上限为1MSPS)

Guru**** 2478765 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/690227/ccs-ek-tm4c1294xl-adc-not-running-at-2msps-capped-at-1msps

器件型号:EK-TM4C1294XL

工具/软件:Code Composer Studio

我在将 ADC 设置为2MSPS 方面遇到了一些困难。 根据我在数据表中看到的内容、为了实现最佳性能、必须为 ADC 提供32MHz 的时钟。

因此、我以这种方式配置 ADC

void CONFIG_ADC0 (void)
{
ROM_GPIOPinTypeADC (GPIO_PORTK_base、GPIO_PIN_0);

ROM_ADCReferenceSet (ADC0_BASE、ADC_REF_INT);

ROM_ADCSequenceConfigure (ADC0_BASE、3、ADC_TRIGGER_TIMER、0);

ROM_ADCSequenceStepConfigure (ADC0_BASE、3、0、ADC_CTL_CH16 | ADC_CTL_IE | ADC_CTL_END);

ROM_ADCHardwareOversampleConfigure (ADC0_BASE、0);

//480MHz PLL / 15 = 32MHz = 2MSPS
ADCClockConfigSet (ADC0_BASE、ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL、15);

ROM_ADCSequenceEnable (ADC0_BASE、3);

ROM_IntDisable (INT_ADC0SS3);
ROM_ADCIntDisable (ADC0_BASE、3);
ROM_IntPendClear (INT_ADC0SS3);
ROM_ADCIntClear (ADC0_BASE、3);

ROM_IntEnable (INT_ADC0SS3);
ROM_ADCIntEnable (ADC0_BASE、3);
} 

并将 Timer0配置为触发(以2MHz 的速度计数)。 但 ADC 速度上限为1MHz、即使我改用 ADC_TRIGGER_Always。 系统时钟为120MHz、PLL 为480MHz。

我将使用这些函数和逻辑分析仪来查看实际速度:

void ADC0SS3IntHandler (void)
{
ROM_ADCIntClear (ADC0_BASE、3);

//rom_ADCSequenceDataGet (ADC0_BASE、3、g_adc0Reading);

ROM_GPIOPinWrite (GPIO_Porta_base、GPIO_PIN_4、g_flagAdc0? GPIO_PIN_4:0x00);

G_flagAdc0 =!g_flagAdc0;
} 

ADC 频率是输出引脚频率的2倍。 我实现略高于1MSPS (~1.2MSPS 不稳定)的唯一方法是将 PLL 频率除以7 (导致 ADC 为68MHz)、但这毫无意义。 我该如何实现2MSPS?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    问题是否出在您的计时器配置中?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我还看到只有1MSPS。 让我来深入探究一下。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Bob Crosby">问题是否出在您的计时器配置中?

    [/报价]

    我不认为是这样、因为计时器的工作频率低于1MHz。 问题也会在始终触发时出现。 至少我已经使用这两种方法进行了测试。

    [引用 user="Bob Crosby">我也只能看到1MSPS。 让我来深入探究一下。

    [/报价]

    这很有趣...我会等待您的调查结果、因为我的想法太多了...

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

    很抱歉、说明文件有问题。 ADC 转换器时钟实际上是 PLL VCO 除以2、然后除以 ADCCC 寄存器的 CLKDIV 字段(CLKDIV+1)中的值。 您无法获得以480MHz 频率运行 PLL VCO 的32MHz ADC 时钟、但以320MHz 频率运行 PLL VCO、您可以使用5分频获得2MSPS。

    由于在2MSPS 时没有足够的时间在中断服务例程中使用 TivaWare 调用来切换 GPIO 引脚和清除中断、这个问题变得更加复杂。 (更少的是、读取并存储样本。) 在下面的示例中、我用直接寄存器写入替换了一些 TivaWare 调用、以避免子例程调用的开销。

    //
    //
    //
    ////版权所有(c) 2012-2018 Texas Instruments Incorporated。 保留所有权利。
    //软件许可协议
    //
    //德州仪器(TI)提供此软件仅供
    和//仅供 TI 的微控制器产品使用。 软件归
    // TI 和/或其供应商所有,并受适用的版权
    //法律保护。 您不能将此软件与"病毒"开源
    //软件组合在一起以形成更大的程序。
    //
    //此软件按“原样”提供,且存在所有故障。
    //对于
    
    本软件,不作任何明示、暗示或法定的保证,包括但不限于对适销性和适用性的暗示保证//特定用途。 在任何
    //情况下、TI 不对任何
    原因造成的特殊、意外或必然//损害负责。
    ////////
    
    *************
    
    #include 
    #include 
    #include "inc/hw_types.h"
    #include "void/hw_ints.h"
    #include "inc/hw_adc.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #define "driverlib_idpio.h"
    
    #include "driverlib_init_init/use_timer #define #include "idpio.idt_init_init.idpio.h"
    
    
    
    
    
    
    
    
    
    
    
    ;#define #include "idr_init_init_ipt_init_init_init.idr.idr_u.idr_ipt_init.h (#include "#define #define #define #include "in_in_ipt_in_in_idr.
    
    //
    //从 PLL 以120MHz 运行。
    //
    ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |
    SYSCTL_OSC_MAIN |
    SYSCTL_USE_PLL |
    SYSCTL_CFG_VCO_320)、120000000);
    
    SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);//启用 TIMER0的时钟
    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);//启用 ADC 模块的时钟
    //
    //启用并等待端口准备好访问
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);
    SysCtlPeripheralEnable (SYSCTL_Periph_GPION);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_GPION))
    {
    }
    
    //
    //为 LED 操作配置 GPIO 端口。
    //
    GPIOPinTypeGPIOOutput (GPIO_PORTN_BASE、(USER_LED1|USER_LED2));
    
    init_adc();
    init_timer();
    IntMasterEnable();
    TimerEnable (TIMER0_BASE、TIMER_A);//开始一切
    //
    //永久循环
    //
    while (1)
    {
    // GPIOPinWrite (GPIO_PORTN_BASE、(USER_LED1|USER_LED2)、0);
    HWREG (GPIO_PORTN_BASE + 4)= 0;
    }
    }
    
    void init_timer()
    {
    TimerConfigure (TIMER0_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODICASE);
    //将采样频率设置为2MHz (每隔62.5uS)
    TimerLoadSet (TIMER0_BASE、TIMER_A、40 - 1);//TODO:此处设置定时器装载值
    TimerControlTrigger (TIMER0_BASE、TIMER_A、TRUE);
    TimerControlStall (TIMER0_BASE、TIMER_A、TRUE);//通过在断点处停止计时器来帮助调试
    }
    
    void init_adc ()
    {
    GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_2);
    SysCtlDelay (80u);
    
    //使用 ADC0序列0为每个定时器周期对通道0采样一次
    ADCClockConfigSet (ADC0_BASE、ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL、5);
    
    SysCtlDelay (10);//设置时钟配置的时间
    
    IntDisable (INT_ADC0SS0);
    ADCIntDisable (ADC0_BASE、0U);
    ADCSequenceDisable (ADC0_BASE、0U);
    //禁用序列后,现在可以安全地加载新的配置参数
    
    ADCSequenceConfigure (ADC0_BASE、0U、ADC_TRIGGER_TIMER、0U);
    ADCSequenceStepConfigure (ADC0_BASE、0U、0U、ADC_CTL_CH0 | ADC_CTL_END | ADC_CTL_IE);
    ADCSequenceEnable (ADC0_BASE、0U);//设置配置后、重新启用序列发生器
    ADCIntClear (ADC0_BASE、0U);
    ADCIntEnable (ADC0_BASE、0U);
    IntEnable (INT_ADC0SS0);
    
    }
    
    void ADC0SS0IntHandler (void)
    {
    HWREG (GPIO_PORTN_BASE + 4)= 1;
    //GPIOPinWrite (GPIO_PORTN_BASE、(USER_LED1|USER_LED2)、USER_LED1);
    HWREG (ADC0_BASE + ADC_O_ISC)= 1 << 0;
    // ADCIntClear (ADC0_BASE、0);
    }
    

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

    现在它正在工作、谢谢 Bob! 我怀疑我必须直接写入寄存器。 但这不是问题、因为我将使用硬件过采样(>=16)。

    说到文档问题、我在  TivaWare 外设驱动程序库用户指南中发现了一个小错误:

    我认为它应该是 SysCtlPWMClockSet()

    再次感谢 Bob 的帮助!