2021-10-28 06:43 PM
Hi everyone, hope everyone is doing well
I am trying to setup the STM32H743ZI's ADC for a 5 channel Continuous scan. The 5 scans will be used for
The Input voltage - Channel 0
The Input Current - Channel 1
The output Voltage - Chanel 2
The output Current - Channel 3
Internal Temperature Sensor - Channel 18
Essentially I just want the ADC to continuously scan these 5 channels and have the DMA transfer it into a buffer so it can be read by software. The way I want to read the buffers is via Polling as I am using a RTOS.
The problem I am having is that the EOS flag for the ADC and the DMA1 TC4 flag is setting but the data is not transferring into the DMA buffer. I see the data shifting around in the DR register in the ADC3 however.
I double checked the DMA, the memory address is within the right region of memory for the DMA to see. I have no idea what's happening has I never really use the ADC for a sequential scan before.
I was hopping if anyone can see if I mis-setup or if I have to do something. For example I am not using interrupts as I mention I am using polling, however I am using the DMA. Do I need to still enable the DMA4 TC interrupt still? Etc etc. I just want the ADC to scan forever along side the DMA transferring data and I poll in whenever I want.
Any suggestions are appreciated
The Low Level register that setups GPIO, DMA, ADC
void ADC_helper_function::enable(int * RxBuffer) {
LL_DMA_InitTypeDef ADC_Config_DMA;
LL_GPIO_InitTypeDef ADC_Config_GPIO;
LL_ADC_InitTypeDef ADC_Config_init;
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_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_UP;
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_UP;
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_WORD;
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)&ADC1->DR;
ADC_Config_DMA.PeriphOrM2MSrcDataSize = LL_DMA_MDATAALIGN_WORD;
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);
//Configure ADC
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_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_OVERWRITTEN;
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_SetChannelSingleDiff(ADC3, LL_ADC_CHANNEL_1 | LL_ADC_CHANNEL_2 | LL_ADC_CHANNEL_3, LL_ADC_SINGLE_ENDED);
LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_0 | LL_ADC_CHANNEL_1 | LL_ADC_CHANNEL_2 | LL_ADC_CHANNEL_3, LL_ADC_SAMPLINGTIME_1CYCLE_5);
LL_ADC_SetChannelSamplingTime(ADC3, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_387CYCLES_5);
LL_ADC_SetCommonPathInternalCh(ADC3_COMMON, LL_ADC_PATH_INTERNAL_TEMPSENSOR);
LL_ADC_DisableDeepPowerDown(ADC3);
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();
while ((LL_RCC_PLL2_IsReady == 0)) {
}
LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_4);
LL_ADC_EnableInternalRegulator(ADC3);
LL_ADC_Enable(ADC3);
LL_ADC_REG_StartConversion(ADC3);
}
The task that polls for the ADC buffer
void ADC::ADC_Daemon(void * parameter) {
int tempSensor = 0;
while(1) {
vTaskDelay(ADC_Checkin_Interval/portTICK_PERIOD_MS);
if ((LL_ADC_IsActiveFlag_EOS(ADC3)) && (LL_DMA_IsActiveFlag_TC4(DMA1))) {
tempSensor = dataStructure->getRxBuffer()[3];
LL_ADC_ClearFlag_EOS(ADC3);
LL_DMA_ClearFlag_TC4(DMA1);
}
}
}
Solved! Go to Solution.
2021-11-01 07:54 PM
Perfect going to try it. Ill let you know
2021-11-01 08:31 PM
I finally got the HAL example working and you're right, I get around the same mV as well for temperature sensor. However the only difference I could find is that the Calibration register is actually filled in, where even though I initiated the ADC calibration theres still nothing in the ADC Calibration register.
2021-11-01 08:39 PM
Got the calibration fully working now ( I see the value within the register) However value is still completely off.
2021-11-01 08:48 PM
Okay, I found the cause but not the fix. The ADC3->DR register is holding the right value, but for whatever reason the transfer from the DR register into the memory buffer used via DMA is completely different. For example.
Inside ADC3->DR = 0x3084 inside Buffer = 0x5F