STM32 ADC Multi Channel Using DMA - FabLabSeoul/WingProject GitHub Wiki

STM32 ADC Multi Channel Using DMA

์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ์„ ๋‘๊ฐœ ์ด์ƒ์„ ๋ฐ›์•„์•ผ ํ•  ๋•Œ ADC ์ฑ„๋„์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. STM32 Value line discovery ๋ณด๋“œ๋Š” ADC1, ADC2 ๋‘๊ฐœ์˜ A/D ์ปจ๋ฒ„ํ„ฐ๊ฐ€ ์žˆ์ง€๋งŒ, ์ฑ„๋„์„ ์‚ฌ์šฉํ•˜๋ฉด ADC1 ํ•˜๋‚˜๋กœ ๋‘ ๊ฐœ ์ด์ƒ์˜ ์•„๋‚ ๋กœ๊ทธ ๋ฐ์ดํƒ€๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. ๋ฌธ์ œ๋Š” ADC1์—์„œ ์•„๋‚ ๋กœ๊ทธ๋ฅผ ๋””์ง€ํ„ธ ์ •๋ณด๋กœ ๋ฐ”๊พผ ํ›„, ADC1->DR ๋ ˆ์ง€์Šคํ„ฐ์— ์ €์žฅ๋˜๋Š”๋ฐ, ๋‘ ๊ฐœ์ด์ƒ์˜ ์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ์„ ๋™์‹œ์— ํฌํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ›๊ฒŒ๋˜๋ฉด, ADC1->DR ์ •๋ณด๊ฐ€ ๋ฎ์–ด์”Œ์›Œ์ง€๊ธฐ ๋•Œ๋ฌธ์—, ๊ธฐ์กด ๋ฐฉ์‹๋Œ€๋กœ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ์ด ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด DMA(Direct Memory access Controller) ๋‹ค. ํฌํŠธ๋กœ ์•„๋‚ ๋กœ๊ทธ ์ •๋ณด๋ฅผ ๋ฐ›์€ ํ›„, ADC1 ์ปจ๋ฒ„ํ„ฐ๋ฅผ ๊ฑฐ์ณ ๋ณ€ํ™˜๋œ ์ •๋ณด๋ฅผ ์ง€์ •๋œ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•˜๊ฒŒ ํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. 2๊ฐœ์˜ ์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ์„ ๋ฐ›๊ณ  ์‹ถ๋‹ค๋ฉด, ๋‘ ๊ฐœ์˜ ์ •๋ณด๋ฅผ ๋ฐ›์„ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ , ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ADC ์ฑ„๋„์— ์—ฐ๊ฒฐ์‹œ์ผœ์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด๋œ๋‹ค. ์œ ์šฉํ•˜๊ณ , ๊ฐ„๋‹จํ•œ ๊ธฐ๋Šฅ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ž์ฃผ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. ๊ฐ„๋‹จํ•œ ๊ฐœ๋…์€ http://egloos.zum.com/recipes/v/5152867 ์‚ฌ์ดํŠธ๋ฅผ ์ฐธ์กฐํ•˜์ž.

์•ž์œผ๋กœ ์„ค๋ช…ํ•  MultiChannel ADC using DMA ์˜ˆ์ œ๋Š” STM32\stm32vldiscovery_package\Project\Examples\ADC_Channel2 ํด๋”์— ์žˆ๋‹ค.

์ด ์˜ˆ์ œ๋Š” ํฌํŠธ PC1, PC2 ๋กœ๋ถ€ํ„ฐ ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ๋ฅผ ๋ฐ›์•„, ๊ฐ๊ฐ์˜ ํฌํŠธ์˜ ์ „์••์ด 2V ์ด์ƒ์ด๋˜๋ฉด, PC9, PC8 LED๋ฅผ ์ผœ๊ฒŒํ•œ๋‹ค. ์ด ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•ด ๋ณด๋ ค๋ฉด, ๊ฐ€๋ณ€์ €ํ•ญ ๋‘ ๊ฐœ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์ž์„ธํ•œ ํšŒ๋กœ ์„ค๊ณ„๋Š” ๊ฐ์ž ์•Œ์•„์„œ ํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค.

์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ ์ดˆ๊ธฐํ™”

