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.

[参考译文] TM4C129ENCPDT:执行 ADC 时偶尔出现脱漏读数

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1075201/tm4c129encpdt-occasional-dropout-reading-when-doing-adc

部件号:TM4C129ENCPDT

你(们)好。  我在这块板上遇到一些 ADC 问题,但我没有找到解决方案。  我在以前的一些主板上完成了类似的 ADC 任务,但没有遇到此问题。  同样的处理器。  此时,我已经将其最小化为最基本的 ADC 代码,但仍然看到问题。

我正在从一个2轴模拟操纵杆读取值。  每个轴上的电压都为0-3V。  我现在已经将代码向下剥离,只读一个轴,因为我不知道发生了什么。

#define SEQ_NUM 3.

UINT32_t pui32ADC0Value[4];
UINT32_t pui32ADC1Value[4];

void 多功能操作手柄初始化(void){
SysPeripheralEnable (sysctl_Periph_GPIOD);
SysPeripheralEnable (sysctl_Periph_ADC0);
GPIOPinTypeADC (GPIO _PORTD_BASE,GPIO _PIN_2);
ADCReferenceSet (ADC0_BASE,ADC_REF_EXT_3V);

ADCSequenceDisable (ADC0_BASE,SEQ_NUM);
ADCSequenceConfigure (ADC0_BASE,SEQ_NUM,ADC_TRIG_PROCESSOR, 0);
ADCSequenceStepConfigure (ADC0_BASE,SEQ_NUM,0,ADC_CTL_CH13 | ADC_CTL_IE | ADC_CTL_END);

ADCSequenceEnable (ADC0_BASE,SEQ_NUM);
ADCIntClear (ADC0_BASE,SEQ_NUM);


}

