TM4内部ADC采集数据的问题



我尝试用M4的内部ADC进行两路数据采集,将采集到的数据放到一个数组中,但发现两路采集到的数据在放置到数组中时好像毫无规律,两路数据完全混到一起。是不是我哪里配置的有问题,希望好心人解答下~~~~~~

void ADCInit(void)
{
	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_3|GPIO_PIN_2);

	ADCReferenceSet(ADC0_BASE,ADC_REF_INT);
	ADCSequenceConfigure(ADC0_BASE,SEQ_NUM,ADC_TRIGGER_ALWAYS,0);//SEQ_NUM宏定义为2

	ADCSequenceStepConfigure(ADC0_BASE,SEQ_NUM,0,ADC_CTL_CH0);
	ADCSequenceStepConfigure(ADC0_BASE,SEQ_NUM,1,ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END );

	ADCSequenceEnable(ADC0_BASE, SEQ_NUM);


	ADCIntRegister(ADC0_BASE,SEQ_NUM,ADC0IntHander);
	ADCIntClear(ADC0_BASE,SEQ_NUM);
	ADCIntEnable(ADC0_BASE,SEQ_NUM);
}

下面是ADC中断函数:

void ADC0IntHander(void)
{
	uint32_t temp[8]={0};

	ADCSequenceDataGet(ADC0_BASE,SEQ_NUM,temp);
	ADCIntClear(ADC0_BASE,SEQ_NUM);//这里设置断点
}

我在PB3(AIN0)加的是1.5VDc,PB2(AIN1)接地

下面是几次运行至断点的数组内容:

  • 我觉得这样的现象正常吧,由于你开的是两路AD,共同访问一个数组,并改写他的值,而且用的是中断,出现这样的情况正常,楼主试试不用中断,读完AIN0的值,再度AIN1的值,这样肯定不会混乱了

  • 额。。不用中断的话。。会影响其他模块吧。。。不明白这个为什么会这样,采样的配置函数明明是配置了步骤的呀,但猜出来的数据怎么会是乱的呢

  • 分享一个ADC多路采样,中断读取的代码。这个测试过没问题的。

    //*****************************************************************************
    //
    // single_ended.c - Example demonstrating how to configure the ADC for
    // single ended operation.
    //
    // Copyright (c) 2010-2013 Texas Instruments Incorporated. All rights reserved.
    // Software License Agreement
    //
    // 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.
    //
    // This is part of revision 1.1 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************

    #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"

    #include "driverlib/interrupt.h"

    #include "inc/hw_ints.h"
    #include "inc/hw_types.h"
    #include "inc/hw_adc.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/PE7.
    //!
    //! 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 - PE7
    //!
    //! 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.
    //
    //*****************************************************************************
    #define ADCSAMPLERATE_1MSPS 0x7 // 1,000,000 samples per second
    #define ADCSAMPLERATE_500KSPS 0x5 // 500,000 samples per second
    #define ADCSAMPLERATE_250KSPS 0x3 // 250,000 samples per second
    #define ADCSAMPLERATE_125KSPS 0x1 // 125,000 samples per second
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************

    uint32_t pui32ADC0Value[8];
    uint32_t Data[8]={0};
    uint32_t TempVal = 0;
    uint32_t TempVal2 = 0;

    void ADCSampleRateSet(uint32_t ui32Speed)
    {
    //
    // Set the ADC speed
    //
    HWREG(ADC0_BASE + ADC_O_PC) = (ui32Speed);
    }

    uint32_t ADCSampleRateGet(void)
    {
    //
    // Return the current ADC speed.
    //
    return((HWREG(ADC0_BASE + ADC_O_PC) & 0x0f));
    }


    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);
    }


    void ADC0Sequence0Isr(void)
    {

    uint16_t i;
    //
    // Clear the ADC interrupt flag.
    //
    ADCIntClear(ADC0_BASE, 0);

    //
    // Read ADC Value.
    //
    ADCSequenceDataGet(ADC0_BASE, 0, pui32ADC0Value);


    for(i = 0;i < 8;i ++)
    {
    Data[i] = pui32ADC0Value[i]*3300/4096;
    }
    SysCtlDelay(1);
    }

    //*****************************************************************************
    //
    // 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)
    {
    //
    // 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[8];
    //uint32_t Data[8]={0};
    //
    // 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.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
    SYSCTL_XTAL_16MHZ);

    //
    // 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/PE7\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_GPIOD);
    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_PORTD_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);


    //set sample rate
    ADCSampleRateSet(ADCSAMPLERATE_1MSPS);

    //
    // 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, 0, 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, 0, 0, ADC_CTL_CH0 );//PE3
    ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH1 );//PE2
    ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH2 );//PE1
    ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH3 );//PE0
    ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH4 );//PD3
    ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_CH5 );//PD2
    ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_CH6 );//PD1
    ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_CH7 | ADC_CTL_IE |ADC_CTL_END);

    ADCIntEnable(ADC0_BASE, 0);
    IntEnable(INT_ADC0SS0);
    IntMasterEnable();

    ADCIntClear(ADC0_BASE, 0);
    //
    // Since sample sequence 3 is now configured, it must be enabled.
    //
    ADCSequenceEnable(ADC0_BASE, 0);

    //
    // Clear the interrupt status flag. This is done to make sure the
    // interrupt flag is cleared before we sample.
    //

    TempVal = ADCSampleRateGet();

    //
    // Sample AIN0 forever. Display the value on the console.
    //
    while(1)
    {
    //
    // Trigger the ADC conversion.
    //
    ADCProcessorTrigger(ADC0_BASE, 0);

    /*
    //
    // Wait for conversion to be completed.
    //
    while(!ADCIntStatus(ADC0_BASE, 0, false))
    {
    }

    //
    // Clear the ADC interrupt flag.
    //
    ADCIntClear(ADC0_BASE, 0);

    //
    // Read ADC Value.
    //
    ADCSequenceDataGet(ADC0_BASE, 0, pui32ADC0Value);

    */
    /*
    Data[0] = pui32ADC0Value[0]*3300/4096;
    Data[1] = pui32ADC0Value[1]*3300/4096;
    Data[2] = pui32ADC0Value[2]*3300/4096;
    Data[3] = pui32ADC0Value[3]*3300/4096;
    Data[4] = pui32ADC0Value[4]*3300/4096;
    Data[5] = pui32ADC0Value[5]*3300/4096;
    Data[6] = pui32ADC0Value[6]*3300/4096;
    Data[7] = pui32ADC0Value[7]*3300/4096;
    */
    //
    // Display the AIN0 (PE7) 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.
    //
    SysCtlDelay(SysCtlClockGet() / 12);
    }
    }