cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L_Discovery Multichannel ADC example

idris
Associate II
Posted on November 09, 2015 at 12:38

I have been trying extend Clive1 ADC_DMA example on STM32L_Discovery to do multi-channel conversion. But am struggling to get the NVIC_IRQ Handle for the two channel right. Can someone assist me with an example of multichannel ADC on STM32L?  The modified code is given below.

include <stm32l1xx.h>

ADC_InitTypeDef ADC_InitStructure;

ADC_CommonInitTypeDef ADC_CommonInitStructure;

DMA_InitTypeDef DMA_InitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

__IO uint16_t ADC_ConvertedValue[2];

   void LEDInit(void)

{

 /*Enable GPIOB & GPIOC clock and Configure PB6 and PB7 in output mode*/

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC, ENABLE);</div>

  

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* Configure PC4&PC5 (ADC Channel14 & 15) in analog mode */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

}

void NVIC_Config(void){

NVIC_InitTypeDef NVIC_InitStructure;

/* Enable the DMA Stream IRQ Channel */

  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;</div>

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;</div>

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;</div>

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;</div>

  NVIC_Init(&NVIC_InitStructure);</div>

}

void ADC_DMA_Config(void)

{

/* Enable the HSI oscillator */

     RCC_HSICmd(ENABLE);

   /* Check that HSI oscillator is ready */

  while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);</div>

  

/* Enable ADC1 clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);</div>

 

  /* Deinitialize ADC */

     ADC_DeInit(ADC1);

ADC_CommonStructInit(&ADC_CommonInitStructure);</div>

  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;</div>

  ADC_CommonInit(&ADC_CommonInitStructure);</div>

  /* ADC1 configuration */

ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;</div>

  ADC_InitStructure.ADC_ScanConvMode = ENABLE;</div>

  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;</div>

  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;</div>

ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;</div>

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;</div>

  ADC_InitStructure.ADC_NbrOfConversion = 2;</div>

  ADC_Init(ADC1, &ADC_InitStructure);

 /* ADC1 regular channel18 configuration */

  ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_192Cycles);

  ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 2, ADC_SampleTime_192Cycles);

/* Enable ADC1 Power Down during Delay */

  ADC_PowerDownCmd(ADC1, ADC_PowerDown_Idle_Delay, ENABLE);

  /*------------------------ DMA1 configuration ------------------------------*/</div>

  /* Enable DMA1 clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);</div>

  /* DMA1 channel1 configuration */

  DMA_DeInit(DMA1_Channel1);

  DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) &ADC1->DR;</div>

  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue[0];</div>

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

  DMA_InitStructure.DMA_BufferSize = 2;</div>

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;</div>

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;</div>

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;</div>

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;</div>

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

  DMA_Init(DMA1_Channel1, &DMA_InitStructure);

  

/* Enable DMA Stream Half / Transfer Complete interrupt */

  DMA_ITConfig(DMA1_Channel1, DMA_IT_TC | DMA_IT_HT, ENABLE);

  /* Enable DMA1 channel1 */

  DMA_Cmd(DMA1_Channel1, ENABLE);

  /* Enable the request after last transfer for DMA Circular mode */

  ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);</div>

  /*----------------- ADC1 configuration with DMA enabled --------------------*/

  

  /* Enable ADC1 DMA */

  ADC_DMACmd(ADC1, ENABLE);

  /* Enable ADC1 */

  ADC_Cmd(ADC1, ENABLE);

  /* Wait until the ADC1 is ready */

  while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);

  

  /* Start ADC1 Software Conversion */

  ADC_SoftwareStartConv(ADC1);

}