操纵杆螺纹无效(无效){

当(1){

ADCProcessorTrigger (ADC0_base,SEQ_NUM);

当(!ADCIntStatus (ADC0_BASE,SEQ_NUM,FALSE)为{时
}

ADCIntClear (ADC0_BASE,SEQ_NUM);
ADCSequenceDataSet (ADC0_base,SEQ_NUM,pui32ADC0Value);

输入值=(pui32ADC0Value[0]和0xFFF);

sprintf (字符串,“raw =%d”,输入值);
send_string_msg (string_command,0,string);

SystlDelay (ui32SysClock /120);

}

}

 send_string_msg()将该值发送到 LED 显示屏。

 

这一切看起来都很基本,但大多数时候,我得到了 ADC 的预期值,但可能是10%的时间,我得到了一个值,0,3,7,15, 31,63,127, 255,你明白了。  这会对控制系统造成严重破坏。

我在循环中的延迟似乎无关紧要。  我尝试执行序列,例如使用序列号0或1,并读取4个值。  我尝试过使用过采样,但后来我得到的值低于预期值,因为平均值较低。  我尝试在 序列步骤中添加 ADC_CTL_SHOL_16值。  例如,如果我执行了4个步骤的序列,则4个样本中的任何一个在任何时候都可能是正确的,或者可能是低的,例如,一个或两个样本是低的,则其他两个样本是预期的。

也许解决方案就在我面前,我已经看了一段时间了,现在还没有看到。  我们非常感谢您的帮助。

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

    您好,

     您的代码相当简单,我不能发现您所显示的内容有任何问题。 ADCCLK 可能有问题。 您能否展示如何设置 SYSCLK 以及是否使用 ADCClockConfigSet 配置 ADCCLK?

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

    我想说每个轴上的0-6V。  居中时为3V。  如果不移动,我通常会看到2056左右的输出。

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

    另一件事是,你说它正在与其他董事会合作。 您可以尝试一些实验。

     -在 LaunchPad 板上运行新删除的代码? 你看到什么?

     ——在新的董事会上运行您过去的工作代码?

     ——在过去的工作板上运行新删除的代码?

     我希望通过这些实验,它们能为故障排除提供一些见解。   

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

    ui32SysClock = SysClockFreqSet (sysctl_use_PLL | sysctl_OSC 主| sysctl_XT_25MHz | sysctl_CFG VCO_480,120000000);

    我没有使用  ADCClockConfigSet。

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

    我最初从另一个读取差分传感器的电路板上获取了我的工作代码,但该电路板也缩小到了大约相同的电压范围。  端口/引脚不同,因此我更改了这些引脚和 ADC 信道,并希望它能正常工作。  我现在遇到的问题完全相同。  “大部分”是有效的,但有退学的情况。

    这是一个定制板。  我可能在某个地方有一个旧的 Launchpad 板,但可能在5年内没有看到它。  该主板的许多主板设计都是以前的主板设计。  通常,我们会尝试维护相同的 CAN 端口。  这次,由于主板上的其他一些外围设备,我们不得不采取一些行动。

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

    您好,

     我真的看不到时钟配置有问题。 如果不使用  ADCClockConfigSet 指定 ADC 的时钟源,则它默认为 PIOSC,这是正常的。 在16MHz 时,如果您将所有内容保持在默认值,PIOSC 将提供1Msps。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="243658" url="~/support/icles/arm-based 微处理器组/基于 ARM 的微控制器/f/基于 ARM 的微控制器-forum/1075201/tm4c129encpdt-occase-drop-read-dime-dcp/3979087#3979087]i,我最初使用的电压范围缩小了另一个读数,但该电压范围与另一个读数相同。  端口/引脚不同,因此我更改了这些引脚和 ADC 信道,并希望它能正常工作。  我现在遇到的问题完全相同。  “大部分”都是有效的,但与退学者有关。

    您还可以尝试将 ADC 输入与0,1.65V 和3.3V 连接起来。 您是否始终如一地从   pui32ADC0Value[0]读取0,0x7FF 或0xFFF?

    还请尝试一下这款 TivaWare 示例,它显示了什么? 您可以在 C:\ti\TiaWare_C_Series-2.2.0.295\Examples\Peripherals\ADC\singal_endended 中找到示例。

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/adc.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    //*****************************************************************************
    //
    //! \addtogroup adc_examples_list
    //! <h1>Single Ended ADC (single_ended)</h1>
    //!
    //! This example shows how to setup ADC0 as a single ended input and take a
    //! single sample on AIN0/PE3.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - ADC0 peripheral
    //! - GPIO Port E peripheral (for AIN0 pin)
    //! - AIN0 - PE3
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of the
    //! ADC.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - None.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    //*****************************************************************************
    //
    // Configure ADC0 for a single-ended input and a single sample.  Once the
    // sample is ready, an interrupt flag will be set.  Using a polling method,
    // the data will be read then displayed on the console via UART0.
    //
    //*****************************************************************************
    int
    main(void)
    {
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        uint32_t ui32SysClock;
    #endif
    
        //
        // This array is used for storing the data read from the ADC FIFO. It
        // must be as large as the FIFO for the sequencer in use.  This example
        // uses sequence 3 which has a FIFO depth of 1.  If another sequence
        // was used with a deeper FIFO, then the array size must be changed.
        //
        uint32_t pui32ADC0Value[1];
    
        //
        // Set the clocking to run at 20 MHz (200 MHz / 10) using the PLL.  When
        // using the ADC, you must either use the PLL or supply a 16 MHz clock
        // source.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        //
        // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
        // later to better reflect the actual VCO speed due to SYSCTL#22.
        //
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_PLL |
                                           SYSCTL_CFG_VCO_240), 20000000);
    #else
        SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
    #endif
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for ADC operation.
        //
        InitConsole();
    
        //
        // Display the setup on the console.
        //
        UARTprintf("ADC ->\n");
        UARTprintf("  Type: Single Ended\n");
        UARTprintf("  Samples: One\n");
        UARTprintf("  Update Rate: 250ms\n");
        UARTprintf("  Input Pin: AIN0/PE3\n\n");
    
        //
        // The ADC0 peripheral must be enabled for use.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    
        //
        // For this example ADC0 is used with AIN0 on port E7.
        // The actual port and pins used may be different on your part, consult
        // the data sheet for more information.  GPIO port E needs to be enabled
        // so these pins can be used.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
        //
        // Select the analog ADC function for these pins.
        // Consult the data sheet to see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
    
        //
        // Enable sample sequence 3 with a processor signal trigger.  Sequence 3
        // will do a single sample when the processor sends a signal to start the
        // conversion.  Each ADC module has 4 programmable sequences, sequence 0
        // to sequence 3.  This example is arbitrarily using sequence 3.
        //
        ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
    
        //
        // Configure step 0 on sequence 3.  Sample channel 0 (ADC_CTL_CH0) in
        // single-ended mode (default) and configure the interrupt flag
        // (ADC_CTL_IE) to be set when the sample is done.  Tell the ADC logic
        // that this is the last conversion on sequence 3 (ADC_CTL_END).  Sequence
        // 3 has only one programmable step.  Sequence 1 and 2 have 4 steps, and
        // sequence 0 has 8 programmable steps.  Since we are only doing a single
        // conversion using sequence 3 we will only configure step 0.  For more
        // information on the ADC sequences and steps, reference the datasheet.
        //
        ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE |
                                 ADC_CTL_END);
    
        //
        // Since sample sequence 3 is now configured, it must be enabled.
        //
        ADCSequenceEnable(ADC0_BASE, 3);
    
        //
        // Clear the interrupt status flag.  This is done to make sure the
        // interrupt flag is cleared before we sample.
        //
        ADCIntClear(ADC0_BASE, 3);
    
        //
        // Sample AIN0 forever.  Display the value on the console.
        //
        while(1)
        {
            //
            // Trigger the ADC conversion.
            //
            ADCProcessorTrigger(ADC0_BASE, 3);
    
            //
            // Wait for conversion to be completed.
            //
            while(!ADCIntStatus(ADC0_BASE, 3, false))
            {
            }
    
            //
            // Clear the ADC interrupt flag.
            //
            ADCIntClear(ADC0_BASE, 3);
    
            //
            // Read ADC Value.
            //
            ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);
    
            //
            // Display the AIN0 (PE3) digital value on the console.
            //
            UARTprintf("AIN0 = %4d\r", pui32ADC0Value[0]);
    
            //
            // This function provides a means of generating a constant length
            // delay.  The function delay (in cycles) = 3 * parameter.  Delay
            // 250ms arbitrarily.
            //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
            SysCtlDelay(ui32SysClock / 12);
    #else
            SysCtlDelay(SysCtlClockGet() / 12);
    #endif
        }
    }

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

    我已将 ADC 输入与已知良好的工作台电源绑定,例如,在3.3V 时,我仍然看到这些输出。  0伏时,我看到的是较小的铁,频率较低。  我可能偶尔会看到低于64的数值弹出,但比我在3V 时看到的频率要低得多。  在6V 时,我应该看到稳定的4095,我看到更频繁的下降到较低的值。

    我无法在没有大量更改的情况下运行该代码,因为我没有这些 PIN,没有 UART 等。 我看到的唯一真正区别是 SysClockFreqSet()中的不同值。  

    我感谢你努力解决这一问题。

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

    我想知道 ADC 输入引脚上的外部阻抗是多少? 如果电压分配器过大,则会影响充电将输入电压传输到内部采样电容器所需的时间。 将您的新板与您以前的工作板进行比较。 您是否看到任何显著的区别? 最好是针脚的外部阻抗 应较小。  

     还有一个问题是您有多少块新的主板? 您可以在所有主板上重复同样的问题,还是只在一个主板上重复同样的问题?

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

    您还可以尝试以实验的一半速率采集样本吗? 这可以让输入电压有更多的时间稳压,从而可以确定外部阻抗是否存在问题。  

    ADCClockConfigSet (ADC0_BASE,ADC_CLOCK,SRC_PIOSC | ADC_CLOCK,RATE_Half,1);

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

    我刚刚尝试过这种方法。  下限值没有明显变化。  我还将延迟乘以10,所以我得到了1秒的样本。  我也没有看到任何变化,也许五分之一的人还低于预期。   

    为了回答上一个问题,我们通常会获得一些用于开发的无涂层板。  我向设计电路板的 EE 发送了相同的代码,他在样品上运行了该代码,结果相同。  他只有一个长凳供他使用。

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

    也许还有一些要检查和试验的东西。

    -您的外部参考电压是否稳定?

    ——您能否注释 出 ADCReferenceSet(ADC0_BASE,ADC_REF_EXT_3V),以便使用内部引用。  

    -您目前使用  ADC_CTL_CH13。 为什么不尝试其他通道,如 ADC_CTL_CH0,并将其连接到 GND,1.65V 和3.3V。 您获得了哪些转换值?

     ——对于实验,如果可能,您能否在 ADC 引脚前添加运算放大器?

     我真的建议你能找到 LaunchPad 并在它上运行代码。 它将帮助确定问题是与主板相关还是与软件相关。 目前,我无法找到您的代码有什么问题。  

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

    我尝试使用外部参考,但我看到的波动也是一样的。

    我不知道这张图像是如何通过的,但这是从操纵杆直接输入到 M4上的针脚的输入线。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="243658" url="~ë/support/icles/arm-based 微处理器组/基于 ARM 的微控制器/f/arm-based 微控制器-forum/1075201/tm4c129encpdt-occase-drop-read-dime-dc/3979327#3979327"]我尝试使用外部波动,但见相同的引用。[

    我想你是指内部参考。  

    [引用 userid="243658" url="~ë/support/icler/arm-based 微处理器组/基于 ARM 的微控制器/f/arm-based 微控制器-forum/1075201/tm4c129encpdt-occase-drop-read-dime-do-dc/3979327#3979327"]

    我不知道这张图像是如何通过的,但这是从操纵杆直接输入到 M4上的针脚的输入线。

    [/引用]

    我可以告诉您,您的外部阻抗似乎有一个运算放大器和较低的阻抗。  

    我真的不知道有什么问题。  我不知道您是否有与 CH13的交叉交谈。  请按照我的建议尝试其他频道,如果您有启动板,请尝试其他频道。 对于我之前展示的 TivaWare 示例,您只需删除主板上没有的任何内容。 我希望您的主板上有 AIN0,您可以通过将其连接到0V,1.65V 或3.3V 来进行实验。 如果是 AIN0,请尝试您的主板上的任何其它可用通道,并查看您是否可以重现问题 (如 CH13)。  

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

    你好,詹姆斯,

    似乎您的轴向电位计代码没有任何可用于控制放大器意外电位计扑动的反跳(如果有的话)。  如果 Charles Ideas 没有产生预期结果,我会检查勘误表中的输入通道,以避免出现任何输入通道。 我可以发布一个代码段,该代码段会取消信道输入,从而删除扑动元件,只需这样说。  

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

    看一下会很棒。  谢谢。

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

    我们找到了一种方法绕过主板上的其他内容,直接进入 PE3/AIN0,所以我将代码更改为从那里读取。  完全相同的问题,所以我认为必须有一些事情来定期中断转换。  这个项目还有一些其他的事情要做,所以我将为此创建一个单独的项目,看看它是否清理了任何东西。  感谢你的帮助。

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

    你好,詹姆斯,

     我现在要结束这条线程。 如果您有一些更新,您只需再次写入此帖子,它将自动重新打开该线程。  

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

    复制到项目文件夹调用 init() ,然后使用原始序列发生器数组变量类型转换调用去抖函数,如 Mydebouncedpot32bitVar=calltodebounce (rawadcpotdata)。 它可以 在 ADC 触发中断处理程序中调用,并从模拟输入返回的电位计数据。

    /CFS 文件/__key/communityserver-discussion-components-files/908/analogue_2D00_pot.zip