2019-02-23 08:36 AM
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
2019-02-23 09:01 AM
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.
2019-02-23 09:40 AM
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).
2019-02-23 09:46 AM
I tried left and right the same no change
2019-02-23 09:47 AM
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 */
}
2019-02-23 08:32 PM
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.
2019-02-25 12:32 AM
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.