AnsweredAssumed Answered

STM32F100 Multi-Channel ADC assitance?

Question asked by Joe Grisso on Dec 24, 2013
Latest reply on Dec 30, 2013 by Joe Grisso
Hello all,

Long time lurker, first time poster. I've spent the past couple days working on a board designed aroumd a STM32F100RB processor, attempting to use ADC1 to scan a group of channels via DMA. I've followed the Standard Peripherals example and expanded it to handle multiple channels, but when I read the array that the DMA destination is set to, I am only able to read the output of the first channel converted. The rest of the array reads back as zero.

Here's the following init code blocks, in the order they are called from my main() function. I hopefully included all globals and defines so you can see the types I've set up for each system.

If it makes any difference, I'm building with a GCC toolchain.

#define ADC1_DR_Address     ((uint32_t)0x4001244C)
#define ADC_NUMCHANS 13
volatile unsigned short ADCValues[ADC_NUMCHANS];

void RCC_Configuration()
{
     RCC_ADCCLKConfig(RCC_PCLK2_Div2);
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);

}

void GPIO_Configuration()
{
     GPIO_InitTypeDef GPIO_InitStructure;

     /**************************************
      * Configure PORTA GPIO 
      *************************************/

     /* ADC Inputs for Port A. */
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

     GPIO_Init(GPIOA, &GPIO_InitStructure);

     /**************************************
      * Configure PORTC GPIO 
      *************************************/

     /* ADC Inputs */
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

     GPIO_Init(GPIOC, &GPIO_InitStructure);

}

void ADC_Configuration()
{
     ADC_InitTypeDef ADC_InitStructure;
     DMA_InitTypeDef DMA_InitStructure;

     /* Initialize ADC DMA Channel */
     DMA_DeInit(DMA1_Channel1);
     DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCValues[0];
     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
     DMA_InitStructure.DMA_BufferSize = ADC_NUMCHANS;
     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_Init(DMA1_Channel1, &DMA_InitStructure);
     DMA_Cmd(DMA1_Channel1, ENABLE);

     /* Initialize ADC */
     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
     ADC_InitStructure.ADC_ScanConvMode = ENABLE;
     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
     ADC_InitStructure.ADC_NbrOfChannel = ADC_NUMCHANS;

     ADC_Init(ADC1, &ADC_InitStructure);

     /* ADC Channel Configuration */
     ADC_RegularChannelConfig(ADC1, ADC_Channel_1,   1, ADC_SampleTime_55Cycles5);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_2,   2, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_3,   3, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_6,   4, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_7,   5, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_8,   6, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_9,   7, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_10,  8, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_11,  9, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 10, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 11, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 12, ADC_SampleTime_55Cycles5); 
     ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 13, ADC_SampleTime_55Cycles5); 

     ADC_DMACmd(ADC1, ENABLE);
     ADC_Cmd(ADC1, ENABLE);

     ADC_ResetCalibration(ADC1);
     while(ADC_GetResetCalibrationStatus(ADC1));

     ADC_StartCalibration(ADC1);
     while(ADC_GetCalibrationStatus(ADC1));

     ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

/* Main execution loop */
int main()
{

     /* Initialize the ARM System */
     RCC_Configuration();
     GPIO_Configuration();
     ADC_Configuration();

     /* Main execution loop - we should never exit from this */
     while(1) {

          /* ADC Test Code */
          if(ADCValues[0] > 2048) {
               ledOn(0);
          } else {
               ledOff(0);
          }

          if(ADCValues[1] > 2048) {
               ledOn(1);
          } else {
               ledOff(1);
          }

          if(ADCValues[2 > 2048) {
               ledOn(2);
          } else {
               ledOff(2);
          }
     }
}

The ledOn/ledOff function turns on GPIO mapped LEDs, which give me a quick pass/fail on ADC results. Once the quick validation failed I used a debugger to verify that the only element being updated in the ADCValues array was the first one.

If I didn't provide enough data to provide a proper analysis, please let me know what more I can provide.

Thanks in advance!

Outcomes