AnsweredAssumed Answered

[SOLVED] ADC problems - STM32F407 discovery

Question asked by ash_ on May 7, 2015
Latest reply on May 7, 2015 by ash_
I am using 2 ADCs with DMA in simultaneous mode and sending data over usb. Here is the code:
#include "main.h"
 
const uint16_t BUFFER_SIZE = 400;
 
volatile uint16_t ADCConvertedValues [BUFFER_SIZE];
volatile uint16_t *head, *buffer_start, *buffer_end;
 
static void initialize_pointers(void);
static void buffer_step(void);
 
static void Hardware_Config(void);
static void ADC_Config(ADC_TypeDef*, uint8_t);
static void DMA_Config(void);
 
int main(void) {
    initialize_pointers();
 
    Hardware_Config();
 
    ADC_SoftwareStartConv(ADC1);
 
    while (1) {
        usb_vcp_putc(*(head));
        buffer_step();
        usb_vcp_putc(*(head));
        buffer_step();
    }
}
 
static void Hardware_Config(void)
{
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    GPIO_InitTypeDef      GPIO_InitStructure;
 
    /* Enable ADC1, ADC2, DMA and GPIO clocks */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
 
    /* Enable DMA */
    DMA_Config();
 
    /* Configure ADC1_ch1 and ADC2_ch2 pins as analog input */
    GPIO_InitStructure.GPIO_Pin = GPIO_PIN_1 | GPIO_Pin_2; // PA1, PA2
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    /* ADC Common Init */
    ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);
 
    /* ADC1 and ADC2 Init*/
    ADC_Config(ADC1, ADC_Channel_1);
    ADC_Config(ADC2, ADC_Channel_2);
 
    /* Enable DMA request after last transfer (Multi-ADC mode) */
    ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
 
    /* Enable ADC1 and ADC2*/
    ADC_Cmd(ADC1, ENABLE);
    ADC_Cmd(ADC2, ENABLE);
}
 
static void DMA_Config(){
    DMA_InitTypeDef       DMA_InitStructure;
 
    DMA_DeInit(DMA2_Stream0);
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValues;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->CDR; //0x40012308
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
 
 
    DMA_InitStructure.DMA_BufferSize = sizeof(ADCConvertedValues)/sizeof(ADCConvertedValues[0]);
    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;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
    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);
}
 
static void ADC_Config(ADC_TypeDef* ADCx, uint8_t ADC_Channel){
    ADC_InitTypeDef       ADC_InitStructure;
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    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 = 1;
    ADC_Init(ADCx, &ADC_InitStructure);
 
    ADC_RegularChannelConfig(ADCx, ADC_Channel, 1, ADC_SampleTime_28Cycles); //84
}
 
static void initialize_pointers(){
    buffer_start = ADCConvertedValues;
    buffer_end = ADCConvertedValues + BUFFER_SIZE - 1;
    head = ADCConvertedValues;
}
 
static void buffer_step() {
    if (head == buffer_end) {
        head = buffer_start;
    } else {
        head++;
    }
}

1kHz sine is fed into channel 1 of ADC1. When I use BUFFER_SIZE = 400 I can get something that looks like a sine (sorry, I couldn't get that 'image manager' thing to work):
Screenshot1

But when I increase buffer size to 1024 or 2048 the results look a lot worse:
Screenshot2

Is there something wrong with my DMA configuration?

Outcomes