cancel
Showing results for 
Search instead for 
Did you mean: 

Multi-channel single mode ADC

id_deco
Associate
Posted on September 17, 2013 at 13:38

With the following code I wanted to use DMA to have multi-channel ADC sampling both on ADC1. I am using PC0 and PC1 as analog inputs.

What is happeing is that the returned values from the conversion are both for PC0. Any help is appreciated.

#include <
stdio.h
>
#include <
stm32f4xx.h
>
#include <
float.h
>
#include <
main.h
>
//#include <
stm32f4xx_adc.h
>
//ADC pointer definitions
int counter = 0;
__IO uint16_t ADC_Values[2];
int Value_PC0 = 0;
int Value_PC1 = 0;
void adc_configure()
{
//Setting GPIOC in analog mode with ADC1 on Channel 10
RCC->APB2ENR |= 0x00000100; // Enable ADC1 peripheral clock
RCC->AHB1ENR |= 0x00000004; // Enable GPIOC peripheral clock
RCC->AHB1ENR |= 0x00400000; // Enable DMA2 Clock
GPIOC->MODER |= 0x00000003; // Set GPIO C0 to Analog Mode
GPIOC->PUPDR &= 0xFFFFFFFC; // Set GPIO C0 to No Push-pull State
//
ADC->CCR &= 0xFFFCFFFF; // PCLK2 divided by 2
ADC->CCR |= 0x00004000; // DMAMode Enabled 
ADC->CCR &= 0xFFFFF0FF; // Delay between two samples by 5 cycles
ADC1->CR1 &= 0xFCFFFFFF; // Set ADC1 Resolution to 12-bit
ADC1->CR1 &= 0xFFFFF7FF; // Ser ADC1 to Right Align
ADC1->CR2 |= 0x00000002; // Set ADC1 to Continous Operation Mode
ADC1->SQR1 |= 0x00100000; // Set Number of Conversion to 2
ADC1->CR2 &= 0xCFFFFFFF; // Exernal trigger disabled
ADC1->CR2 &= 0xF0FFFFFF; // Timer 1 CC1 Event
ADC1->CR2 |= 0x00000100; // Enable DMA ADC1
ADC1->CR1 &= 0x00000100; // Enable Scan Mode
ADC1->CR2 |= 0x00000001; // Enable ADC1
ADC1->SMPR1 &= 0xFFFFFFF8; // Select Channel 10 for ADC with 3 cycles
ADC1->SQR3 |= 0x0000000A; // Channel 10 First in Sequence
//
GPIOC->MODER |= 0x0000000C; // Set GPIO C1 to Analog Mode
GPIOC->PUPDR &= 0xFFFFFFF3; // Set GPIO C1 to No Push-pull State
ADC1->SMPR1 |= 0x00000008; // Select Channel 11 for ADC with 3 cycles
ADC1->SQR3 |= 0x00000160; // Channel 11 Second in Sequence
//DMA2 Stream 0 Configuration
DMA2_Stream0->CR &= 0xF1FFFFFF; // Select DMA2 Channel 0
DMA2_Stream0->M0AR = (uint32_t) &ADC_Values; //Load Memory address to store data
DMA2_Stream0->PAR = (uint32_t) ADC_CCR_ADDRESS; //Load ADC Base Register Address
DMA2_Stream0->CR &= 0xFFFFFF3F; //Data transfer direction peripheral-to-memory
DMA2_Stream0->NDTR |= 0x00000002; //Buffer Size 2
DMA2_Stream0->CR &= 0xFFFFFDFF; //Peripheral address pointer is fixed
DMA2_Stream0->CR |= 0x00000400; //Memory address pointer is incremented after each data transfer
DMA2_Stream0->CR |= 0x00000800; //Peripheral size half word (16 bits)
DMA2_Stream0->CR |= 0x00002000; //Memory size half word (16 bits)
DMA2_Stream0->CR |= 0x00000100; //Circular Mode Enabled
DMA2_Stream0->CR |= 0x00020000; //DMA Priority HIGH
DMA2_Stream0->FCR &= 0xFFFFFFFB; //FIFO Enable
DMA2_Stream0->FCR |= 0x00000001; //Half Full FIFO
DMA2_Stream0->CR &= 0xFE7FFFFF; //Single Memory Burst
DMA2_Stream0->CR &= 0xFF9FFFFF; //Single Peripheral Burst
DMA2_Stream0->CR |= 0x00000001; //Enable stream
ADC1->CR2 |= 0x40000000; //Start ADC1
ADC1->CR2 |= 0x00000200; //DDS bits set
}
int main ()
{
adc_configure();
while(1)
{
Value_PC0 = ADC_Values[0];
Value_PC1 = ADC_Values[1];
} 
}

2 REPLIES 2
Posted on September 17, 2013 at 17:16

Sorry, no interest debugging register level code.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
id_deco
Associate
Posted on September 17, 2013 at 19:15

Hi Clive1,

I managed to fix the aforementioned code. Still wish to thank you for your reply.

I agree that register level programming is time consuming and tedious and thus acknowledge your reluctance to discuss such coding. However I personally find it an excellent way for beginners like myself to learn the details of the hardware components and the library functions.