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.

[参考译文] TM4C123GH6PM:PE0 和 PE1 引脚上 CH2 和 CH3 之间的 ADC 串扰

Guru**** 2903660 points

Other Parts Discussed in Thread: TM4C123GH6PM, DRV8801

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1584021/tm4c123gh6pm-adc-crosstalk-between-ch2-and-ch3-on-pins-pe0-and-pe1

器件型号: TM4C123GH6PM
主题中讨论的其他器件: DRV8801

您好:

我的定制 TM4C123GH6PM 板出现了一些(很少)的问题读数、因此我创建了一个简单的程序来隔离将在 Tiva-c tm4c123 评估板上运行的问题。

1.其中一个频道有一个不可解释的偏倚

2.通道间的串扰很小,一个影响到另一个。

问题仍然存在并且可以观察到。 发生的情况是、如果我将一个通道悬空并对另 一个通道施加 3V3、一个通道读取 3V3、另一个通道(悬空)读取 2v9、反之亦然。 在实际电路板上、没有 ADC 引脚悬空、有一个 33nf 电容器接地、电压来自 10K 电阻器。 (DRV8801 的 VPROPI 引脚)

这几乎就像过时数据停留在 ADC FIFO 中、即 ADC 的采样/保持一样。 是否有解决此问题的方法? 这在之前的论坛中讨论过、但没有在相同的设置下讨论。

也许我可以使用单个序列、从 ch3 从 ch2 采样一个? 也许我可以将一个引脚分配给 ADC0、将另一个引脚分配给 ADC1? 在试错之前、我想在这个论坛上提问。

其他发现结果:a. ADC 速度越快、交叉耦合越多。 B.单独使用 ADC0 和 ADC1 不会消除交叉耦合 C。我们实际上同时对两个通道进行采样、这将是一次又一次的中断、一个具有优先级 1、另一个具有优先级 2 — 我们可能会在 ADC 通道上引入相移。

此致、

c.

以下是我的完整代码:

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>


#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"

#include "driverlib/fpu.h"
#include "driverlib/timer.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/adc.h"

#include "utils/uartstdio.h"
#include "utils/ustdlib.h"

#define RED_LED GPIO_PIN_1   // PF1
#define GREEN_LED GPIO_PIN_3 // PF3

#define EMA_ALPHA 15.0f
#define EMA_DIV 16.0

#define ADC_MULTIPLIER 0.000805664;

uint32_t ui32SysClkFreq;
char loginfo_buffer[128];

uint32_t adc_fifo_left_load[4];
uint32_t adc_fifo_right_load[4];
volatile uint32_t adc_ch1;
volatile uint32_t adc_ch2;

volatile float ch1 = 0.0f;
volatile float ch2 = 0.0f;

volatile float avg_ch1 = 0.0f;
volatile float avg_ch2 = 0.0f;

void ADC0SS1IntHandler(void) {
    MAP_ADCIntClear(ADC0_BASE, 1);
    MAP_ADCSequenceDataGet(ADC0_BASE, 1, adc_fifo_right_load);
    adc_ch2 = ( adc_fifo_right_load[0] + adc_fifo_right_load[1] + adc_fifo_right_load[2] + adc_fifo_right_load[3] ) / 4;
    ch2 = adc_ch2 * ADC_MULTIPLIER;
    avg_ch2 = ( (EMA_ALPHA * avg_ch2) + ch2 ) / EMA_DIV;
}

void ADC0SS2IntHandler(void) {
    MAP_ADCIntClear(ADC0_BASE, 2);
    MAP_ADCSequenceDataGet(ADC0_BASE, 2, adc_fifo_left_load);
    adc_ch1 = ( adc_fifo_left_load[0] + adc_fifo_left_load[1] + adc_fifo_left_load[2] + adc_fifo_left_load[3] ) / 4;
    ch1 = adc_ch1 * ADC_MULTIPLIER;
    avg_ch1 = ( (EMA_ALPHA * avg_ch1) + ch1 ) / EMA_DIV;
}

void init_serial(void) {
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
    MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    MAP_UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTStdioConfig(0, 115200, 16000000);
}

void init_gpio(void) {

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, RED_LED);
    MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, RED_LED, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);

    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GREEN_LED);
    MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GREEN_LED, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);

}

int main(void) {

    MAP_FPUEnable();
    MAP_FPULazyStackingEnable();
    MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_20MHZ | SYSCTL_OSC_MAIN);

    ui32SysClkFreq = MAP_SysCtlClockGet();

    init_gpio();

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);                                                 // enable ADC0
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0));

    MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1);                                   // PE0, PE1
    MAP_ADCReferenceSet(ADC0_BASE, ADC_REF_INT);                                                    // Use internal reference VDDA = 3V3

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);                                               // timer2 enable

    MAP_ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 1);                                   // set adc trigger for sequence 1 pri 1
    MAP_ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 2);                                   // set adc trigger for sequence 2 pri 2

    MAP_ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH2);                                     // sequence 1 step configuration
    MAP_ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH2);
    MAP_ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH2);
    MAP_ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);

    MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH3);                                     // sequence 2 step configuration
    MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH3);
    MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH3);
    MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH3 | ADC_CTL_IE | ADC_CTL_END);

    MAP_ADCSequenceEnable(ADC0_BASE, 1);                                                            // enable sequence 1
    MAP_ADCSequenceEnable(ADC0_BASE, 2);                                                            // enable sequence 2

    MAP_ADCIntClear(ADC0_BASE, 1);                                                                  // interrupt clear sequence 1
    MAP_ADCIntClear(ADC0_BASE, 2);                                                                  // interrupt clear sequence 2

    ADCIntRegister(ADC0_BASE, 1, ADC0SS1IntHandler);                                                // register interrupt SS1
    ADCIntRegister(ADC0_BASE, 2, ADC0SS2IntHandler);                                                // register interrupt SS2

    MAP_ADCIntEnable(ADC0_BASE, 1);                                                                 // adc interrupt int enable
    MAP_IntEnable(INT_ADC0SS1);                                                                     // enable nvic interrupt

    MAP_ADCIntEnable(ADC0_BASE, 2);                                                                 // adc interrupt int enable
    MAP_IntEnable(INT_ADC0SS2);                                                                     // enable nvic interrupt

    MAP_TimerConfigure(TIMER2_BASE, TIMER_CFG_A_PERIODIC);                                          // configure timer as periodic

    MAP_TimerLoadSet(TIMER2_BASE, TIMER_A, ui32SysClkFreq / 16000);                                 // sampling at 16khz default
    MAP_TimerControlTrigger(TIMER2_BASE, TIMER_A, true);                                            // enable the ADC trigger output for Timer A

    init_serial();

    MAP_IntMasterEnable();

    MAP_TimerEnable(TIMER2_BASE, TIMER_A);                                                          // always running, trigger is g_ADC_SAMPLING

    uint8_t len = sprintf(loginfo_buffer, "SYSINIT");
    UARTprintf(loginfo_buffer, len);

    while(true) {
        len = sprintf(loginfo_buffer, "%f %f\n", avg_ch1, avg_ch2);
        UARTprintf(loginfo_buffer, len);
        MAP_SysCtlDelay(100000);
    }

}