PC1, PC2 ๋ฅผ ์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๋Š”๋‹ค. ๊ตณ์ด PC ํฌํŠธ๋ฅผ ์“ด ์ด์œ ๋Š”, ํฌํŠธ์™€ ADC1 ๊ฐ„์— ์ฑ„๋„์„ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋‹ค. ADC1๋Š” ์ฑ„๋„๋งˆ๋‹ค ์ •ํ•ด์ง„ ํฌํŠธ๊ฐ€ ์žˆ๋‹ค. ์ •ํ•ด์ง„ ์ฑ„๋„ ํฌํŠธ ํ…Œ์ด๋ธ”์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ADC1_IN0 ์€ Channel_0 ์„ ๋งํ•œ๋‹ค.

Channel Port
ADC1_IN0 PA0
ADC1_IN1 PA1
ADC1_IN2 PA2
ADC1_IN3 PA3
ADC1_IN4 PA4
ADC1_IN5 PA5
ADC1_IN6 PA6
ADC1_IN7 PA7
ADC1_IN8 PB0
ADC1_IN9 PB1
ADC1_IN10 PC0
ADC1_IN11 PC1
ADC1_IN12 PC2
ADC1_IN13 PC3
ADC1_IN14 PC4
ADC1_IN15 PC5

PC1, PC2 ์˜ ์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ์„ ๋ฐ›๊ฒŒ ํ•˜๋Š” ์„ค์ • ์ฝ”๋“œ๋‹ค. GPIOC ์— ํด๋Ÿญ์„ ์„ค์ •ํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋‹ค๋ฅธ ๊ณณ์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์—ฌ๊ธฐ์„œ๋Š” ์ƒ๋žตํ•œ๋‹ค.

GPIO_InitTypeDef myGPIO;
myGPIO.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; //set to pin 1, 2
myGPIO.GPIO_Mode = GPIO_Mode_AIN; //set as analog input
GPIO_Init(GPIOC, &myGPIO); //set to C1, C2

PC8,PC9 LED ์„ค์ •

PC8, PC9 ํฌํŠธ๋ฅผ ์ถœ๋ ฅ์œผ๋กœ ์„ค์ •ํ•œ๋‹ค. PC8,9๋Š” STM32 Value line discovery ๋ณด๋“œ ์œ„์— LED 3,4๋ฒˆ๊ณผ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋‹ค.

//Configure other I/O pins
void GPIO_config(void)
{
    GPIO_InitTypeDef myGPIO;

    // initialize LED C8, 9 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIO_StructInit(&myGPIO);
    myGPIO.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    myGPIO.GPIO_Mode = GPIO_Mode_Out_PP;
    myGPIO.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOC, &myGPIO);
}

ADC ์„ค์ •

์—ฌ๊ธฐ๊นŒ์ง€๋Š” ๊ธฐ์กด ADC ์„ค์ •๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค.

  • ADC_NbrOfChannel : Number of Channel ์€ ์ฑ„๋„์˜ ์ˆ˜๋‹ค. ๋‘ ๊ฐœ์˜ ์ฑ„๋„์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ˆ 2 ๋‹ค.
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //clock for ADC (max 14MHz, 72/6=12MHz)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //enable ADC clock

//configure ADC1 parameters
ADC_InitTypeDef myADC;
myADC.ADC_Mode = ADC_Mode_Independent;
myADC.ADC_ScanConvMode = ENABLE;
myADC.ADC_ContinuousConvMode = ENABLE;
myADC.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
myADC.ADC_DataAlign = ADC_DataAlign_Right;
myADC.ADC_NbrOfChannel  = 2;
ADC_Init(ADC1, &myADC);

DMA ์„ค์ •

