AnsweredAssumed Answered

STM32F030F4P6 - ADC 12b with DMA - 4 bits missing

Question asked by garcia.maxime on Oct 1, 2014
Hello Guys,

I'm starting a new simple project with the STM32F030F4P6 chip and some analog sensors.
In this project I need values from 3 channels from ADC1 (AN5:7) and send them to UART1. My problem is the value after the DMA transfer contain only the 8 first bit of the sample (4 Msb are missing). I try different DMA configurations, try another IDE (1st was CooCox, now I'm working with Keil µV5 but nothing change) .


ps. It work fine with ADC Res = 8 bit, but it's not enough for the application.
It also work in 12bit mode without DMA, but I need to read all channel in one ADC shot. 


Please follow below, maybe you'll have some suggestions


// To simplify tests I work with one channel
volatile unsigned short ADCConvertedValues[1];


void DMA1_Channel1_IRQHandler(void){
     if(DMA_GetFlagStatus(DMA1_FLAG_TC1) != RESET){
               STREAM_TRAME[3] =   ADCConvertedValues[0]&0xFF;
               STREAM_TRAME[4] =   (ADCConvertedValues[0]&0x0F00)>>8;
               DMA_ClearFlag(DMA1_FLAG_TC1);
     }
}


void adc_init(void){
     
     //DMA NVIC
     InitNVIC.NVIC_IRQChannel = DMA1_Channel1_IRQn;
     InitNVIC.NVIC_IRQChannelPriority = 2;
     InitNVIC.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&InitNVIC);


     DMA_DeInit(DMA1_Channel1);
     InitDMA.DMA_PeripheralBaseAddr           =      (uint32_t)&ADC1->DR;
     InitDMA.DMA_MemoryBaseAddr          =     (uint32_t)ADCConvertedValues;
     InitDMA.DMA_DIR                         =     DMA_DIR_PeripheralSRC;
     InitDMA.DMA_BufferSize                    =     1;
     InitDMA.DMA_PeripheralInc                =     DMA_PeripheralInc_Disable;
     InitDMA.DMA_MemoryInc                    =     DMA_MemoryInc_Enable;
     InitDMA.DMA_PeripheralDataSize          =     DMA_MemoryDataSize_HalfWord;
     InitDMA.DMA_MemoryDataSize               =     DMA_MemoryDataSize_HalfWord;
     InitDMA.DMA_Mode                         =     DMA_Mode_Circular;
     InitDMA.DMA_Priority                         =     DMA_Priority_High;
     InitDMA.DMA_M2M                          =      DMA_M2M_Disable;


     DMA_Init(DMA1_Channel1, &InitDMA);
     DMA_Cmd(DMA1_Channel1, ENABLE);
     
     DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);
     
     ADC_DMARequestModeConfig(ADC1,ADC_DMAMode_Circular);
     ADC_DMACmd(ADC1,ENABLE);




     // divide systemClock for ADCClock to optain 12MHz => 48M/4=12M
     RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);




     ADC_StructInit(&InitAdc);
     InitAdc.ADC_Resolution = ADC_Resolution_12b;
     InitAdc.ADC_ContinuousConvMode = ENABLE;
     InitAdc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
     InitAdc.ADC_DataAlign = ADC_DataAlign_Right;
     InitAdc.ADC_ScanDirection = ADC_ScanDirection_Upward;
     ADC_Init(ADC1, &InitAdc);




     ADC_ChannelConfig(ADC1,    ADC_Channel_7, ADC_SampleTime_239_5Cycles);
     
     ADC_GetCalibrationFactor(ADC1);
     ADC_Cmd(ADC1, ENABLE);
     while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
     ADC_StartOfConversion(ADC1);


}


After this, TIMx reload periodically one channel (ch2) of DMA1 to send data via UART1.
Samples are included in one array who contain START and END flags. There are no problems with the sending,
I get all fields of the array but STREAM_TRAME[4] always contain 0x00
___________________________________________________________
Extra testing :


With the source code bellow I obtain two bytes who contain the full sample
from de DMA but these datas are sometime wrong (I think the last bit of the LSB ans the 1 bit of the MSB are wrongs)

Please find enclosed a snapshot of data for this configuration.

volatile unsigned char ADCConvertedValues[2];
void DMA1_Channel1_IRQHandler(void){
     if(DMA_GetFlagStatus(DMA1_FLAG_TC1) != RESET){
               STREAM_TRAME[3] =   ADCConvertedValues[0];
               STREAM_TRAME[4] =   ADCConvertedValues[1];
               DMA_ClearFlag(DMA1_FLAG_TC1);
     }
}


void adc_init(void){
     ...
     DMA_DeInit(DMA1_Channel1);
     InitDMA.DMA_PeripheralBaseAddr           =      (uint32_t)&ADC1->DR;
     InitDMA.DMA_MemoryBaseAddr          =     (uint32_t)ADCConvertedValues;
     InitDMA.DMA_DIR                         =     DMA_DIR_PeripheralSRC;
     InitDMA.DMA_BufferSize                    =     2;
     InitDMA.DMA_PeripheralInc                =     DMA_PeripheralInc_Enable;
     InitDMA.DMA_MemoryInc                    =     DMA_MemoryInc_Enable;
     InitDMA.DMA_PeripheralDataSize          =     DMA_MemoryDataSize_Byte;
     InitDMA.DMA_MemoryDataSize               =     DMA_MemoryDataSize_Byte;
     InitDMA.DMA_Mode                         =     DMA_Mode_Circular;
     InitDMA.DMA_Priority                         =     DMA_Priority_High;
     InitDMA.DMA_M2M                          =      DMA_M2M_Disable;


     DMA_Init(DMA1_Channel1, &InitDMA);
     DMA_Cmd(DMA1_Channel1, ENABLE);
     
     DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);
     
     ADC_DMARequestModeConfig(ADC1,ADC_DMAMode_Circular);
     ADC_DMACmd(ADC1,ENABLE);




     // divide systemClock for ADCClock to optain 12MHz => 48M/4=12M
     RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);




     ADC_StructInit(&InitAdc);
     InitAdc.ADC_Resolution = ADC_Resolution_12b;
     InitAdc.ADC_ContinuousConvMode = ENABLE;
     InitAdc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
     InitAdc.ADC_DataAlign = ADC_DataAlign_Right;
     InitAdc.ADC_ScanDirection = ADC_ScanDirection_Upward;
     ADC_Init(ADC1, &InitAdc);
     ...


}

Best, 

Max 

Attachments

Outcomes