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.

[参考译文] MSPM0G3507:ADC 噪声问题、这似乎与采样时钟分频器和 CPUCLK 有关

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1392995/mspm0g3507-adc-noise-issue-it-seems-to-be-related-to-sample-clock-divider-and-cpuclk

器件型号:MSPM0G3507

工具与软件:

您好!

当我使用 ADC 来收集值时、有一些事情发生:当采样时钟分频器= 1或2时、一切看起来正常。 但当采样时钟分频器= 24时、我收到一些噪声、正常情况下的图片如下所示。 同时还有一件有趣的事情。 如果我将 CPUCLK 减少到40M、无论采样时钟分频器是什么、都是正常的。 原因是什么? 我如何考虑 CPUCLK = 80M 和采样时钟分频器= 24? ?  ADC 时钟源为 ULPCLK

感谢您的帮助

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

    您好!

    您能否针对发现的此问题提供测试代码? 我们可以对其进行研究、并检查可能存在的问题。  

    此致、

    Cash Hao

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

    您好、Cash Hao、

    谢谢、我从 mspm0_sdk 导入"adc12_triggered_by_timer_event_lp_MSPM0G3507_nortos_ticlang"。

    下面是我所做的更改
    1.添加 UART 打印(UART0,波特率:115200)  

    2.时钟树:启用 HFXT (40M)、选择 XTAL、选择 HFCLK、将 QDIV 设置为 x4、 选择 SYSPLL0、将 UDIV 设置 为/2

    在 ADC12中、将 ADC 时钟源更改为 ULPCLK、将采样时钟分频器设置为24分频、将基准电压设置为 VREF

    4.启用 VREF、MODE 设置为外部、VREF+-启用且外部电压设置为1.5

    FB

    /*
     * Copyright (c) 2021, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include "ti_msp_dl_config.h"
    
    #define ADC_SAMPLE_SIZE (1024)
    /* When FIFO is enabled 2 samples are compacted in a single word */
    #define ADC_FIFO_SAMPLES (ADC_SAMPLE_SIZE >> 1)
    
    uint16_t gADCSamples[ADC_SAMPLE_SIZE];
    volatile bool gCheckADC;
    
    void SendString(char *String, int Length)
    {
        int i;
        for(i = 0 ;i < Length ; i++)
        {
            DL_UART_Main_transmitData(UART_0_INST, String[i]);
            delay_cycles(8000);
        }
    
    }
    
    int main(void)
    {
        char Data[100];
        int i;
        SYSCFG_DL_init();
    
        /* Configure DMA source, destination and size */
        DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID,
            (uint32_t) DL_ADC12_getFIFOAddress(ADC12_0_INST));
    
        DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t) &gADCSamples[0]);
        DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_FIFO_SAMPLES);
    
        DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
    
        /* Setup interrupts on device */
        NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
    
        gCheckADC = false;
    
        DL_ADC12_startConversion(ADC12_0_INST);
    
    // for test ADC noise
        while (false == gCheckADC) {
            __WFE();
        }
    
        DL_ADC12_stopConversion(ADC12_0_INST);
        DL_DMA_disableChannel(DMA, DMA_CH0_CHAN_ID);
    
        for(i=0;i<ADC_SAMPLE_SIZE;i++)
        {
            sprintf(Data,"%04d\n",gADCSamples[i]);
            SendString(Data,5);
        }
    
    // end
        __BKPT(0);
    
        while (1) {
            __WFI();
        }
    }
    
    void ADC12_0_INST_IRQHandler(void)
    {
        switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
            case DL_ADC12_IIDX_DMA_DONE:
                gCheckADC = true;
                break;
            default:
                break;
        }
    }
    
    /**
     * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
     * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
     * @cliArgs --device "MSPM0G350X" --package "LQFP-64(PM)" --part "Default" --product "mspm0_sdk@2.00.01.00"
     * @versions {"tool":"1.20.0+3587"}
     */
    
    /**
     * Import the modules used in this configuration.
     */
    const ADC12  = scripting.addModule("/ti/driverlib/ADC12", {}, false);
    const ADC121 = ADC12.addInstance();
    const Board  = scripting.addModule("/ti/driverlib/Board");
    const SYSCTL = scripting.addModule("/ti/driverlib/SYSCTL");
    const UART   = scripting.addModule("/ti/driverlib/UART", {}, false);
    const UART1  = UART.addInstance();
    const VREF   = scripting.addModule("/ti/driverlib/VREF");
    
    /**
     * Write custom configuration values to the imported modules.
     */
    const divider9       = system.clockTree["UDIV"];
    divider9.divideValue = 2;
    
    const multiplier2         = system.clockTree["PLL_QDIV"];
    multiplier2.multiplyValue = 4;
    
    const mux4       = system.clockTree["EXHFMUX"];
    mux4.inputSelect = "EXHFMUX_XTAL";
    
    const mux8       = system.clockTree["HSCLKMUX"];
    mux8.inputSelect = "HSCLKMUX_SYSPLL0";
    
    const mux12       = system.clockTree["SYSPLLMUX"];
    mux12.inputSelect = "zSYSPLLMUX_HFCLK";
    
    const pinFunction4       = system.clockTree["HFXT"];
    pinFunction4.enable      = true;
    pinFunction4.inputFreq   = 40;
    pinFunction4.HFXTStartup = 100;
    
    ADC121.$name                          = "ADC12_0";
    ADC121.repeatMode                     = true;
    ADC121.adcMem0chansel                 = "DL_ADC12_INPUT_CHAN_4";
    ADC121.sampleTime0                    = "62.5 ns";
    ADC121.powerDownMode                  = "DL_ADC12_POWER_DOWN_MODE_MANUAL";
    ADC121.enableFIFO                     = true;
    ADC121.configureDMA                   = true;
    ADC121.sampCnt                        = 6;
    ADC121.enabledDMATriggers             = ["DL_ADC12_DMA_MEM10_RESULT_LOADED"];
    ADC121.enabledInterrupts              = ["DL_ADC12_INTERRUPT_DMA_DONE"];
    ADC121.adcMem0vref                    = "VREF";
    ADC121.sampClkSrc                     = "DL_ADC12_CLOCK_ULPCLK";
    ADC121.sampClkDiv                     = "DL_ADC12_CLOCK_DIVIDE_24";
    ADC121.peripheral.$assign             = "ADC0";
    ADC121.peripheral.adcPin4.$assign     = "PB25";
    ADC121.adcPin4Config.$name            = "ti_driverlib_gpio_GPIOPinGeneric0";
    ADC121.DMA_CHANNEL.$name              = "DMA_CH0";
    ADC121.DMA_CHANNEL.addressMode        = "f2b";
    ADC121.DMA_CHANNEL.peripheral.$assign = "DMA_CH0";
    
    
    SYSCTL.forceDefaultClkConfig = true;
    SYSCTL.clockTreeEn           = true;
    
    UART1.$name                            = "UART_0";
    UART1.targetBaudRate                   = 115200;
    UART1.peripheral.rxPin.$assign         = "PA11";
    UART1.peripheral.txPin.$assign         = "PA10";
    UART1.txPinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric3";
    UART1.txPinConfig.direction            = scripting.forceWrite("OUTPUT");
    UART1.txPinConfig.hideOutputInversion  = scripting.forceWrite(false);
    UART1.txPinConfig.onlyInternalResistor = scripting.forceWrite(false);
    UART1.txPinConfig.passedPeripheralType = scripting.forceWrite("Digital");
    UART1.rxPinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric4";
    UART1.rxPinConfig.hideOutputInversion  = scripting.forceWrite(false);
    UART1.rxPinConfig.onlyInternalResistor = scripting.forceWrite(false);
    UART1.rxPinConfig.passedPeripheralType = scripting.forceWrite("Digital");
    
    VREF.basicVrefPins          = "VREF+-";
    VREF.basicMode              = "DL_VREF_ENABLE_DISABLE";
    VREF.basicExtVolt           = 1.5;
    VREF.vrefPosPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric1";
    VREF.vrefNegPinConfig.$name = "ti_driverlib_gpio_GPIOPinGeneric2";
    
    /**
     * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
     * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
     * re-solve from scratch.
     */
    pinFunction4.peripheral.$suggestSolution           = "SYSCTL";
    pinFunction4.peripheral.hfxInPin.$suggestSolution  = "PA5";
    pinFunction4.peripheral.hfxOutPin.$suggestSolution = "PA6";
    Board.peripheral.$suggestSolution                  = "DEBUGSS";
    Board.peripheral.swclkPin.$suggestSolution         = "PA20";
    Board.peripheral.swdioPin.$suggestSolution         = "PA19";
    UART1.peripheral.$suggestSolution                  = "UART0";
    VREF.peripheral.$suggestSolution                   = "VREF";
    VREF.peripheral.vrefPosPin.$suggestSolution        = "PA23";
    VREF.peripheral.vrefNegPin.$suggestSolution        = "PA21";
    

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

    您好!

    您使用的是哪个 SDK 版本?  

    最好转到 CCS 工作区、压缩项目文件并将其发送到此处。  

    此致、

    Cash Hao

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

    e2e.ti.com/.../Err80M.zip

    尊敬的 Cash:

    仅供参考、此文件是从"mspm0_sdk_2_00_01_00""adc12_max_freq_dma_lp_MSPM0G3507_nortos_ticlang"修改的

    此外、我今天也进行了一些验证。 由于错误被修复为每12个事务和错误的值发生一次、因此我尝试将"Enable DMA Triggers"从 MEM10设置为 MEM11。 该错误不存在。 是否有合理的解释?

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

    听起来像这样可疑:

    https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1393962/mspm0g3507-adc-dma-samples-count

    其中 DMA 在准备就绪前获取样本。

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

    您好!

    它应该与 e2e 问题无关。  

    在 DMA 配置中、源长度为字(4字节)。 一个 ADC 结果为2个字节。 因此、DMA 移动2个 ADC 一次产生结果。 而 DMA 样本计数为6。 因此、DMA 将连续移动6*2=12个 ADC 结果。  

    由于您的 DMA 触发器为 MEM10、因此它仅包含11个 ADC 结果。 将连续移动12个 ADC 结果。 MEMRESx 寄存器中保存的 ADC 结果处于 FIFO 模式。 DMA 将移动(11个新的 ADC 结果和1个先前的 ADC 结果)。 这就是您看到该问题的原因。  

    此致、

    Cash Hao

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

    尊敬的 Cash:

    感谢您的解释! 我明白了!

    FB

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

    尊敬的 Keith:

    谢谢!  这对我有很大帮助! 谢谢!

    FB