2020-09-22 09:33 AM
Hi,
I am setting up my STM32F405RG with 3 analog inputs on ADC with DMA.
The problem I'm having is that the ADC buffer is being filled in the wrong order:
For example, I have channel 11, 12 and 13, with ranks 1, 2 and 3 respectively, so I presume the ADC buffer should be as follows:
adc_buf[0] -> data from channel 11
adc_buf[1] -> data from channel 12
adc_buf[2] -> data from channel 13
.
.
.
but what I am actually getting is:
adc_buf[0] -> data from channel 12 - this wrong order
adc_buf[1] -> data from channel 11 - this wrong order
adc_buf[2] -> data from channel 13
adc_buf is defined above int main():
#define ADC_BUF_LEN 3
uint16_t adc_buf[ADC_BUF_LEN];
in int main we have:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
app_init();
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_I2C1_Init();
MX_SPI1_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_USB_DEVICE_Init();
MX_TIM2_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc_buf[0], ADC_BUF_LEN);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
//do stuff
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
}
ADC init and DMA init look like this:
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 3;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_11;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_12;
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_13;
sConfig.Rank = 3;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
HAL_ADC_Start(&hadc1);
/* USER CODE END ADC1_Init 2 */
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
And when I run I am inspecting the values here:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
HAL_GPIO_WritePin(IND1_GPIO_Port, IND1_Pin, 0);
uint16_t num1, num2, num3 = 0;
num1 = adc_buf[0]; // should be data from ch11 but is actually ch12
num2 = adc_buf[1]; // should be data from ch12 but is actually ch11
num3 = adc_buf[2]; // channel 13
}
Currently I can get all the correct data but I would love to know why the order is incorrect when the adc_buf is being filled.
Thanks!
Solved! Go to Solution.
2020-09-22 12:09 PM
2020-09-22 10:45 AM
How do you know it's in the wrong order? Note that 3 cycles is not a long time. The readings might not be what you're expecting, particularly if you're measuring high impedance signals.
2020-09-22 12:03 PM
Well, correct me if I'm wrong, but I am presuming that because I set the rank for each ADC channel, that this is the order in which they are scanned and thus the order that they are filled into the buffer?
2020-09-22 12:09 PM
2020-09-22 12:54 PM
Ah yes, sorry... I am running in debug mode and have set a breakpoint where I set num1, num2 and num3 in the HAL_ADC_ConvCpltCallback function.
I have set the three channels to known values: 3.3V , 1.5v and 0V, so I can make sure what the the ADC is reading is correct.
2020-09-22 12:59 PM
Thanks so much! Yes, this has solved my problem! :smiling_face_with_smiling_eyes:
It looks like starting it twice caused the order to be incorrect!
Thank you for your help.