DMA ์— ๊ด€๋ จ๋œ ๋‚ด์šฉ์€ ๋งค๋‰ด์–ผ์„ ์ฐธ์กฐํ•˜์ž. DMA1 ๋„ ADC, DAC์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํด๋Ÿญ์„ ์„ค์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

  • DMA_PeripheralBaseAddr ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ์–ด๋–ค ๋ ˆ์ง€์Šคํ„ฐ์˜ ์ •๋ณด๋ฅผ ๋ฐ›์„ ์ง€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์„ค์ •ํ•œ๋‹ค.
  • DMA_MemoryBaseAddr ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ์‹ค์ œ๋กœ ์ €์žฅ๋  ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์„ค์ •ํ•œ๋‹ค.
  • DMA_BufferSize ๋ณ€์ˆ˜์— ์ €์žฅํ•  ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ๋ฅผ ์„ค์ •ํ•œ๋‹ค. ๋งŒ์•ฝ uint32 ๋‘๊ฐœ๋ฅผ ๋ฐ›๋Š”๋‹ค๋ฉด, 2๋ฅผ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค.
  • DMA_MemoryDataSize ๋ณ€์ˆ˜์— ์ €์žฅํ•  ๋ฐ์ดํƒ€ ํฌ๊ธฐ๋ฅผ ์„ค์ •ํ•œ๋‹ค. ํ˜„์žฌ uint32 ํ˜•์œผ๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— 32๋น„ํŠธ ์‚ฌ์ด์ฆˆ์˜ Word๋กœ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค. 16๋น„ํŠธ ๋ฐ์ดํƒ€๋ฅผ ๋ฐ›์„ ๊ฒƒ์ด๋ผ๋ฉด HalfWord ๋กœ ์„ค์ •ํ•œ๋‹ค.
  • DMA_MemoryInc ๋ณ€์ˆ˜์— DMA_MemoryInc_Enable ๋กœ ์„ค์ •ํ•ด์•ผ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋ฉด์„œ ๋‹ค์Œ ๋ฉ”๋ชจ๋ฆฌ์— ์ •๋ณด๋ฅผ ์“ฐ๊ฒŒ ๋œ๋‹ค.
  • DMA_Mode ๋ณ€์ˆ˜์—๋Š” DMA_Mode_Circular ๋กœ ์„ค์ •ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ๋˜๋ฉด ์ •ํ•ด์ง„ ํฌ๊ธฐ์˜ ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ์ดํƒ€๋ฅผ ๋‹ค ์“ฐ๋ฉด, ์ฒ˜์Œ์œผ๋กœ ๋Œ์•„๊ฐ€์„œ ๊ณ„์† ์“ฐ๊ฒŒ ๋œ๋‹ค. ๋งค ๋ฃจํ”„ ๋งˆ๋‹ค ์ •๋ณด๋ฅผ ๊ฐฑ์‹ ํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์“ธ ์ˆ˜ ์žˆ๋Š”, ์ด ์˜ต์…˜์œผ๋กœ ์„ค์ •ํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค.
__IO uint32_t ADC_DualConvertedValueTab[2]; // ์ „์—ญ ๋ณ€์ˆ˜ 

DMA_InitTypeDef DMA_InitStructure;
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_DualConvertedValueTab;
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_Word; // 32bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; // 32bit
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 DMA1 Channel1
DMA_Cmd(DMA1_Channel1, ENABLE);

ADC Channel ์„ค์ •

ADC1์— ์ฑ„๋„์„ ์—ฐ๊ฒฐํ•œ๋‹ค. ADC_Channel_11์€ PC1๊ณผ ์—ฐ๊ฒฐ๋˜๊ณ , ADC_Channel_12๋Š” PC2์™€ ์—ฐ๊ฒฐ๋œ๋‹ค. ์ฆ‰, ํฌํŠธ PC1์œผ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์•„๋‚ ๋กœ๊ทธ ์ •๋ณด๋Š” Channel_11 ์„ ํ†ตํ•ด ๋””์ง€ํ„ธ๋กœ ๋ณ€ํ™˜๋˜์–ด DMA๋ฅผ ํ†ตํ•ด, ์ตœ์ข…์ ์œผ๋กœ ADC_DualConvertedValueTab[0] ์œ„์น˜์— ์ €์žฅ๋œ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํฌํŠธ PC2๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์•„๋‚ ๋กœ๊ทธ ์ •๋ณด๋Š” Channel_12๋ฅผ ํ†ตํ•ด ๋””์ง€ํ„ธ๋กœ ๋ณ€ํ™˜๋˜์–ด DMA๋ฅผ ํ†ตํ•ด, ์ตœ์ข…์ ์œผ๋กœ ADC_DualConvertedValueTab[1] ์œ„์น˜์— ์ €์žฅ๋œ๋‹ค.

ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5); //PC1 as Input
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 2, ADC_SampleTime_55Cycles5); //PC2 as Input
ADC_DMACmd(ADC1, ENABLE);

ADC1 ์ดˆ๊ธฐํ™” ๊ทธ๋ฆฌ๊ณ , ๋ณ€ํ™˜ ์‹œ์ž‘

์ด ์ฝ”๋“œ์˜ ๋‚ด์šฉ์€ STM32 ADC์— ์žˆ์œผ๋‹ˆ ์ฐธ์กฐํ•˜์ž.

