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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1333341/tm4c129encpdt-adc-reading-not-correct

器件型号:TM4C129ENCPDT

您好!

我已经配置了微控制器的内部 ADC。 我会收到正确的 AIN0、 AIN1、AIN2 、AIN3值 、但对于 AIN8和 AIN9、会输出错误的值。 我想它是否与通道顺序有关、因为 AIN3和 AIN8之间缺少 ADC 通道。

我已经为上述信号配置了控制器的端口 E。

以下是我的代码;

端口引脚定义 如下所示;

uint32_t IntADCRawData0[8]; //Buffer array that holds ADC samples

//On Board ADC Signals Pins map connected to microcontroller internal ADC
#define ADC_PIN_33Volt GPIO_PIN_0
#define ADC_PIN_5Volt GPIO_PIN_1
#define ADC_PIN_15NegVolt GPIO_PIN_2
#define ADC_PIN_15PosVolt GPIO_PIN_3
#define ADC_PIN_VCF GPIO_PIN_4
#define ADC_PIN_VC2 GPIO_PIN_5


#define ADC_CH_33Volt           ADC_CTL_CH3 //PE0 = AIN3
#define ADC_CH_5Volt            ADC_CTL_CH2 //PE1 = AIN2
#define ADC_CH_15NegVolt        ADC_CTL_CH1 //PE2 = AIN1
#define ADC_CH_15PosVolt        ADC_CTL_CH0 //PE3 = AIN0
#define ADC_CH_VCFVolt          ADC_CTL_CH9 //PE4 = AIN9
#define ADC_CH_VC2Volt          ADC_CTL_CH8 //PE5 = AIN8

ADC INIT 函数就在这里;

void Internal_ADC0_Init(void)
{
    //First configure common ADC Ports and Pins
    // *** Peripheral Enable
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOE);
    SysCtlDelay(100);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    SysCtlDelay(100);

    //Configure the individual pins being used as ADC input pins
    ROM_GPIOPinTypeADC(GPIO_PORTE_BASE, ADC_PIN_VC2 | ADC_PIN_VCF | ADC_PIN_15PosVolt | ADC_PIN_15NegVolt | ADC_PIN_5Volt | ADC_PIN_33Volt);

    ROM_ADCReferenceSet(ADC0_BASE,ADC_REF_INT);

    ROM_ADCSequenceDisable(ADC0_BASE, 0);  //Disable sequence before we change it

    ROM_ADCSequenceConfigure(ADC0_BASE,0,ADC_TRIGGER_PROCESSOR,0); //ADC Trigger by Processor

    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,0,ADC_CH_15PosVolt); //To sample Channel 0
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,1,ADC_CH_15NegVolt); //To sample Channel 1
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,2,ADC_CH_5Volt); //To sample Channel 2
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,3,ADC_CH_33Volt); //To sample Channel 3
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,4,ADC_CH_VC2Volt); //To sample Channel 8
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,5,ADC_CH_VCFVolt); //To sample Channel 9


    ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64); //Configure the hardware Averager module to average out 64 samples for each channel.

    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,6,ADC_CTL_TS|ADC_CTL_IE|ADC_CTL_END);

    ROM_ADCSequenceEnable(ADC0_BASE,0);
}

初始化后、我会调用以下函数来收集数据并保存到不同的变量中。

//This function collects data from internal ADC and saves at the pointer location.
void IntADC_Collect_Data(void)
{

        // Trigger the sample sequence.
        ADCProcessorTrigger(ADC0_BASE, 0);

        //while(!ADCIntStatus(ADC0_BASE, 0, false)){} //DO NOT use this while loop as it may take forever instead use a delay
        vTaskDelay(10/portTICK_PERIOD_MS); // 10msec delay
        
        ADCSequenceDataGet(ADC0_BASE, 0, IntADCRawData0);

        volt15Pos.data.value16bits              =   0x0000FFFF & IntADCRawData0[0];
        volt15Neg.data.value16bits              =   0x0000FFFF & IntADCRawData0[1];
        volt5.data.value16bits                  =   0x0000FFFF & IntADCRawData0[2];
        volt33.data.value16bits                 =   0x0000FFFF & IntADCRawData0[3];
        VC2DAC_ReadBack.data.value16bits        =   0x0000FFFF & IntADCRawData0[4];
        VCFDAC_ReadBack.data.value16bits        =   0x0000FFFF & IntADCRawData0[5];
        ProcessorTemp.data.value16bits          =   0x0000FFFF & IntADCRawData0[6];
        Kicker_Spare_Temp.data.value16bits      =   0x0000FFFF & IntADCRawData0[7]; //This is just a place holder since in case of Septum Kicker_Spare_Temp doesnt exist

}

