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.

[参考译文] MSP430F5529:带有 DMA 的 ADC、将意外值写入阵列

Guru**** 2481625 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1278130/msp430f5529-adc-with-dma-unexpected-values-written-to-array

器件型号:MSP430F5529
主题中讨论的其他器件:MSP430WARE

我正在尝试实现循环 ADC 方案、在该方案中、连续读取4个通道、并使用 DMA 将值更新到阵列。 我已经使用来自 MSP430ware 驱动程序库的示例将这一点连接在一起。

轮询按预期工作,当允许 main()终止并且允许 DMA 自行运行时,数组中的预期值将被允许。 如果 main ()中有内容,比如 while (1)对这个 ADC 数据执行一些操作,则在数组中找到的 ADC 值总是非常低。 预期值在1000左右时变为0或接近零。 这些值确实会发生变化、因此会错误地进行更新。

我真的不明白为什么在 MCU 执行操作时会有意外的值被写入到数组中;我会用一个更简单的时间来理解没有任何值或不变的值。

提前感谢您的任何帮助。

#include "driverlib.h"
#include <dma.h>

volatile uint16_t adcDmaTarget[NUMDMAWORDS];

//*****************************************************************************
//
//Configure DMA
//
//*****************************************************************************

void configDma(void) {

    DMA_enableRoundRobinPriority();

    DMA_initParam dmaParam0 = {0};
    dmaParam0.channelSelect = DMA_CHANNEL_0;
    dmaParam0.transferModeSelect = DMA_TRANSFER_REPEATED_SINGLE;
    dmaParam0.transferSize = NUMDMAWORDS;
    dmaParam0.triggerSourceSelect = DMA_TRIGGERSOURCE_24;
    dmaParam0.transferUnitSelect = DMA_SIZE_SRCWORD_DSTWORD;
    dmaParam0.triggerTypeSelect = DMA_TRIGGER_RISINGEDGE;
    DMA_init(&dmaParam0);

    DMA_setSrcAddress(DMA_CHANNEL_0,
                      ADC12_A_getMemoryAddressForDMA(ADC12_A_BASE,ADC12_A_MEMORY_0),
                      DMA_DIRECTION_UNCHANGED);

    DMA_setDstAddress(DMA_CHANNEL_0,
                      (uint32_t)(uintptr_t)&adcDmaTarget,
                      DMA_DIRECTION_INCREMENT);

    DMA_clearInterrupt(DMA_CHANNEL_0);

    DMA_enableInterrupt(DMA_CHANNEL_0);

    DMA_enableTransfers(DMA_CHANNEL_0);

void configAdc(void) {

    //Enable A/D channel inputs
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,
        GPIO_PIN0 |
        GPIO_PIN1 |
        GPIO_PIN2 |
        GPIO_PIN3
        );

    //Initialize the ADC12_A Module
    /*
     * Base address of ADC12_A Module
     * Use internal ADC12_A bit as sample/hold signal to start conversion
     * USE MODOSC 5MHZ Digital Oscillator as clock source
     * Use default clock divider of 1
     */
    ADC12_A_init(ADC12_A_BASE,
        ADC12_A_SAMPLEHOLDSOURCE_SC,
        ADC12_A_CLOCKSOURCE_ACLK,
        ADC12_A_CLOCKDIVIDER_1);

    ADC12_A_enable(ADC12_A_BASE);

    /*
     * Base address of ADC12_A Module
     * For memory buffers 0-7 sample/hold for 256 clock cycles
     * For memory buffers 8-15 sample/hold for 4 clock cycles (default)
     * Enable Multiple Sampling
     */
    ADC12_A_setupSamplingTimer(ADC12_A_BASE,
        ADC12_A_CYCLEHOLD_64_CYCLES,
        ADC12_A_CYCLEHOLD_64_CYCLES,
        ADC12_A_MULTIPLESAMPLESENABLE);

    //Configure Memory Buffers
    /*
     * Base address of the ADC12_A Module
     * Configure memory buffer 0
     * Map input A0 to memory buffer 0
     * Vref+ = AVcc
     * Vref- = AVss
     * Memory buffer 0 is not the end of a sequence
     */
    ADC12_A_configureMemoryParam param0 = {0};
    param0.memoryBufferControlIndex = ADC12_A_MEMORY_0;
    param0.inputSourceSelect = ADC12_A_INPUT_A0;
    param0.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_AVCC;
    param0.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_AVSS;
    param0.endOfSequence = ADC12_A_NOTENDOFSEQUENCE;
    ADC12_A_configureMemory(ADC12_A_BASE ,&param0);

    /*
     * Base address of the ADC12_A Module
     * Configure memory buffer 1
     * Map input A1 to memory buffer 1
     * Vref+ = AVcc
     * Vref- = AVss
     * Memory buffer 1 is not the end of a sequence
     *
     */
    ADC12_A_configureMemoryParam param1 = {0};
    param1.memoryBufferControlIndex = ADC12_A_MEMORY_1;
    param1.inputSourceSelect = ADC12_A_INPUT_A1;
    param1.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_AVCC;
    param1.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_AVSS;
    param1.endOfSequence = ADC12_A_NOTENDOFSEQUENCE;
    ADC12_A_configureMemory(ADC12_A_BASE ,&param1);
    /*
     * Base address of the ADC12_A Module
     * Configure memory buffer 2
     * Map input A2 to memory buffer 2
     * Vref+ = AVcc
     * Vref- = AVss
     * Memory buffer 2 is not the end of a sequence
     */
    ADC12_A_configureMemoryParam param2 = {0};
    param2.memoryBufferControlIndex = ADC12_A_MEMORY_2;
    param2.inputSourceSelect = ADC12_A_INPUT_A2;
    param2.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_AVCC;
    param2.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_AVSS;
    param2.endOfSequence = ADC12_A_NOTENDOFSEQUENCE;
    ADC12_A_configureMemory(ADC12_A_BASE ,&param2);
    /*
     * Base address of the ADC12_A Module
     * Configure memory buffer 3
     * Map input A3 to memory buffer 3
     * Vr+ = AVcc
     * Vr- = AVss
     * Memory buffer 3 IS the end of a sequence
     */
    ADC12_A_configureMemoryParam param3 = {0};
    param3.memoryBufferControlIndex = ADC12_A_MEMORY_3;
    param3.inputSourceSelect = ADC12_A_INPUT_A3;
    param3.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_AVCC;
    param3.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_AVSS;
    param3.endOfSequence = ADC12_A_ENDOFSEQUENCE;
    ADC12_A_configureMemory(ADC12_A_BASE ,&param3);


    //Using DMA transfer instead!

    //Enable memory buffer 3 interrupt
    /*
    ADC12_A_clearInterrupt(ADC12_A_BASE,
        ADC12IFG3);
    ADC12_A_enableInterrupt(ADC12_A_BASE,
        ADC12IE3);
    */

    //Enable/Start first sampling and conversion cycle
    /*
     * Base address of ADC12_A Module
     * Start the conversion into memory buffer 0
     * Use the repeated sequence of channels
     */
    ADC12_A_startConversion(ADC12_A_BASE,
        ADC12_A_MEMORY_0,
        ADC12_A_REPEATED_SEQOFCHANNELS);
}

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

    你好、Hardy、

    您可以尝试在 DMA 中断中对数组执行一些操作吗?  

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

    愚蠢的错误...

    我没有递增 DMA 源。 哎呀! 将 nochange 更改为递增固定值。

    谢谢你。

    DMA_setSrcAddress (DMA_CHANNEL_0、
    ADC12_A_getMemoryAddressForDMA (ADC12_A_BASE、ADC12_A_MEMORY_0)、
    dma_direction_increment);

    DMA_setDstAddress (DMA_CHANNEL_0、
    (uint32_t)(uintptr_t)&adcDmaTarget、
    dma_direction_increment);