int main (void){

   double x = 0, y = 0;

LEDInit();

NVIC_Config();

GPIO_WriteBit(GPIOB, GPIO_Pin_7, Bit_RESET);

  GPIO_WriteBit(GPIOB, GPIO_Pin_6, Bit_SET);

ADC_DMA_Config();

while (1)

{

x = ADC_ConvertedValue[0] * 3.3/4095; //get analog value and convert to volts, 12bit ADC

        if(y > 2)

        {

          GPIO_WriteBit(GPIOB, GPIO_Pin_7, Bit_SET);//Red LED on

        }

        else 

        {

          GPIO_WriteBit(GPIOB, GPIO_Pin_7, Bit_RESET);//Red LED off 

        }

        y = ADC_ConvertedValue[1] * 3.3/4095; //get analog value and convert to volts, 12bit ADC

        if(x > 2)

        {

          GPIO_WriteBit(GPIOB, GPIO_Pin_6, Bit_SET);// Green LED on

        }

        else 

        {

          GPIO_WriteBit(GPIOB, GPIO_Pin_6, Bit_RESET);//Green LED off 

        }

}

}

6 REPLIES 6
Posted on November 09, 2015 at 13:08

Please don't email every time you post, it's rather presumtive.

I'm not using L1 parts, I tried to work through the logic here

include <
stm32l1xx.h
>
// Consider using locals, it won't suck up resources permanently
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
__IO uint16_t ADC_ConvertedValue[2];
void LEDInit(void)
{
/*Enable GPIOB & GPIOC clock and Configure PB6 and PB7 in output mode*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure PC4&PC5 (ADC Channel14 & 15) in analog mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void NVIC_Config(void){
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the DMA Stream IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void ADC_DMA_Config(void)
{
/* Enable the HSI oscillator */
RCC_HSICmd(ENABLE);
/* Check that HSI oscillator is ready */
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
/* Enable ADC1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* Deinitialize ADC */
ADC_DeInit(ADC1);
ADC_CommonStructInit(&ADC_CommonInitStructure);
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 configuration */
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 2;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel18 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_192Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 2, ADC_SampleTime_192Cycles);
/* Enable ADC1 Power Down during Delay */
ADC_PowerDownCmd(ADC1, ADC_PowerDown_Idle_Delay, ENABLE);
/*------------------------ DMA1 configuration ------------------------------*/
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA1 channel1 configuration */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) &ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 2;
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_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* Enable the request after last transfer for DMA Circular mode */
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/*----------------- ADC1 configuration with DMA enabled --------------------*/
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Wait until the ADC1 is ready */
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConv(ADC1);
}
int main (void)
{
LEDInit();
NVIC_Config();
GPIO_WriteBit(GPIOB, GPIO_Pin_7, Bit_RESET);
GPIO_WriteBit(GPIOB, GPIO_Pin_6, Bit_SET);
ADC_DMA_Config();
while (1)
{
}
}
void DMA1_Channel1_IRQHandler(void)
{
double x, y;
x = (double)ADC_ConvertedValue[0] * 3.3/40; //get analog value and convert to volts, 12bit ADC
if(x > 2.0)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_6, Bit_SET);// Green LED on
}
else 
{
GPIO_WriteBit(GPIOB, GPIO_Pin_6, Bit_RESET);//Green LED off 
}
y = (double)ADC_ConvertedValue[1] * 3.3/40; //get analog value and convert to volts, 12bit ADC
if(y > 2.0)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_7, Bit_SET);//Red LED on
}
else 
{
GPIO_WriteBit(GPIOB, GPIO_Pin_7, Bit_RESET);//Red LED off 
}
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 09, 2015 at 13:10

Are you sure VREF is 3.3V?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
idris
Associate II
Posted on November 09, 2015 at 16:21

Hello Clive1;

I'm sorry about the email. Yes, the vref is 3.3V.

idris
Associate II
Posted on November 10, 2015 at 15:58

Thanks for the assistance. However, the code is still not working properly.  The blue LED just flashes for less than a second. 

Posted on November 10, 2015 at 19:27

Are you using an STM32L1-Discovery?

Are you SURE the VREF is 3.3V, most DISCO boards run at 3.0V

The PC4/PC5 pins are used by the touch sensor, have you disconnected that? What are you supplying to the pins?

What is being measured at the time the LED turns off? Use a debugger and provide specific details about the measurements.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
idris
Associate II
Posted on November 16, 2015 at 11:28

Hello Clive1

 Am using STM32L152RC board. You are absolutely correct. The voltage is 2.96V.   When the Led is off, the voltage is 0.0025 V. I did the debugging by blinking the Leds. How can I disconnect the PC4/PC5 from the touch sensor?