STM32Duino : Using DMA ADC as well as regular ADC? - Page 1
Forum section: electronics / general

author: Eldi4
author_rank: Contributor
timestamp: July 22, 2020, 12:59:59 pm
content: Hello there,I'm looking a way to use DMA ADC and normal ADC combined, the DMA ADC is used to measuring current and voltage of power supply (continous), while the normal ADC used to measure temperature of transistor (probably like once per second), when i read the ADC value of temperature the DMA crashed.I have separated the DMA ADC channel with the ADC that is used for temperature reading, the DMA is ADC1 whilst the temperature is ADC2.If i call readTherm(int channel) function somewhere on the program, the DMA buffer goes mad (random big number like 12412812951) andalso i did'nt get my temperature reading either (also some random big number).DMA crashes on HAL_ADC_Start(&hadc2); and HAL_ADCEx_Calibration_Start(&hadc2) as well.Here is my whole DMA, ADC and some HAL GPIO settings :Code:extern "C" void DMA1_Channel1_IRQHandler(void){HAL_DMA_IRQHandler(&hdma_adc1);}extern "C" void HAL_ADC_MspInit(ADC_HandleTypeDef* hadcx){GPIO_InitTypeDef GPIO_InitStruct = {0};if(hadcx->Instance==ADC2){__HAL_RCC_ADC2_CLK_ENABLE();}if(hadcx->Instance==ADC1){__HAL_RCC_ADC1_CLK_ENABLE();hdma_adc1.Instance = DMA1_Channel1;hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;hdma_adc1.Init.Mode = DMA_CIRCULAR;hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;if (HAL_DMA_Init(&hdma_adc1) != HAL_OK){Error_Handler();}__HAL_LINKDMA(hadcx,DMA_Handle,hdma_adc1);}}extern "C" void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadcx){if(hadcx->Instance==ADC1){__HAL_RCC_ADC1_CLK_DISABLE();HAL_DMA_DeInit(hadcx->DMA_Handle);}if(hadcx->Instance==ADC2){__HAL_RCC_ADC2_CLK_DISABLE();HAL_DMA_DeInit(hadcx->DMA_Handle);}}static void MX_GPIO_Init(void){GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);/*Configure GPIO pin : PB10 */GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_6|GPIO_PIN_8|GPIO_PIN_7|GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_8|GPIO_PIN_12;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);}static void MX_DMA_Init(void){/* DMA controller clock enable */__HAL_RCC_DMA1_CLK_ENABLE();/* DMA interrupt init *//* DMA1_Channel1_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);}static void MX_ADC1_Init(void){/* USER CODE BEGIN ADC1_Init 0 *//* USER CODE END ADC1_Init 0 */ADC_ChannelConfTypeDef sConfig = {0};ADC_ChannelConfTypeDef sConfig2 = {0};/* USER CODE BEGIN ADC1_Init 1 *//* USER CODE END ADC1_Init 1 *//** Common config*/hadc1.Instance = ADC1;hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;hadc1.Init.ContinuousConvMode = ENABLE;hadc1.Init.DiscontinuousConvMode = DISABLE;hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;hadc1.Init.NbrOfConversion = 4;if (HAL_ADC_Init(&hadc1) != HAL_OK){Error_Handler();}hadc2.Instance = ADC2;hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;hadc2.Init.ContinuousConvMode = DISABLE;hadc2.Init.DiscontinuousConvMode = DISABLE;hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;hadc2.Init.NbrOfConversion = 1;if (HAL_ADC_Init(&hadc2) != HAL_OK){Error_Handler();}sConfig2.Channel = ADC_CHANNEL_6;sConfig2.Rank = ADC_REGULAR_RANK_1;sConfig2.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;if (HAL_ADC_ConfigChannel(&hadc2, &sConfig2) != HAL_OK){Error_Handler();}sConfig2.Channel = ADC_CHANNEL_7;sConfig2.Rank = ADC_REGULAR_RANK_2;sConfig2.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;if (HAL_ADC_ConfigChannel(&hadc2, &sConfig2) != HAL_OK){Error_Handler();}/*sConfig2.Channel = ADC_CHANNEL_8;sConfig2.Rank = ADC_REGULAR_RANK_3;sConfig2.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;if (HAL_ADC_ConfigChannel(&hadc2, &sConfig2) != HAL_OK){Error_Handler();}*///////////////////////////////////////////////////////////////////sConfig.Channel = ADC_CHANNEL_2;sConfig.Rank = ADC_REGULAR_RANK_1;sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}sConfig.Channel = ADC_CHANNEL_3;sConfig.Rank = ADC_REGULAR_RANK_2;sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}sConfig.Channel = ADC_CHANNEL_4;sConfig.Rank = ADC_REGULAR_RANK_3;sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}sConfig.Channel = ADC_CHANNEL_9;sConfig.Rank = ADC_REGULAR_RANK_4;sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK){Error_Handler();}//if (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK){// Error_Handler();//}}int readTherm(int channel){ADC_ChannelConfTypeDef adcChannel = {0};switch(channel){case 0://adcChannel.Channel = ADC_CHANNEL_8;break;case 1:adcChannel.Channel = ADC_CHANNEL_6;break;case 2:adcChannel.Channel = ADC_CHANNEL_7;break;}adcChannel.Rank = 1;adcChannel.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; //or any other value available.if(HAL_ADC_ConfigChannel(&hadc2, &adcChannel) != HAL_OK){Error_Handler();}HAL_ADC_Start(&hadc2);if (HAL_ADC_PollForConversion(&hadc2, 10) == HAL_OK){return HAL_ADC_GetValue(&hadc2);}}int raw_ch1Voltage;int raw_ch2Voltage;int raw_ch1Current;int raw_ch2Current;void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle){if(AdcHandle->Instance==ADC1){raw_ch1Voltage = (dmaAdcBuffer+dmaAdcBuffer+dmaAdcBuffer)/3;raw_ch2Voltage = (dmaAdcBuffer+dmaAdcBuffer+dmaAdcBuffer)/3;raw_ch1Current = (dmaAdcBuffer+dmaAdcBuffer+dmaAdcBuffer)/3;raw_ch2Current = (dmaAdcBuffer+dmaAdcBuffer+dmaAdcBuffer)/3;// Add value from DMA buffer to running average (for smooth performance).ch1Voltage.reading(raw_ch1Voltage);ch2Current.reading(raw_ch2Current);ch2Voltage.reading(raw_ch2Voltage);ch1Current.reading(raw_ch1Current);}}void initializeHAL(){HAL_Init();MX_GPIO_Init();MX_DMA_Init();MX_ADC1_Init();HAL_ADC_Start(&hadc1);HAL_ADC_Start(&hadc2);HAL_ADC_Start_DMA(&hadc1, dmaAdcBuffer, 12);}I have tried the temperature reading only by disabling the DMA and it does work fine, but once i enabled the DMA, the DMA crashed.I have tried to change the PinMap setting on "variants/Generic_F103Cx", like this :Code:#ifdef HAL_ADC_MODULE_ENABLEDWEAK const PinMap PinMap_ADC[] = {{PA_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC1_IN0// {PA_0, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC2_IN0{PA_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC1_IN1// {PA_1, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC2_IN1{PA_2, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC1_IN2// {PA_2, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC2_IN2{PA_3, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC1_IN3// {PA_3, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC2_IN3{PA_4, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC1_IN4// {PA_4, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC2_IN4{PA_5, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC1_IN5// {PA_5, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC2_IN5//{PA_6, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC1_IN6{PA_6, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC2_IN6//{PA_7, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC1_IN7{PA_7, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC2_IN7{PB_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC1_IN8// {PB_0, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC2_IN8//{PB_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC1_IN9{PB_1, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC2_IN9{NC, NP, 0}};#endifbut no luckMy board is BluePill and i use STM32Core : readTherm(); actually return correct value even while DMA is crashing: After reading some reference manual (i should have read it before programming these actually lol), i think i should use injected ADC, while the ADC is busy reading voltage and current, trigger an injected ADC request, when injected channel is triggered the ADC abort all of its current conversion and prioritize the injected channel. The injected channel has it's own register so the converted value is not interfering with the ADC with DMA and corrupts the DMA buffer.I will come back after trying to implement this...,: Got it to work, by implementing injection mode adc on the temperature reading.

author: thm_w
author_rank: Super Contributor
timestamp: July 23, 2020, 09:20:42 pm
content: Code:HAL_ADC_Start(&hadc1);HAL_ADC_Start(&hadc2);HAL_ADC_Start_DMA(&hadc1, dmaAdcBuffer, 12);That first line should be removed right?ADC1 = DMAADC2 = non DMA

author: Eldi4
author_rank: Contributor
timestamp: July 24, 2020, 12:56:01 am
content: Quote from: thm_w on July 23, 2020, 09:20:42 pmI don't think that is the problem, i tried to remove that first line and still behaving exactly the same (big number and so), and if i remove HAL_ADC_Start(&hadc2); the DMA ADC is not working (previously it should work), so that first line is needed i guess.: After reading some reference manual (i should have read it before programming these actually lol), i think i should use injected ADC, while the ADC is busy reading voltage and current, trigger an injected ADC request, when injected channel is triggered the ADC abort all of its current conversion and prioritize the injected channel. The injected channel has it's own register so the converted value is not interfering with the ADC with DMA and corrupts the DMA buffer.I will come back after trying to implement this...,