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