STM32L152RE (Nucleo64) ADC DMA (HAL) problems
Good day!
I'm trying to run ADC DMA mode on the NUCLEO-L152RE board using HAL, but it doesn't work properly. For testing, 3 channels are used: ADC_CHANNEL_6 (RANK 1), ADC_CHANNEL_VREFINT (RANK 2), ADC_CHANNEL_TEMPSENSOR (RANK 3). 2 problems were found out: 1) When channels are sequentially polled, all values are written to one (first) element of the array. 2) The values of all channels are 8 bits, although the ADC resolution is 12bit and a 12 bit value is displayed in the ADC data register. The same code works fine on STM32F103RBT6. Maybe someone knows if there are any BUGs or some peculiarities in using STM32L1 HAL for ADC DMA mode?
Test code:
#include "main.h"
volatile uint16_t ADC_RES[3];
volatile float U_ADC_RES[3];
#define Vref 3.3
//#define TS_CAL1_25 1.34// raw ADC 670
//#define Avg_Slope 0.0043
ADC_HandleTypeDef hadc;
DMA_HandleTypeDef hdma_adc;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC_Init(void);
static void MX_DMA_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC_Init();
MX_DMA_Init();
while (1)
{
HAL_ADC_Start_DMA(&hadc,(uint32_t*)&ADC_RES, 3);
// HAL_ADC_Stop_DMA(&hadc1);
HAL_Delay(200);
U_ADC_RES[0]=Vref*ADC_RES[0]/4095;
U_ADC_RES[1]=Vref*ADC_RES[1]/4095;
U_ADC_RES[2]=Vref*ADC_RES[2]/4095;
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = ADC_AUTOWAIT_DISABLE;// hadc.Init.LowPowerAutoPowerOff = ADC_AUTOPOWEROFF_DISABLE;
hadc.Init.ChannelsBank = ADC_CHANNELS_BANK_A;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.NbrOfConversion = 3;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.DMAContinuousRequests = ENABLE;
if (HAL_ADC_Init(&hadc) != 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_6;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_4CYCLES;
if (HAL_ADC_ConfigChannel(&hadc, &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_VREFINT;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc, &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_TEMPSENSOR;
sConfig.Rank = ADC_REGULAR_RANK_3;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
}
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_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
}