如前所述、我们可以正确读取  AIN0、 AIN1、 AIN2、AIN3 的所有值、但 AIN8和 AIN9的所有值不报告正确的值。

有任何想法/提示吗?

谢谢

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

    您好!

     我有几个问题和评论:

     -你说不正确的价值是什么意思? 您是说它们是完全随机的值吗? 如果您将 AIN8/AIN9接地或连接到3.3V 会怎样。 多少钱?

     -可以在 LaunchPad 上重复同样的问题吗?

     -为了进行实验,您可以在 AIN0之前移动 AIN8和 AIN9。 换句话说、使 AIN8和 AIN9成为步骤0和1。 结果是什么?

     -对于实验,你可以禁用硬件平均? 结果是什么?

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

    它们并不是完全随机的、因为如果引脚上的实际电压发生变化、它们会报告相应的变化。 但它们不是可重复的、例如、如果您将输入设置为2V、它们可能报告2.5V 电压、现在如果您更改输入引脚电压、增大或减小 ADC 将保持不变。 重新启动电路板后、重复执行 ADC 操作并在输入引脚处设置2V、ADC 可能会报告完全不同的值、例如3.1V、同样、如果您增大或减小引脚电压、ADC 将会相应地移动。 但在一段时间内、它不会移动并保持在同一水平。

    我已尝试将 AIN8与 AIN0交换、但交换后问题会出现。

    我已尝试禁用硬件均值计算、但未生效。

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

    在 intADC_ltd 中 Collect_Data、 为什么不使用  while (! ADCIntStatus (ADC0_BASE、0、false)){}并改用 TaskDelay? 在完成 ADC FIFO 读取之前、您可能已经过快、尤其是在使用平均值计算时。 为什么不首先删除平均电路和使用 while (! ADCIntStatus (ADC0_BASE、0、false){}。 请参阅以下 TivaWare 示例。 您觉得有什么区别吗? 您尚未告诉我 LaunchPad 的结果是什么? 您看到相同之处吗?

    //
    ///触发 ADC 转换
    //
    ADCProcessorTrigger (ADC0_BASE、3);

    //
    //等待转换完成。
    //
    while (! ADCIntStatus (ADC0_BASE、3、false)
    {

    //
    //清除 ADC 中断标志。
    //
    ADCIntClear (ADC0_BASE、3);

    //
    //读取 ADC 值。
    //
    ADCSequenceDataGet (ADC0_BASE、3、pui32ADC0Value);

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

    我已经删除了硬件平均值。 我正在等待10毫秒,而不是使用 while ()循环,这应该是足够的。 我可以增加该延迟。 在开发板上尝试我的代码将需要付出很多努力、我可能有一天会尝试一些。 但我有一些有用的东西可以报告给大家。 我看到 AIN9报告正确、但 AIN8报告不正确。 这意味着所有通道 AIN0、AIN1、AIN2、AIN3、AIN9都正确报告、只有 AIN8报告 错误的值。 我能够读取引脚电压、因此我确定引脚上有什么、但 ADC 报告了错误的值。  

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

    您好!

     如果在 AIN8和 AIN9之间交换顺序、该怎么办? 结果如何。 我在勘误表中找不到任何可以解释您得出的结果的地方。

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

    尊敬的 Charles:

    我发现这是 AIN8引脚的干货.. 它现在正在工作。 感谢您的帮助、祝您愉快。