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: ADCBUF is not working with AIN16 and higher

Part Number: MSP432E401Y
The problem have been found in Simplelink 2.30.0.14

The wrong value for channel are send to MAP_ADCSequenceStepConfigure. This function needs channel 16 to be 256 (17->257, 18->258, ...) to set register SSEMUX, SSCTL correctly. After ADCBuf_convert, register are SSMUX0=0x0 SSEMUX1=0x0 SSCTL=0x1, which is not good, it should be SSMUX0=0x0 SSEMUX1=0x7 SSCTL=0x06 .

But primeConvert do send 16 to MAP_ADCSequenceStepConfigure which configure channel 1 (because SSEMUX is not set) differential (because it is 0x10) instead of channel 16 common mode.

My workaround is to call MAP_ADCSequenceStepConfigure after ADCBuf_convert to fix register configuration.

MAP_ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADCBufMSP432E4_SamplingDuration_PULSE_WIDTH_32 |  256) // Channel 16
MAP_ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADCBufMSP432E4_SamplingDuration_PULSE_WIDTH_32 |  257) // Channel 17
MAP_ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADCBufMSP432E4_SamplingDuration_PULSE_WIDTH_32 | ADC_CTL_IE | ADC_CTL_END | 258) // Channel 18

#define ADCBufMSP432E4_PK_0_A16 ((16 << 16) | 0x6101)

    {   // READOUT_VPWR: AIN16 --> PK0
        .adcPin = ADCBufMSP432E4_PK_0_A16,
        .adcSequence = ADCBufMSP432E4_Seq_1,
        .adcInputMode = ADCBufMSP432E4_SINGLE_ENDED,
        .adcDifferentialPin = ADCBufMSP432E4_PIN_NONE,
        .adcInternalSource = ADCBufMSP432E4_INTERNAL_SOURCE_MODE_OFF,
        .refVoltage = 3000000
    },

#define pinConfigChannel(config) (((config) >> 16) & 0x1F)


/* * ======== primeConvert ======== */ static int_fast16_t primeConvert(ADCBufMSP432E4_Object *object, ADCBufMSP432E4_HWAttrsV1 const *hwAttrs, ADCBuf_Conversion *conversions, uint_fast8_t channelCount) { uint_fast8_t i=0; uint32_t channel; uint32_t port; uint8_t pin; uint_fast16_t powerID; ADCBufMSP432E4_Channels channelSetting = hwAttrs->channelSetting[conversions[0].adcChannel]; uint_fast8_t base = (hwAttrs->adcBase == ADC0_BASE) ? 0 : 1; uint8_t sequencer = channelSetting.adcSequence; uint32_t refVoltage = channelSetting.refVoltage; if ((channelCount > adcMaxSamples[sequencer]) || (hwAttrs->sequencePriority[sequencer] >= ADCBufMSP432E4_Seq_Disable)) { return (ADCBuf_STATUS_ERROR); } /* Store the conversions struct array into object */ object->conversions[sequencer] = conversions; /* Store the channel count into object */ object->channelCount[sequencer] = channelCount; /* Store the samples count into object - one channel*/ object->sampleBuffer[sequencer] = conversions->sampleBuffer; object->sampleCount[sequencer] = conversions->samplesRequestedCount; object->sampleIndex[sequencer] = 0; /* Initialize GPIOs and Temperature mode*/ for (i=0; i < channelCount; i++) { channelSetting = hwAttrs->channelSetting[conversions[i].adcChannel]; if (channelSetting.refVoltage != refVoltage) { return (ADCBuf_STATUS_ERROR); } channel = pinConfigChannel(channelSetting.adcPin); port = pinConfigPort(channelSetting.adcPin); pin = pinConfigPin(channelSetting.adcPin); /* If using temperature mode, skip GPIO initialization and use ADC_CTL_TS instead of channel */ if (channelSetting.adcInternalSource == ADCBufMSP432E4_TEMPERATURE_MODE) { channel = ADCBufMSP432E4_TEMPERATURE_MODE; } else { powerID = getPowerResourceId(port); if (powerID == (uint16_t)(-1)) { return (ADCBuf_STATUS_ERROR); } Power_setDependency(powerID); GPIOPinTypeADC(port, pin); } /* Initialize differential pin channel for differential mode*/ if (channelSetting.adcInputMode == ADCBufMSP432E4_DIFFERENTIAL) { if (channelSetting.adcDifferentialPin == ADCBufMSP432E4_PIN_NONE) { return (ADCBuf_STATUS_ERROR); } MAP_GPIOPinTypeADC( pinConfigPort(channelSetting.adcDifferentialPin), pinConfigPin(channelSetting.adcDifferentialPin) ); channel = channel / 2; channel = channel | ADCBufMSP432E4_DIFFERENTIAL; } if (i == channelCount - 1) { channel |= ADC_CTL_IE | ADC_CTL_END; } MAP_ADCSequenceStepConfigure(hwAttrs->adcBase, sequencer, i, channel|object->samplingDuration); } /* If DMA enabled, setup peripheral*/ if (hwAttrs->useDMA) { MAP_ADCIntClearEx(hwAttrs->adcBase, ADC_INT_DMA_SS0 << sequencer); MAP_ADCIntEnableEx(hwAttrs->adcBase, ADC_INT_DMA_SS0 <<sequencer); configDMA(object, hwAttrs, conversions); } else { MAP_ADCIntClear(hwAttrs->adcBase, sequencer); MAP_ADCIntEnable(hwAttrs->adcBase, sequencer); } /* Since sample sequence is now configured, it must be enabled. */ MAP_ADCSequenceEnable(hwAttrs->adcBase, sequencer); /* Enable the Interrupt generation from the specified ADC Sequencer */ MAP_IntEnable(adcInterrupts[base][sequencer]); /* Enable timer if using timer trigger */ if (hwAttrs->adcTriggerSource[sequencer] == ADCBufMSP432E4_TIMER_TRIGGER) { MAP_TimerEnable(timerSettings.timerSource, TIMER_A); } return (ADCBuf_STATUS_SUCCESS); }

}

