2021-11-01 04:03 PM
Hi everyone, hope all of you are doing well.
Posting here again about the ADC. I finally got the ADC out of that over run situation and now ready to acquire data!
The way the ADC is setup is by having 4 channels using Pins setup as continuous scanning
PC2 = Channel 0 for ADC 3 Rank 0
PC3 = Channel 1 for ADC 3 Rank 1
PF9 = Channel 2 for ADC 3 Rank 2
PF7 = Channel 3 for ADC 3 Rank 3
and internal temperature sensor = Channel 12 for ADC 3
I am essentially polling for the DMA1 Stream 4 Transfer Complete 4 flag, once this is done I know that the ADC has done all 5 sequential reads, however when I get into the array or even the data there's either nonsense data or zeros. The channels that read zero I have tried hooking up those pins to VDD and it still reads zero. I notice in the ADC3->DR there's a lot of activity going.
What I have tried thus far is, changing DMA to one shot mode, behavior is the same.
I am not sure what's going as it seems to look like the DMA is not transferring from ADC3->DR properly into its memory buffer. The buffer being used is in the x2400 region of memory and there's no error flag set for either DMA1 or ADC3.
ADC, GPIO, Low Level driver initialization
LL_DMA_InitTypeDef ADC_Config_DMA;
LL_GPIO_InitTypeDef ADC_Config_GPIO;
LL_ADC_InitTypeDef ADC_Config_Init;
LL_ADC_CommonInitTypeDef ADC_Config_CommonInit;
LL_ADC_REG_InitTypeDef ADC_Config_REG;
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOC);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOF);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_ADC3);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
LL_ADC_StructInit(&ADC_Config_Init);
LL_ADC_CommonStructInit(&ADC_Config_CommonInit);
LL_ADC_REG_StructInit(&ADC_Config_REG);
LL_GPIO_StructInit(&ADC_Config_GPIO);
LL_DMA_StructInit(&ADC_Config_DMA);
//Configure GPIOA
ADC_Config_GPIO.Mode = LL_GPIO_MODE_ANALOG;
ADC_Config_GPIO.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
ADC_Config_GPIO.Pin = LL_GPIO_PIN_2 | LL_GPIO_PIN_3;
ADC_Config_GPIO.Pull = LL_GPIO_PULL_DOWN;
ADC_Config_GPIO.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
LL_GPIO_Init(GPIOC, &ADC_Config_GPIO);
//Configure GPIOC
ADC_Config_GPIO.Mode = LL_GPIO_MODE_ANALOG;
ADC_Config_GPIO.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
ADC_Config_GPIO.Pin = LL_GPIO_PIN_9 | LL_GPIO_PIN_7;
ADC_Config_GPIO.Pull = LL_GPIO_PULL_DOWN;
ADC_Config_GPIO.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
LL_GPIO_Init(GPIOF, &ADC_Config_GPIO);
ADC_Config_DMA.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
ADC_Config_DMA.FIFOMode = LL_DMA_FIFOMODE_DISABLE;
ADC_Config_DMA.MemBurst = LL_DMA_MBURST_SINGLE;
ADC_Config_DMA.MemoryOrM2MDstAddress = (uint32_t)RxBuffer;
ADC_Config_DMA.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;
ADC_Config_DMA.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
ADC_Config_DMA.Mode = LL_DMA_MODE_CIRCULAR;
ADC_Config_DMA.NbData = 5;
ADC_Config_DMA.PeriphBurst = LL_DMA_PBURST_SINGLE;
ADC_Config_DMA.PeriphOrM2MSrcAddress = (uint32_t)&ADC3->DR;
ADC_Config_DMA.PeriphOrM2MSrcDataSize = LL_DMA_MDATAALIGN_HALFWORD;
ADC_Config_DMA.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
ADC_Config_DMA.PeriphRequest = LL_DMAMUX1_REQ_ADC3;
ADC_Config_DMA.Priority = LL_DMA_PRIORITY_LOW;
//Interrupt: DMA
LL_DMA_Init(DMA1, LL_DMA_STREAM_4, &ADC_Config_DMA);
ADC_Config_Init.LeftBitShift = LL_ADC_LEFT_BIT_SHIFT_NONE;
ADC_Config_Init.LowPowerMode = LL_ADC_LP_MODE_NONE;
ADC_Config_Init.Resolution = LL_ADC_RESOLUTION_16B;
LL_ADC_Init(ADC3, &ADC_Config_Init);
ADC_Config_CommonInit.CommonClock = LL_ADC_CLOCK_ASYNC_DIV1;
ADC_Config_CommonInit.MultiDMATransfer = LL_ADC_MULTI_REG_DMA_EACH_ADC;
ADC_Config_CommonInit.Multimode = LL_ADC_MULTI_INDEPENDENT;
LL_ADC_CommonInit(ADC3_COMMON, &ADC_Config_CommonInit);
ADC_Config_REG.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;
ADC_Config_REG.DataTransferMode =LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
ADC_Config_REG.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;
ADC_Config_REG.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
ADC_Config_REG.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS;
ADC_Config_REG.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
LL_ADC_REG_Init(ADC3, &ADC_Config_REG);
LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_0);
LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_1);
LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_2);
LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_3);
LL_ADC_REG_SetSequencerRanks(ADC3, LL_ADC_REG_RANK_5, LL_ADC_CHANNEL_TEMPSENSOR);
LL_ADC_SetChannelPreSelection(ADC3, LL_ADC_CHANNEL_0);
LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_0, LL_ADC_SAMPLINGTIME_810CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_810CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_2, LL_ADC_SAMPLINGTIME_810CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_3, LL_ADC_SAMPLINGTIME_810CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_4, LL_ADC_SAMPLINGTIME_810CYCLES_5);
LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_0, LL_ADC_SINGLE_ENDED);
LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_1, LL_ADC_SINGLE_ENDED);
LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_2, LL_ADC_SINGLE_ENDED);
LL_ADC_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_3, LL_ADC_SINGLE_ENDED);
LL_ADC_SetCommonPathInternalCh(ADC3_COMMON, LL_ADC_PATH_INTERNAL_TEMPSENSOR);
LL_ADC_SetBoostMode(ADC3, LL_ADC_BOOST_MODE_50MHZ);
LL_ADC_SetLowPowerMode(ADC3, LL_ADC_LP_MODE_NONE);
//LL_ADC_SetOffsetSignedSaturation(ADC3, LL_ADC_OFFSET_4, LL_ADC_OFFSET_SIGNED_SATURATION_ENABLE);
//LL_ADC_SetDataRightShift(ADC3, LL_ADC_OFFSET_4, LL_ADC_OFFSET_RSHIFT_ENABLE);
LL_RCC_PLL2_SetM(4);
LL_RCC_PLL2_SetN(9);
LL_RCC_PLL2_SetP(4);
LL_RCC_PLL2_SetFRACN(6144);
LL_RCC_PLL2_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
LL_RCC_PLL2_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLL2P);
LL_RCC_PLL2FRACN_Enable();
LL_RCC_PLL2P_Enable();
LL_RCC_PLL2_Enable();
LL_ADC_StartCalibration(ADC3, LL_ADC_CALIB_OFFSET, LL_ADC_SINGLE_ENDED);
while (LL_ADC_IsCalibrationOnGoing(ADC3));
LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_4);
LL_ADC_DisableDeepPowerDown(ADC3);
LL_ADC_EnableInternalRegulator(ADC3);
LL_ADC_ClearFlag_ADRDY(ADC3);
LL_ADC_Enable(ADC3);
while (LL_ADC_IsActiveFlag_ADRDY(ADC3) == 0);
LL_ADC_ClearFlag_ADRDY(ADC3);
LL_ADC_REG_StartConversion(ADC3);
ADC Task to read 5 channels
void ADC::ADC_Daemon(void * parameter) {
int tempSensor = 0;
int inputVoltage = 0;
int inputCurrent = 0;
int outputVoltage = 0;
int outputCurrent = 0;
while(1) {
vTaskDelay(ADC_Checkin_Interval / portTICK_PERIOD_MS);
if (LL_DMA_IsActiveFlag_TC4(DMA1)) {
inputVoltage = dataStructure->getRxBuffer()[0];
inputCurrent = dataStructure->getRxBuffer()[1];
outputVoltage = dataStructure->getRxBuffer()[2];
outputCurrent = dataStructure->getRxBuffer()[3];
tempSensor = (TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP)/(*TEMPSENSOR_CAL2_ADDR - *TEMPSENSOR_CAL1_ADDR) * dataStructure->getRxBuffer()[4] + 30;
LL_DMA_ClearFlag_TC4(DMA1);
}
}
}
Data within the buffer once Transfer Completed flag 4 from the DMA1 is triggered. Just pure nonsense data. The pins are pull down and not in used but here there's some kind of voltage.
Solved! Go to Solution.
2021-11-06 03:08 PM
Fixed the issue for the analog pins for not reading the voltage properly.
Fix:
LL_ADC_SetChannelPreSelection(ADC3, LL_ADC_CHANNEL_0);
LL_ADC_SetChannelPreSelection(ADC3, LL_ADC_CHANNEL_1);
LL_ADC_SetChannelPreSelection(ADC3, LL_ADC_CHANNEL_2);
LL_ADC_SetChannelPreSelection(ADC3, LL_ADC_CHANNEL_3);
LL_ADC_SetChannelPreSelection(ADC3, LL_ADC_CHANNEL_TEMPSENSOR);
I dont know why this is the way to initialize the ADC as I thought the ranks you pick them will decide which channel to sample through. I also thought setChannelPreSelection was to choose which ADC channel gets sampled first. Anyways adding all the ADC channels you are going to use into setChannelPreSelection works.