cancel
Showing results for 
Search instead for 
Did you mean: 

problem to read adc1 channel 8 and 9 at the same time

mohamad_armoon
Associate III
Posted on May 11, 2014 at 18:47

hi guys.

i want to read adc1 channel 8 and 9 at the same time .i mean in main loop at first read adc1 channel 8 and then read channel 9. i set this channel for PB0 and PB1. you know when i want to read from ADC i don't have option for channel i just have to send ADC number as parameter to my function :

int
adc_convert(ADC_TypeDef* ADCx){
ADC_SoftwareStartConv(ADCx);
while
(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC));
return
ADC_GetConversionValue(ADCx); 
}

so how can i read this 2 channel separately . how about putting this two channel in adc1 and adc2; and in this case just adc2 works.because i initialized adc2 after 1. any idea would be grate.
5 REPLIES 5
Posted on May 11, 2014 at 21:10

Two channels at exactly the same instance in time. Dual Mode?

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/ADC%20in%20Dual%20Mode%20Simultaneously&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=67...

It could probably be done without DMA, if it's just two paired channels

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mohamad_armoon
Associate III
Posted on May 12, 2014 at 19:13

hi clive

changed my code based on your example . but my code still does't work. at least i decided to compile your code but it didn't work too . it stop at line ADC_SoftwareStartConv(ADC1); here is my code what's your idea about it :

#include ''stm32f4xx.h''
__IO uint16_t ADC3ConvertedValue[2] = {0,0};
__IO uint32_t ADC3ConvertedVoltage = 0;
__IO uint16_t temp = 0;
typedef
unsigned 
char
byte;
void
RCC_Configuration(
void
)
{
/*--------------------ADC 3 clock enable-----------------------*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
/*--------------------DMA1 clock enable-----------------------*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/*-------------------USART2 clock enable-----------------------*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
}
void
ADC3_CH12_DMA_Config(
void
)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/*-------------- DMA2 Stream0 channel0 configuration -----------------------*/
DMA_InitStructure.DMA_Channel = DMA_Channel_0; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 
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_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_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);
/*--------------Configure ADC3 Channel 10 pin as analog input------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*--------------------- ADC Common Init ------------------------------------*/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);

/*------------------------ADC3 Init ----------------------------------------*/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Init(ADC2, &ADC_InitStructure);
/*------------------ADC3 regular channel12 configuration--------------------*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 1, ADC_SampleTime_15Cycles);
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
/* Enable ADC3 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC3 */
ADC_Cmd(ADC1, ENABLE);
ADC_Cmd(ADC2, ENABLE);
}
void
init_usart(
void
){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE); 
}
void
Delay(__IO uint32_t nCount)
{
while
(nCount--)
{
}
}
int
main()
{
RCC_Configuration();
ADC3_CH12_DMA_Config();
init_usart();
/* Start ADC3 Software Conversion */
ADC_SoftwareStartConv(ADC1);
byte raw_Data[3]; 
while
(1)
{
temp = ADC3ConvertedValue[0];
raw_Data[0] = 0xFF;
raw_Data[1] = temp >> 8;
raw_Data[2] = temp & 255;
for
(
int
i = 0 ; i < 3; i++)
{
if
(USART_GetITStatus(USART2, USART_IT_RXNE) == RESET)
{
USART_SendData(USART2,raw_Data[i]);
Delay(0x3FFFF);
}
}
}
}

another question what's the concept behind of allocate memory to dma ?? , in you assign a 16bit int array with size of 800
Posted on May 14, 2014 at 03:24

Yes, that's still rather broken, I might try to recode it if I find some time.

I don't understand why the raw[] is 3 bytes, or why you can't wait on TXE rather than delay for some arbitrary period.

I had a large buffer in my example for several reasons, I wanted to get samples fast without sitting polling them, or having an interrupt storm. The DMA should handle two 16-bit (12-bit) samples from each ADC, and I doubled the working size so the half and full transfer interrupts could process a block of samples without copying them, or have the DMA overwrite them. In the time it takes to fill half the buffer you must process the other half.

What sample rate are you looking to achieve? At the moment it is going to be limited by the serial port, and the added delay.

What is the nature of the signals you are measuring?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mohamad_armoon
Associate III
Posted on May 14, 2014 at 07:40

thanks clive for your information.

i decided not to use interrupt an made some changes and now i can read 2 adc at the same time with dma .

i think i misunderstand about using dma for adc or any thing . at first how one dma can handle 2 adc with 2 different channel ?? you know because from my perspective for each peripheral , in this case we use dma just for adc1 . and what is exactly half and full transfer interrupt that you mentioned ?? if would be grate if you introduce me a article or tutorial about understanding DMA .

and if i want to use 3 dma channel, is it possible ?? in that case i need to use 1 dma too ??

i think it is impossible to use 2 different channel of 1 adc so the maximum adc channel which i can use is 3 ???

i have to mention for testing adc channel i just use 2 potentiometer .

thanks a lot

 

Posted on May 14, 2014 at 13:44

Do you need to sample at the ''same time''? A single ADC can sample multiple channels in a sequence, you can pair two ADC to have the sample occur at the same instance, and you can configure three ADC into a couple of different Triple modes.

DMA typically has an interrupt for a ''Terminal Count'' or ''Transfer Complete'' TC, when the buffer has been filled, the STM32 also has a ''Half Transfer'' HT to indicate when it has reached the midway of the data transfer. This way you can implement a simple ping-pong buffer.

I don't have any tutorials, a Google may turn some up, and there is probably some coverage in Computer System Architecture texts.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..