void
ADCSequenceStepConfigure(uint32_t ui32Base, uint32_t ui32SequenceNum,
                         uint32_t ui32Step, uint32_t ui32Config)
{
    uint32_t ui32Temp;

    //
    // Check the arguments.
    //
    ASSERT((ui32Base == ADC0_BASE) || (ui32Base == ADC1_BASE));
    ASSERT(ui32SequenceNum < 4);
    ASSERT(((ui32SequenceNum == 0) && (ui32Step < 8)) ||
           ((ui32SequenceNum == 1) && (ui32Step < 4)) ||
           ((ui32SequenceNum == 2) && (ui32Step < 4)) ||
           ((ui32SequenceNum == 3) && (ui32Step < 1)));

    //
    // Get the offset of the sequence to be configured.
    //
    ui32Base += ADC_SEQ + (ADC_SEQ_STEP * ui32SequenceNum);

    //
    // Compute the shift for the bits that control this step.
    //
    ui32Step *= 4;

    //
    // Set the analog mux value for this step.
    //
    HWREG(ui32Base + ADC_SSMUX) = ((HWREG(ui32Base + ADC_SSMUX) &
                                    ~(0x0000000f << ui32Step)) |
                                   ((ui32Config & 0x0f) << ui32Step));

    //
    // Set the upper bits of the analog mux value for this step.
    //
    HWREG(ui32Base + ADC_SSEMUX) = ((HWREG(ui32Base + ADC_SSEMUX) &
                                     ~(0x0000000f << ui32Step)) |
                                    (((ui32Config & 0xf00) >> 8) << ui32Step));

    //
    // Set the control value for this step.
    //
    HWREG(ui32Base + ADC_SSCTL) = ((HWREG(ui32Base + ADC_SSCTL) &
                                    ~(0x0000000f << ui32Step)) |
                                   (((ui32Config & 0xf0) >> 4) << ui32Step));

    //
    // Set the sample and hold time for this step.
    //
    HWREG(ui32Base + ADC_SSTSH) = ((HWREG(ui32Base + ADC_SSTSH) &
                                    ~(0x0000000f << ui32Step)) |
                                (((ui32Config & 0xf00000) >> 20) << ui32Step));

    //
    // Enable digital comparator if specified in the ui32Config bit-fields.
    //
    if(ui32Config & 0x000F0000)
    {
        //
        // Program the comparator for the specified step.
        //
        ui32Temp = HWREG(ui32Base + ADC_SSDC);
        ui32Temp &= ~(0xF << ui32Step);
        ui32Temp |= (((ui32Config & 0x00070000) >> 16) << ui32Step);
        HWREG(ui32Base + ADC_SSDC) = ui32Temp;

        //
        // Enable the comparator.
        //
        HWREG(ui32Base + ADC_SSOP) |= (1 << ui32Step);
    }

    //
    // Disable digital comparator if not specified.
    //
    else
    {
        HWREG(ui32Base + ADC_SSOP) &= ~(1 << ui32Step);
    }
}

**Attention** This is a public forum