ADC_Cmd(ADC1, ENABLE);

ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));

ADC_SoftwareStartConvCmd(ADC1, ENABLE);

์ „์ฒด ์˜ˆ์ œ ์ฝ”๋“œ

์„ค๋ช…์„ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ์œ„ํ•ด ์œ„์— ๋ณด์—ฌ์ค€ ์ฝ”๋“œ๋Š” ์‹ค์ œ ์˜ˆ์ œ์ฝ”๋“œ์™€๋Š” ์กฐ๊ธˆ ๋‹ค๋ฅด๋‹ค. ์ตœ์ข… ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์ด ์˜ˆ์ œ๋Š” ํฌํŠธ PC1, PC2 ๋กœ๋ถ€ํ„ฐ ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ๋ฅผ ๋ฐ›์•„, ๊ฐ๊ฐ์˜ ํฌํŠธ์˜ ์ „์••์ด 2V ์ด์ƒ์ด๋˜๋ฉด, PC9, PC8 LED๋ฅผ ์ผœ๊ฒŒํ•œ๋‹ค. ์ด ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•ด ๋ณด๋ ค๋ฉด, ๊ฐ€๋ณ€์ €ํ•ญ ๋‘ ๊ฐœ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

//
// ADC Channel 2 Example
//

#include "stm32f10x.h"
#include "STM32vldiscovery.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_dma.h"


double x = 0, y = 0;
GPIO_InitTypeDef myGPIO;
ADC_InitTypeDef myADC;
DMA_InitTypeDef DMA_InitStructure;
 __IO uint32_t ADC_DualConvertedValueTab[2];
 

//Configure other I/O pins
void GPIO_config(void)
{
    // initialize LED C8, 9 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIO_StructInit(&myGPIO);
    myGPIO.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    myGPIO.GPIO_Mode = GPIO_Mode_Out_PP;
    myGPIO.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOC, &myGPIO);
}

 
void adc_config()
{ 
  // PC1, PC2๋ฅผ analog input ๋ชจ๋“œ๋กœ ์„ค์ •ํ•œ๋‹ค.  
  myGPIO.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; //set to pin 1, 2
  myGPIO.GPIO_Mode = GPIO_Mode_AIN; //set as analog input
  GPIO_Init(GPIOC, &myGPIO); //set to C1, C2

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	
  RCC_ADCCLKConfig(RCC_PCLK2_Div6); //clock for ADC (max 14MHz, 72/6=12MHz)
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //enable ADC clock

  // DMA1 channel1 configuration ----------------------------------------------
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_DualConvertedValueTab;
  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_Word; // 32bit
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; // 32bit
  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 DMA1 Channel1
  DMA_Cmd(DMA1_Channel1, ENABLE);
	
  //configure ADC1 parameters
  myADC.ADC_Mode = ADC_Mode_Independent;
  myADC.ADC_ScanConvMode = ENABLE;
  myADC.ADC_ContinuousConvMode = ENABLE;
  myADC.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  myADC.ADC_DataAlign = ADC_DataAlign_Right;
  myADC.ADC_NbrOfChannel  = 2;
  ADC_Init(ADC1, &myADC);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5); //PC1 as Input
  ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 2, ADC_SampleTime_55Cycles5); //PC2 as Input
  ADC_DMACmd(ADC1, ENABLE);

  //enable
  ADC_Cmd(ADC1, ENABLE);

  //Calibrate ADC *optional?
  ADC_ResetCalibration(ADC1);
  while(ADC_GetResetCalibrationStatus(ADC1));
  ADC_StartCalibration(ADC1);
  while(ADC_GetCalibrationStatus(ADC1));

  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

int main(void)
{
    GPIO_config(); //configure pins
    adc_config(); //configure ADC
	
    while(1)
    {
        x = ADC_DualConvertedValueTab[0] * 3.3/4095; //get analog value and convert to volts, 12bit ADC
 
        if(x > 2)
        {
          GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_SET);//turn LED on 1
        }
        else 
        {
          GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_RESET);//turn LED off 0
        }
				
        y = ADC_DualConvertedValueTab[1] * 3.3/4095; //get analog value and convert to volts, 12bit ADC
 
        if(y > 2)
        {
          GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);//turn LED on 1
        }
        else 
        {
          GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET);//turn LED off 0
        }
    }
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/