2013-09-17 04:38 AM
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];
}
}
2013-09-17 08:16 AM
Sorry, no interest debugging register level code.
2013-09-17 10:15 AM
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.