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.

[参考译文] MSP432E401Y:来自12位 ADC 的错误样本

Guru**** 2524500 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1069662/msp432e401y-wrong-samples-from-12-bit-adc

部件号:MSP432E401Y

我正在尝试在端口 E 的针脚 PE0到 PE3上采样 ADC。 我正在配置 ADC,如 TI 示例中所示,用于在多个通道上采样,我正在通过处理器触发器触发每个采样,我使用中断处理程序功能在采样序列发生器中获取样本。 我对 PE3和 PE2使用样本序列发生器0 (SS0),对 PE1使用 SS1,对 PE0使用 SS2。 我获得了 SS1和 SS2的合理值,但 SS0似乎是错误的。 我已配置为从 PE2中采样一个值,读取该值,然后为 PE3触发一个新值并读取该值。这只能执行一次。  

我在勘误表中看到前两个样本的值可能有误,因此在启用序列发生器之前,我在 ADC 中重置了这些值,而我忽略了前两个采样值,但我仍然得到相同的结果。 这是否是需要在这里完成的特定任务?

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

    格尔加纳,您好!

    请尝试此代码,这在我看来是正常的:

    // Initiate ADC
    void initADC(void)
    {
        /* Enable the clock to GPIO Port E and wait for it to be ready */
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE)));
    
        /* Enable the clock to GPIO Port D and wait for it to be ready */
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD)));
    
        /* Configure PD0-PD3 as ADC input channel */
        MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_3);
        MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_2);
        MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_1);
        MAP_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_0);
    
        /* Configure PE0-PE3 as ADC input channel */
        MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
        MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
        MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);
        MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
    
        /* Enable the clock to ADC-0 and wait for it to be ready */
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0)));
    
        /* Enable the clock to ADC-1 and wait for it to be ready */
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
        while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_ADC1)));
    
        /* Configure Sequencer 2 to sample the analog channel : AIN0-AIN3. The
         * end of conversion and interrupt generation is set for AIN3 */
        MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH0);
        MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH1);
        MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH2);
        MAP_ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH3 | ADC_CTL_IE | ADC_CTL_END);
    
        /* Configure Sequencer 2 to sample the analog channel : AIN0-AIN3. The
         * end of conversion and interrupt generation is set for AIN3 */
        MAP_ADCSequenceStepConfigure(ADC1_BASE, 2, 0, ADC_CTL_CH12);
        MAP_ADCSequenceStepConfigure(ADC1_BASE, 2, 1, ADC_CTL_CH13);
        MAP_ADCSequenceStepConfigure(ADC1_BASE, 2, 2, ADC_CTL_CH14);
        MAP_ADCSequenceStepConfigure(ADC1_BASE, 2, 3, ADC_CTL_CH15 | ADC_CTL_IE | ADC_CTL_END);
    
        /* Enable sample sequence 2 with a PWM signal trigger.  Sequencer 2
         * will do a single sample when the PWM0 generates a match for the Duty
         * Cycle */
        MAP_ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_PWM2, 2); // The last '2' means priority
        MAP_ADCSequenceConfigure(ADC1_BASE, 2, ADC_TRIGGER_PWM2, 2); // The last '2' means priority
    
        /* Since sample sequence 2 is now configured, it must be enabled. */
        MAP_ADCSequenceEnable(ADC0_BASE, 2);
        MAP_ADCSequenceEnable(ADC1_BASE, 2);
    
        /* Clear the interrupt status flag before enabling. This is done to make
         * sure the interrupt flag is cleared before we sample. */
        MAP_ADCIntClear(ADC0_BASE, 2);
        MAP_ADCIntEnable(ADC0_BASE, 2);
        MAP_ADCIntClear(ADC1_BASE, 2);
        MAP_ADCIntEnable(ADC1_BASE, 2);
    
        /* Enable the Interrupt generation from the ADC-0 Sequencer */
        MAP_IntEnable(INT_ADC0SS2);
        MAP_IntEnable(INT_ADC1SS2);
    }
    
    
    // ADC0 ISR
    void ADC0SS2_IRQHandler(void)
    {
        uint32_t getIntStatus;
    
        DEBUG_PP4_H();
    
        /* Get the interrupt status from the ADC */
        getIntStatus = MAP_ADCIntStatus(ADC0_BASE, 2, true);
    
        /* If the interrupt status for Sequencer-3 is set the
         * clear the status and read the data */
        if(getIntStatus == ADC_INT_SS2)
        {
            /* Clear the ADC interrupt flag. */
            MAP_ADCIntClear(ADC0_BASE, 2);
    
            /* Read ADC Value. */
            MAP_ADCSequenceDataGet(ADC0_BASE, 2, MotorStatus.currentstate.ADC0RawData);
        }
    
        DEBUG_PP4_L();
    }
    
    // ADC1 ISR
    void ADC1SS2_IRQHandler(void)
    {
        uint32_t getIntStatus;
    
        /* Get the interrupt status from the ADC */
        getIntStatus = MAP_ADCIntStatus(ADC1_BASE, 2, true);
    
        /* If the interrupt status for Sequencer-3 is set the
         * clear the status and read the data */
        if(getIntStatus == ADC_INT_SS2)
        {
            /* Clear the ADC interrupt flag. */
            MAP_ADCIntClear(ADC1_BASE, 2);
    
            /* Read ADC Value. */
            MAP_ADCSequenceDataGet(ADC1_BASE, 2, MotorStatus.currentstate.ADC1RawData);
        }
    
    }

    谢谢!

    此致

    约翰逊

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

    你好,约翰逊,

    感谢你的回复。 我对已连接的 ADC 信道具有相同的顺序。 问题似乎是由读取值引起的。 由于我要从通道 AIN0触发采样,请阅读它, 然后在同一序列发生器的同一步骤中触发 AIN1的采样。 这两个通道使用同一个点,但我希望它们的样本在不同的时间触发,彼此独立。 因此,在我的配置中,我有类似你的信:  

    MAP_ADCSequenceStepConfigure (ADC0_BASE,0,0,ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);
    MAP_ADCSequenceStepConfigure (ADC0_BASE,0,0,ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);

    在我阅读样本之前,我运行触发器功能:

    MAP_ADCProcessorTrigger (ADC0_BASE,0);

    这显然不起作用。 我想,每次我读出一个值-- void ADC0SS0_IRQHandler(void)--  我只从最初配置为使用此序列发生器的通道中读取样本。 也许我应该在第二次采样中使用另一个样本序列发生器。  

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

    格尔加纳,您好!

    此代码由 PWM 触发,因此附加 PWM 代码:

    // Initiate PWM
    void initPWM(void)
    {
        /* The PWM peripheral must be enabled for use. */
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
        while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0)));
    
        /* Set the PWM clock to the system clock. */
        MAP_PWMClockSet(PWM0_BASE,PWM_SYSCLK_DIV_1);
    
        /* Enable the clock to the GPIO Port F, G and K for PWM pins */
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
        while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOG));
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
        while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOK));
    
        /* Generator 1 Pins */
        MAP_GPIOPinConfigure(GPIO_PF2_M0PWM2);
        MAP_GPIOPinConfigure(GPIO_PF3_M0PWM3);
    
        /* Generator 2 Pins */
        MAP_GPIOPinConfigure(GPIO_PG0_M0PWM4);
        MAP_GPIOPinConfigure(GPIO_PG1_M0PWM5);
    
        /* Generator 3 Pins */
        MAP_GPIOPinConfigure(GPIO_PK4_M0PWM6);
        MAP_GPIOPinConfigure(GPIO_PK5_M0PWM7);
    
        MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, (GPIO_PIN_2 | GPIO_PIN_3));
        MAP_GPIOPinTypePWM(GPIO_PORTG_BASE, (GPIO_PIN_0 | GPIO_PIN_1));
        MAP_GPIOPinTypePWM(GPIO_PORTK_BASE, (GPIO_PIN_4 | GPIO_PIN_5));
    
        /* Configure the PWM0 to count up/down without synchronization.
         * Note: Enabling the dead-band generator automatically couples the 2
         * outputs from the PWM block so we don't use the PWM synchronization. */
        MAP_PWMGenConfigure(PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_OUTPUT_MODE_SYNC_GLOBAL);
        MAP_PWMGenConfigure(PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_OUTPUT_MODE_SYNC_GLOBAL);
        MAP_PWMGenConfigure(PWM0_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_OUTPUT_MODE_SYNC_GLOBAL);
    
        /* Set the PWM period to 250Hz.  To calculate the appropriate parameter
         * use the following equation: N = (1 / f) * SysClk.  Where N is the
         * function parameter, f is the desired frequency, and SysClk is the
         * system clock frequency.
         * In this case you get: (1 / 250Hz) * 16MHz = 64000 cycles.  Note that
         * the maximum period you can set is 2^16 - 1.
         * TODO: modify this calculation to use the clock frequency that you are
         * using. */
        MAP_PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, PWM_LoadValue);
        MAP_PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, PWM_LoadValue);
        MAP_PWMGenPeriodSet(PWM0_BASE, PWM_GEN_3, PWM_LoadValue);
    
        // Clear cmpA
        MAP_PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, 0);
        MAP_PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4, 0);
        MAP_PWMPulseWidthSet(PWM0_BASE, PWM_OUT_6, 0);
    
        // Configure dead time
        MAP_PWMDeadBandEnable(PWM0_BASE, PWM_GEN_1, 160, 160);
        MAP_PWMDeadBandEnable(PWM0_BASE, PWM_GEN_2, 160, 160);
        MAP_PWMDeadBandEnable(PWM0_BASE, PWM_GEN_3, 160, 160);
    
        // Tirgger for ADC
        MAP_PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_2, PWM_TR_CNT_ZERO);
    
        /* Interrupt */
        MAP_IntMasterEnable();
    
        /* This timer is in up-down mode. Interrupts will occur when the counter counts up to 0. */
        MAP_PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_1, PWM_INT_CNT_ZERO);
        MAP_IntEnable(INT_PWM0_1);
        MAP_PWMIntEnable(PWM0_BASE, PWM_INT_GEN_1);
    
        /* Enable the PWM0 output signals
         *   Bit 2 (PF2) and Bit 3 (PF3)
         *   Bit 4 (PG0) and Bit 5 (PG1)
         *   Bit 6 (PK4) and Bit 7 (PK5) */
        MAP_PWMOutputState(PWM0_BASE, (  PWM_OUT_2_BIT | PWM_OUT_3_BIT |
                                         PWM_OUT_4_BIT | PWM_OUT_5_BIT |
                                         PWM_OUT_6_BIT | PWM_OUT_7_BIT ) , true);
    
        /* Enables the counter for a PWM generator block. */
        MAP_PWMGenEnable(PWM0_BASE, PWM_GEN_1);
        MAP_PWMGenEnable(PWM0_BASE, PWM_GEN_2);
        MAP_PWMGenEnable(PWM0_BASE, PWM_GEN_3);
    
        MAP_PWMSyncTimeBase(PWM0_BASE, (PWM_GEN_1_BIT | PWM_GEN_2_BIT | PWM_GEN_3_BIT));
    
        /* Update locally */
        MAP_PWMOutputUpdateMode(PWM0_BASE, ( PWM_OUT_1_BIT | PWM_OUT_2_BIT | PWM_OUT_3_BIT), PWM_OUTPUT_MODE_SYNC_GLOBAL);
    }

    添加此代码后,您将发现您可以输入 ADC 中断并获取正确的值。

    谢谢!

    此致

    约翰逊

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

    您好,  

    我明白了,但我想让它与一个 proc 触发器配合使用。 我的应用程序中不使用 PWM。  
    非常感谢。

    此致,

    格尔加纳

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

    您好,格尔加纳,

    此代码与您的参考一样,您可以更改此代码以满足您的要求,ADC 模块应该正常。

    您还可以参考 MSP432E SDK 示例代码。

    谢谢!

    此致

    约翰逊

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

    我还有一个问题。 如果我需要从3个不同的模拟输入通道采样 ,而我只需要从每个通道采样一次,而且时间不同,我只能配置一个采样器,在其中进行采样。 因此,我将有通道0到步骤0,通道1到步骤1,通道2到步骤2。

     当我触发模拟输入通道2的采样时,我能否仅获得 该通道的样本?  或者我需要始终读取配置为在同一样品序列发生器中采样的所有通道的值?

    我只想使用 ADC0模块和样本序列发生器0,例如,它有8个样本的缓冲区。

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

    您好,格尔加纳,

    即使将 ADC 配置为序列模式,也可以直接读取所需的通道值。

    ADC 模块内有一些缓冲器,这将存储所有 ADC 捕获值。

    谢谢!

    此致

    约翰逊

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

    谢谢!  

    此致,

    格尔加纳