cancel
Showing results for 
Search instead for 
Did you mean: 

Any ideas why I get those 0 - 65500 values from adc ?

MNapi
Senior II

I have

uint16_t array[2000];

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)array, 2000);

I get values from 0 up to 65535

but when I declare

uint8_t array[2000];

I get values 0-255

I shouldn't be bigger than 4095 since it is 12 bit resolution for ADC

I have STM32L416KBU6

I do not have the problem with STM32F446RE

6 REPLIES 6

Depends on the 12-bit being left or right aligned, you can pick either. Left aligned would have the 12-bits in the high order bits of a 16-bit word, and thus up to 65500 ish.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal

How the ADC is configured? It could be the DMA is wrongly configured, could be direction or wrong ADC number. Have you also aligned the 16 bit array to a even address number? (#pragma or align keyword, compiler dependent).

I tried left and right the same no change

I do not see anything wrong in ADC setting I use Cube MX

static void MX_ADC1_Init(void)

{

 /* USER CODE BEGIN ADC1_Init 0 */

 /* USER CODE END ADC1_Init 0 */

 ADC_MultiModeTypeDef multimode = {0};

 ADC_ChannelConfTypeDef sConfig = {0};

 /* USER CODE BEGIN ADC1_Init 1 */

 /* USER CODE END ADC1_Init 1 */

 /**Common config

 */

 hadc1.Instance = ADC1;

 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;

 hadc1.Init.Resolution = ADC_RESOLUTION_12B;

 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

 hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;

 hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

 hadc1.Init.LowPowerAutoWait = DISABLE;

 hadc1.Init.ContinuousConvMode = ENABLE;

 hadc1.Init.NbrOfConversion = 1;

 hadc1.Init.DiscontinuousConvMode = DISABLE;

 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

 hadc1.Init.DMAContinuousRequests = ENABLE;

 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;

 hadc1.Init.OversamplingMode = DISABLE;

 if (HAL_ADC_Init(&hadc1) != HAL_OK)

 {

   Error_Handler();

 }

 /**Configure the ADC multi-mode

 */

 multimode.Mode = ADC_MODE_INDEPENDENT;

 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)

 {

   Error_Handler();

 }

 /**Configure Regular Channel

 */

 sConfig.Channel = ADC_CHANNEL_5;

 sConfig.Rank = ADC_REGULAR_RANK_1;

 sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;

 sConfig.SingleDiff = ADC_SINGLE_ENDED;

 sConfig.OffsetNumber = ADC_OFFSET_NONE;

 sConfig.Offset = 0;

 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

 {

   Error_Handler();

 }

 /* USER CODE BEGIN ADC1_Init 2 */

 /* USER CODE END ADC1_Init 2 */

}

S.Ma
Principal

Look at ADC + DMA examples for the closest Nucleo board and narrow down what's different.

Maybe the ADC or DMA IP is slightly different between both STM32 families and copy/paste requires code edits. This happened between STM32L496 and STM32L4R5 for DMAMUX and EXTI.

Nix Wayne
Associate III

I think you have problem with data alignment.

Have a look at my union declaration which I use to assign to DMA call and to extract proper data when conversion is done. This is example for 3 channels.

typedef union
{
  uint32_t data[2];
	
	struct 
	{
	  uint16_t channels[4];	
	} fields;
	
} adc_buffer_s;

So my DMA call looks like:

HAL_ADC_Start_DMA(&adc.hadc1, cnv_buffer.data, 3);

where

// buffer 
adc_buffer_s cnv_buffer;

And then I get data out of buffer by accessing fields in this way:

// first channel
cnv_buffer.fields.channels[0]
 
// second channel
cnv_buffer.fields.channels[1]
 
// third channel
cnv_buffer.fields.channels[2]

A short explanation:

We have 3 channels... each channel has 16 bit data and this results in 6 bytes (3x 2bytes)... but DMA demands pointer to 32bit buffer... so we have to reserve 2x 32 bits which is enough for 4 channels. So there will be one left empty.

Why I am using union in such way? Because data will be written and aligned into memory in a such way that accesing cnv_buffer.fields.channels[X] will already give me back properly aligned data and I can avoid any additional operations to compose data when not using union.

I hope this helps.