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
}
}
}