2017-05-06 04:34 AM
Hi there. i have a question about stm32f745 adc. When we use ADC in Scan mode,Continuous,Regular with Interrupt, how to detect which data is for which channel. eos flag bit is not considered in this chip. I have to use counter to know end of all conversions.it's true but i think it's not reliable. my Software and Configuration is:
Configuration:
static void MX_ADC1_Init(void)
{ADC_ChannelConfTypeDef sConfig;
/**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_DIV4; 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 = DISABLE; 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_4; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; 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_5; 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_6; sConfig.Rank = 3; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); }}
-------------------------------------------------------------------------------------------
Software:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{ ADCValue[i]=HAL_ADC_GetValue(hadc); i++; if (i==3) { i=0; } } Note: this post was migrated and contained many threaded conversations, some content may be missing.2017-05-06 06:19 PM
Well the idea is that you DMA into an array which is a multiple of the sample count, and then get an interrupt when that is full, or half full, and the array is all nicely aligned.
2017-05-07 12:17 AM
Thanks for your reply.
I didn't use DMA. is there any way without DMA??
i have to use counter for detecting which adc channel generated this data.
is there any flag register that determine active adc channel or something like this??
thanks alot
2017-05-07 01:24 AM
If using ADC normal channels, all share a single DR per ADC. DMA is the right plumbing when continuous data flow is happening. 3 ADC for 3 DMA channels going to 3 memory buffers, if running independentlt. Otherwise, there are some ADC flavors with injected channels which have one DR per input on some STM32.
2017-05-07 02:27 AM
Thanks for your help. I'm going to work with DMA.
2017-11-28 03:50 AM
Hi,
Sorry to dig into an old post.
I have configured ADC - 1 channel with DMA to retrieve data. It all works fine.
Now, I am trying to use the same ADC (ADC1, DMA2_Stream0) to use 2 channels (channel 12 and 13).
uint16_t ADC_Value[2] = {0,0}; //the user variable for retrieving ADC data from 2 channels
DMA_InitStructure.DMA_Channel =DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)&ADC1->DR; DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)&ADC_Value; DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize =2; // increase the buffer size for multi-channels DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable; //Enabling the memory increment DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode =DMA_Mode_Circular; DMA_InitStructure.DMA_Priority =DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode =DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold =DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst =DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst =DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE);/* ADC1 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution =ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode =ENABLE; // Single channel or Multiple channels (ENABLE) ADC_InitStructure.ADC_ContinuousConvMode =ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge =ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_DataAlign =ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion =2; // INCREASE for multiple channels ADC_Init(ADC1, &ADC_InitStructure);Firstly, I'd like to know if my settings are correct. And secondly, Can someone explain me how exactly the result variable (array) is filled with ADC data from the DR?
Thanks a lot.
2017-11-28 09:27 AM
Filled one word at a time, in Rank order as configured.
I would NOT use two entries, better to use more, and allow the HT/TC DMA interrupts determine what half of the buffer was stable.
Variable should be volatile as changed outside of execution flow.
Prefer (uint32_t)&ADC_Value[0]
Sequencing might get muddled if ADC calibration attempted
2017-11-28 09:49 AM
'Filled one word at a time, in Rank order as configured.' I Understand.
'I would NOT use two entries, better to use more, and allow the HT/TC DMA interrupts determine what half of the buffer was stable.
'
Ok, so I will increase the DMA buffer as suggested.
'
Variable should be volatile as changed outside of execution flow.
'Sorry, yes it should be volatile.
'
Sequencing might get muddled if ADC calibration attempted
'Ok, so far, I have not tried to calibrate the ADC.
'
Prefer (uint32_t)&ADC_Value[0]
'Sorry, but I don't understand here, Why should we update only the first index of the array?
2017-11-28 10:02 AM
>>Sorry, but I don't understand here, Why should we update only the first index of the array?
Because it is explicitly the address of the first entry in the array and the DMA steps forward from there.
ADC_Value would work, as does &ADC_Value[0], where as &ADC_Value can mean something else depending on context, ie if it is a pointer
Casting removes any kind of warning you might get.
I prefer it, it conveys intent.
2017-12-02 09:14 AM
Hi Clive,
Thanks for enlightening me.
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1_DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_values[0];when we declare our variable ADC_values as uint16_t, why do we typecast here?
From the RM,
'ADC1_DR is a 16 bit register, and the AHB slave port is used to program the DMA controller (it supports only 32-bit
accesses).'Is my understanding correct?
Thanks.