STM32 ADC - FabLabSeoul/WingProject GitHub Wiki

STM32 Value line discovery board ์šฉ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŠœํ† ๋ฆฌ์–ผ ์ž…๋‹ˆ๋‹ค.

ADC(Analog to Digital Converter) ํ”„๋กœ๊ทธ๋ž˜๋ฐ

ADC ์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ์€ STM32\stm32vldiscovery_package\Project\Examples\ADC\ ํด๋”์— ์žˆ๋‹ค.

์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ์—์„œ ์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ์ด๋ž€ Voltage ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์ฝ์–ด์˜จ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์„ผ์„œ๋“ค์€ ์ „์••์˜ ์„ธ๊ธฐ๋กœ ์ •๋ณด๋ฅผ ๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์—, ์„ผ์„œ์ฒ˜๋ฆฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ ADC ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ํ•„์ˆ˜๊ฐ€ ๋œ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ์—์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๋œ ์–ด๋–ค ๊ฐ’์„ ์•„๋‚ ๋กœ๊ทธ ์ถœ๋ ฅ์œผ๋กœ ๋ณด๋‚ผ ๋•Œ๋Š” DAC ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•ด์•ผํ•œ๋‹ค.

A/D์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๋ชจ๋“ˆ์€ STM32 Value line discovery๋ณด๋“œ์—์„œ ADC1, ADC2 ๋‘๊ฐœ๋งŒ ์žˆ๋Š” ๊ฑธ๋กœ ๋ณด์ธ๋‹ค. ์ฑ„๋„์„ ์ด์šฉํ•˜๋ฉด ADC1 ์ปจ๋ฒ„ํ„ฐ ํ•˜๋‚˜๋กœ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. STM32 ADC Multi Channel Using DMA ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์ž.

ADC ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์‹œ์ž‘

ํฌํŠธ๋กœ ๋“ค์–ด์˜ค๋Š” ์ „์•• ๊ฐ’์— ๋”ฐ๋ผ LED On/Off๋ฅผ ์ œ์–ดํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ์„ค๋ช…ํ•œ๋‹ค. ์ „์••์„ ํฌํŠธ๋กœ ์ž…๋ ฅ ๋ฐ›์„ ๊ฒƒ์ด๋ฏ€๋กœ, ํฌํŠธ ์ž…๋ ฅ์€ ์•„๋‚ ๋กœ๊ทธ ๋ชจ๋“œ์—ฌ์•ผ ํ•œ๋‹ค. ๋จผ์ €, ํฌํŠธ์— ํ™˜๊ฒฝ์„ค์ •์„ ํ•˜์ž. ์ž…์ถœ๋ ฅ ํ™˜๊ฒฝ์„ค์ •์— ๊ด€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ STM32 discovery ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ฐธ์กฐํ•˜์ž.

ADC ์ž…๋ ฅํฌํŠธ ์„ค์ •

PA6๋ฅผ ์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ ๋ชจ๋“œ๋กœ ์„ค์ •ํ•œ๋‹ค.

myGPIO.GPIO_Pin = GPIO_Pin_6; //set to pin 6
myGPIO.GPIO_Mode = GPIO_Mode_AIN; //set as analog input
GPIO_Init(GPIOA, &myGPIO); //set to A6

ADC ์ „์šฉ ํด๋Ÿญ ์„ค์ •

์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ์šฉ ํด๋Ÿญ์„ ์„ค์ •ํ•œ๋‹ค. STM32 ๋Š” ์ „์••์„ ๋””์ง€ํƒˆ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— cpu clock ๋Œ€๋กœ ์ •๋ณด๋ฅผ ์ฝ๊ฒŒ ๋˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋งค๋‰ด์–ผ 162 ํŽ˜์ด์ง€ ํƒ€์ด๋ฐ ๋‹ค์ด์–ด๊ทธ๋žจ์„ ์ฐธ์กฐํ•˜์ž.

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

ADC ํ™˜๊ฒฝ์„ค์ •

STM32์€ ADC ํ™˜๊ฒฝ์„ค์ •์„ ์œ„ํ•ด ๋ณ„๋„์˜ ๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ณ ์ •๋œ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ํ†ตํ•ด์„œ๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ตฌ์กฐ์ฒด๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ณด๋‹ค ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. STM32 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ •์˜๋œ ADC ๋ ˆ์ง€์Šคํ„ฐ ๊ตฌ์กฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

/** 
  * @brief Analog to Digital Converter  
  */
typedef struct
{
  __IO uint32_t SR;
  __IO uint32_t CR1;
  __IO uint32_t CR2;
  __IO uint32_t SMPR1;
  __IO uint32_t SMPR2;
  __IO uint32_t JOFR1;
  __IO uint32_t JOFR2;
  __IO uint32_t JOFR3;
  __IO uint32_t JOFR4;
  __IO uint32_t HTR;
  __IO uint32_t LTR;
  __IO uint32_t SQR1;
  __IO uint32_t SQR2;
  __IO uint32_t SQR3;
  __IO uint32_t JSQR;
  __IO uint32_t JDR1;
  __IO uint32_t JDR2;
  __IO uint32_t JDR3;
  __IO uint32_t JDR4;
  __IO uint32_t DR;
} ADC_TypeDef;

ADC ํ™˜๊ฒฝ์„ค์ •์€ ADC ๋ ˆ์ง€์Šคํ„ฐ์— ๊ฐ’์„ ๋„ฃ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. STM32 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•จ์ˆ˜์ธ ADC_Init()ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ADC๋ฅผ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋งค๋‰ด์–ผ 158ํŽ˜์ด์ง€๋ฅผ ์ฐธ์กฐํ•˜์ž.

