ADC channel reading
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-01-23 07:16 AM
Hi guys,
I'm using two channels of ADC1 to convert two different inputs, i'm using the interrupt mode of End Of Conversion. I don't know how to get these values into two different variables.Please take a look at my code, /* Initialize the ADC1 according to the ADC_InitStructure members */ ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = ENABLE; /* Choose ADC to scan all the channels registered */ ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; /* Choose Continuous mode, ADC starts another conversion as soon as it finishes one */ ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; /* Start conversion by software */ ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 2; /* ADC1_IN0 and ADC1_IN3 */ ADC_Init(ADC1, &ADC_InitStructure); /* Configures ADC1 (Bat_Status) Channel0 as: first converted channel with a 7.5 cycles sample time */ ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5); //Sample time may need modification, Old=0.4us, New=0.375us /* Configures ADC1 (ADC) Channel3 as: second converted channel with a 7.5 cycles sample time */ ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_7Cycles5); //Sample time may need modification /* Enable ADC1 EOC interrupt */ ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); /* EOC = End Of Conversion */ /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Reset the ADC1 Calibration registers */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1)); /* It is recommended to start calibration for the ADC after each power up */ /* Start the ADC1 Calibration */ ADC_StartCalibration(ADC1); /* Get the ADC1 calibration status */ while(ADC_GetCalibrationStatus(ADC1)); /* Start by software the ADC1 Conversion */ ADC_SoftwareStartConvCmd(ADC1, ENABLE);In the handler, i clear the interrupt bending bit then what? how to choose a specific channel to get it's value?Any help would be so much appreciated #dma #adc #adc #stm32 #stm32- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-01-23 08:54 AM
The usual way is to use DMA to transfer more than one channel into an array. See Waytae's post below for more information.
Cheers, Hal- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-01-24 05:50 AM
Thanks a lot for your help, the thread you mentioned was very helpful
Here's my final code, haven't tried it yet, but if there's any glitches, you may let me know please.#define ADC1_DR_ADDRESS ((uint32_t)0x4001244C)__IO uint16_t ADC1ConvertedValues[2];void ADC_Config(void){ /* Initialize the ADC1 according to the ADC_InitStructure members */ ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 2; /* ADC1_IN0 and ADC1_IN3 */ ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5); //Sample time may need modification, Old=0.4us, New=0.375us ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_7Cycles5); //Sample time may need modification /* Enable ADC1 DMA transfer */ ADC_DMACmd(ADC1, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Reset the ADC1 Calibration registers */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1)); /* Start the ADC1 Calibration */ ADC_StartCalibration(ADC1); /* Get the ADC1 calibration status */ while(ADC_GetCalibrationStatus(ADC1)); /* Start by software the ADC1 Conversion */ ADC_SoftwareStartConvCmd(ADC1, ENABLE);}void DMA_Config(void){ /* Initialize the DMA1 Channel1 according to the DMA_InitStructure members */ DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_ADDRESS; DMA_InitStructure.DMA_MemoryBaseAddr =(uint32_t)&ADC1ConvertedValues; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 2; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //Better for SCAN and CONTINOUS ADC modes DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); /* Enable DMA1 Channel1 */ DMA_Cmd(DMA1_Channel1, ENABLE);}int main(void){ ADC_Config(); DMA_Config(); //Do whatever with ADC1ConvertedValues[0] and ADC1ConvertedValues[1]}- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-01-24 06:54 AM
Swap the initializations in main.c. DMA needs to be ready before starting the ADC. A usually better solution is to start the ADC in main after calling initializations.
Cheers, Hal- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-01-24 07:33 AM
You mean to do the ADC initialization in the main after all other ones?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-01-24 10:39 AM
int main(void)
{ DMA_Config(); ADC_Config(); //Do whatever with ADC1ConvertedValues[0] and ADC1ConvertedValues[1] } The problem is that the ADC conversion was started in ADC configuration before DMA was configured, probably producing undefined results. Cheers, Hal- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2015-05-04 01:41 AM
Hello
I have started to look into ARM and STM32 world and from ATMEGA it is very eyes opening to see how things really are working. I am playing with STM32F103 and using Eclipse ARM GCC OpenOCD tool-chain.I managed to control digital inputs and outputs and there is no problem with those but I am really struggling with analog inputs. I would just like to read one or several potentiometer values from AI but I am not able to do that. I have tried many samples (single- and multichannel) which could be found on internet and I think that generally I understand AI and ADC working principles but there are some issues.I have included stm32f10x.h, stm32f10x_conf.h, stm32f10x_adc.h headers and it seems that I have correct paths configured but with some ADC functions the code just isn’t compiling. For example ADC_ResetCalibration(ADC1) and other calibration functions but mainly ADC_DeInit(), ADC_Init(ADC1, &ADC_InitStructure) and ADC_Cmd(ADC1, ENABLE) are all giving undefined reference error. However when I comment those out, other ADC functions are accepted and code is compiling.Hopefully I wrote it under correct topic. I have been dealing with it for so long time and I am getting out of ideas, what to try. Could somebody please give a hint, what should I do or try?