myADC.ADC_Mode = ADC_Mode_Independent;
myADC.ADC_ScanConvMode = DISABLE;
myADC.ADC_ContinuousConvMode = ENABLE;
myADC.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
myADC.ADC_DataAlign = ADC_DataAlign_Right;
myADC.ADC_NbrOfChannel  = 1;
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_55Cycles5); //PA6 as Input
ADC_Init(ADC1, &myADC);

ADC ํ™œ์„ฑํ™”

ADC1 ์„ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๊ณ  ์•Œ๋ฆฌ๊ณ , ADC ๋‚ด๋ถ€ ํšŒ๋กœ๋ฅผ ์ดˆ๊ธฐํ™” ํ•˜๋Š” Calibration ๊ณผ์ •์„ ์‹คํ–‰ํ•œ๋‹ค.

ADC_Cmd(ADC1, ENABLE);

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

//enable ADC to work
ADC_Cmd(ADC1, ENABLE);

ADC ํฌํŠธ๋ฅผ ํ†ตํ•ด ์ฝ์–ด๋“ค์ธ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค์ž.

STM32๊ฐ€ ์‹ฑ๊ธ€๋ณ€ํ™˜๋ชจ๋“œ ์ผ ๋•Œ, ํฌํŠธ๋กœ๋ถ€ํ„ฐ ๋“ค์–ด์˜จ Voltage ๊ฐ’์€ ๋ณ€ํ™˜๋˜์–ด 16๋น„ํŠธ ADC_DR ๋ ˆ์ง€์Šคํ„ฐ์— ์ €์žฅ๋œ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋งค๋‰ด์–ผ 161 ํŽ˜์ด์ง€ single conversion mode ํ•ญ๋ชฉ์„ ์ฐธ์กฐํ•˜์ž.

//get Analog Value at pin
int getPot(void)
{
    return ADC_GetConversionValue(ADC1);
}

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx)
{
  /* Check the parameters */
  assert_param(IS_ADC_ALL_PERIPH(ADCx));
  /* Return the selected ADC conversion value */
  return (uint16_t) ADCx->DR;
}

ADC_DR ๋ ˆ์ง€์Šคํ„ฐ์— ์ €์žฅ๋œ ์ •๋ณด๋Š” Voltage ๊ฐ’์ด ์•„๋‹ˆ๋ฏ€๋กœ, ๋ณ€ํ™˜ํ•ด์ค˜์•ผ ํ•œ๋‹ค. STM32F100x ํ”„๋กœ์„ธ์Šค๋Š” ์ „์•• ์ •๋ณด๋ฅผ ์ตœ๋Œ€ 12bit ์ •๋ณด๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. 0V -> 0x000, 3.3V -> 0xFFF ๋กœ ํ‘œํ˜„๋œ๋‹ค. ์ตœ๋Œ€๊ฐ’์ด ์‹ญ์ง„์ˆ˜๋กœ 4095์ด๊ธฐ ๋•Œ๋ฌธ์—, ์‹ค์ œ ์ „์••์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

double x = getPot()*3.3/4095; //get analog value and convert to volts, 12bit ADC

ADC ์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ

PA6 ํฌํŠธ์— 2V ์ด์ƒ์˜ ์ „์••์ด ๋“ค์–ด์˜ค๋ฉด PC9 ํฌํŠธ๋ฅผ On ํ•œ๋‹ค. STM32 Value line discovery ๋ณด๋“œ๋Š” PC9 ํฌํŠธ๊ฐ€ ๋ณด๋“œ ์œ„์˜ led์™€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ์˜ˆ์ œ๋Š” STM32\stm32vldiscovery_package\Project\Examples\ADC\ ํด๋”์— ์žˆ๋‹ค.

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

double x = 0;
GPIO_InitTypeDef myGPIO;
ADC_InitTypeDef myADC;

void adc_config()
{ 
  // PA6๋ฅผ analog input ๋ชจ๋“œ๋กœ ์„ค์ •ํ•œ๋‹ค.  
  myGPIO.GPIO_Pin = GPIO_Pin_6; //set to pin 6
  myGPIO.GPIO_Mode = GPIO_Mode_AIN; //set as analog input
  GPIO_Init(GPIOA, &myGPIO); //set to A6

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

  //configure ADC parameters
  myADC.ADC_Mode = ADC_Mode_Independent;
  myADC.ADC_ScanConvMode = DISABLE;
  myADC.ADC_ContinuousConvMode = ENABLE;
  myADC.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  myADC.ADC_DataAlign = ADC_DataAlign_Right;
  myADC.ADC_NbrOfChannel  = 1;
  ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_55Cycles5); //PA6 as Input
  ADC_Init(ADC1, &myADC);

  //enable
  ADC_Cmd(ADC1, ENABLE);

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

  //enable ADC to work
  ADC_Cmd(ADC1, ENABLE);
}
 
//get Analog Value at pin
int getPot(void)
{
  return ADC_GetConversionValue(ADC1);
}
 
//Configure other I/O pins
void GPIO_config(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    //LED-pinC9
    GPIO_StructInit(&myGPIO);
    myGPIO.GPIO_Pin = GPIO_Pin_9;
    myGPIO.GPIO_Mode = GPIO_Mode_Out_PP;
    myGPIO.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOC, &myGPIO);
}
 

// The second example is an analog read example. 
// Here we have connected a potentiometer to pin PA6 and are reading the voltage. 
// If it exceeds 2V the LED PC9 turns on, otherwise itโ€™s off.
// https://sourcelion.wordpress.com/2014/09/14/stm32-discovery-get-started-tutorial/
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
    GPIO_config(); //configure pins
    adc_config(); //configure ADC
    while(1)
    {
        x = getPot()*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
        }
    }
}

๋‹ค์Œ ์˜ˆ์ œ


๋ ˆํผ๋Ÿฐ์Šค