ADC – Analog – Dijital Çeviriciler – ARM Programlama

  • ADC, Analog veriyi dijital veri haline getirme işlemine denir.
  • STM32F407VG içerisinde 3 tane ADC birimi mevcuttur.
  • ADC biriminin ulaştığı maksimum hız 36 MHz’dir.

Çevrim Hızları

ÇözünürlükADC Çevrim Hızı
12 Bit12 Cycle
10 Bit10 Cycle
8 Bit8 Cycle
6 Bit6 Cycle
  • STM32F407VG mikrodenetleyicisi 0 V – 3.6 V aralığında ölçümler yapılabilmektedir.
  • Buradaki voltaj aralığı ADC biriminin beslemesi (VDDA – VSSA) ile ilgili bir durumdur.
  • ADC biriminin besleme voltajı ve referans gerilimi (VREF+ , VREF-), ADC biriminin ölçebileceği gerilim aralığını belirler. Fakat her ne olursa olsun ADC birimi 3.6 V değerinden büyük bir değer ölçemez.
  • ADC biriminin besleme gerilimi is (VDDA) tam hız çalışmada 2.4 V – 3.6V aralığında, daha düşük hızdaki çalışmalarda ise minimum 1.65 V değerinde olmalıdır.
  • STM32F407VG 24 tane ADC giriş kanalına sahiptir.
  • ADC1’in 3 adet kanalı, mikrodenetleyicinin dahili ısı sensörüne, dahili referans voltaj kaynağına (1.2 V) ve batarya ölçümü için Vbat ucuna bağlanmıştır.
  • Analog bir değeri dijital bir değere dönüştürürken dikkat edilmesi gereken bir takım hususlar bulunmaktadır.
  • Bunlardan en önemlisi; ölçülecek analog gerilim değerinin, dönüşümü yapacak çipin ölçüm aralığında olması gerektiğidir.
  • Diğer bir husus da ölçüm yapılacak hassasiyetin belirlenmesi ve buna uygun bit genişliğinde bir dönüştürücü seçilmesidir.

Örnek: Voltage Divider (Voltaj Bölücü)

Vin = 36V
R1 = 1K
R2= 9K olmalıdır.

ADC Fonksiyonları

ADCx_Init

  • Bu fonksiyon mikrodenetleyici içindeki ADC birimini yapılandırır.
  • Bu fonksiyon ile yapılandırılan dahili ADC birimi 12 bit çözünürlüğe sahiptir.
  • unsigned int data tipinde dönüşüm sonucu üretir ve voltaj referans kaynakları olarak VDDA – VSSA değerlerini kullanır.
  • ADC1_Init(); //Varsayılan ayarlarla ADC modülünü yapılandırır.

ADCx_Init_Advanced

ADCx_Init_Advanced (harici referans kaynağı, ADC çözünürlüğü)

KomutAçıklama
_ADC_EXTERNAL_REFHarici referans voltajı
_ADC_EXTERNAL_REF_3VHarici 3V referans voltajı
_ADC_EXTERNAL_REF_1VHarici 1V referans voltajı
_ADC_INTERNAL_REFDahili voltaj referans kaynağı
KomutAçıklama
_ADC_RESOLUTION_10BIT10-Bit ADC Çözünürlüğü
_ADC_RESOLUTION_12BIT12-Bit ADC Çözünürlüğü

ADC_Set_Input_Channel

  • Bu komut ile hangi kanal veya kanalların analog giriş olarak seçileceği mikrodenetleyiciye bildirilir. Bunun için 23 tane kanal vardır.
  • ADC_Set_Input_Channel(_ADC_CHANNEL_0|_ADC_CHANNEL_1);

ADCx_Get_Sample

  • Bu fonksiyon ile seçilen ADC kanalı aktif edilir ve bu kanaldan ölçüm yapılır.
  • unsigned olcum;
  • ADC_Set_Input_Channel(_ADC_CHANNEL_10);
  • ADC1_Init();
  • olcum=ADC1_Get_Sample(10);

ADCx_Read

  • Bu fonksiyon ADC kanalını giriş olarak ayarlar, ADC modülünü başlatır ve analog kanal girişini okur.
  • ADCx_Get_Sample fonksiyonundan farkı, bütün ayarlamaları (modülün kurulumu, referans voltajı seçimi vs.) kendi kendine yapmasıdır.
  • Bu ayarlamalar her ADCx_Read komutunda yapıldığı için daha yavaştır.
  • unsigned olcum;
  • olcum=ADC_Read(10);

Örnek: Potansiyometre geriliminin okunması

unsigned okunan;
int ledler;

void kurulum(){
	GPIO_Digital_Output(&GPIOD_BASE, _GPIO_PINMASK_12| _GPIO_PINMASK_13| _GPIO_PINMASK_14| _GPIO_PINMASK_15);
	ADC1_Init();
	ADC_Set_Input_Channel(_ADC_CHANNEL_1);
}

void main(){
	kurulum();
	while(1){
		okunan=ADC1_Get_Sample(1);
		if (okunan>=0 && okunan<1024) GPIOD_ODR=0;
		if (okunan>=1024 && okunan<2048) GPIOD_ODR=(1<<12);
		if (okunan>=2048 && okunan<3072) GPIOD_ODR=(1<<13);
		if (okunan>=3072 && okunan<4095) GPIOD_ODR=(1<<14);
		if (okunan== 4095) GPIOD_ODR=(1<<15);
		delay_ms(150);
	}
}

Örnek: LM35 sensörü ile sıcaklık ölçümü

sbit LCD_RS at GPIOE_ODR.B8;
sbit LCD_EN at GPIOE_ODR.B10;
sbit LCD_D4 at GPIOE_ODR.B4;
sbit LCD_D5 at GPIOE_ODR.B5;
sbit LCD_D6 at GPIOE_ODR.B6;
sbit LCD_D7 at GPIOE_ODR.B7;
unsigned olculen=0;
long toplam=0;
float milivolt=0, sicaklik=0, ortalama=0, filterval=0;
char i=0, txt[15];

void main(){
	GPIO_Digital_Output(&GPIOE_BASE, _GPIO_PINMASK_9);
	GPIOE_ODR.B9=0;
	Lcd_Init();
	Lcd_Cmd(_LCD_CLEAR);
	Lcd_Cmd(_LCD_CURSOR_OFF);
	Lcd_Out(1,1,’’Sicaklik’’);
	ADC1_Init();
	ADC_Set_Input_Channel(_ADC_CHANNEL_12);
	while(1){
		for(i=0;i<100;i++){
			olculen=ADC1_Get_Sample(12);
			toplam+=olculen;
		}
	ortalama=toplam/100.0;
	toplam=0;
	milivolt=ortalama*3000.0/4095;
	sicaklik=milivolt/10;
	FloatToStr(sicaklik,txt);
	if(sicaklik>=1){
		Lcd_Chr(1,10,txt[0]);
		Lcd_Chr_CP(txt[1]);
		Lcd_Chr_CP(txt[2]);
		Lcd_Chr_CP(txt[3]);
		Lcd_Chr_CP(txt[4]);
		Lcd_Chr_CP(‘C’);
	}
	if(sicaklik<1){
		Lcd_Chr(1,10, ‘0’);
		Lcd_Chr_CP(‘.’);
		Lcd_Chr_CP(txt[0]);
		Lcd_Chr_CP(txt[2]);
		Lcd_Chr_CP(txt[3]);
		Lcd_Chr_CP(‘C’);
	}
	}
}

Örnek: LCD’li Dijital Voltmetre

sbit LCD_RS at GPIOE_ODR.B8;
sbit LCD_EN at GPIOE_ODR.B10;
sbit LCD_D4 at GPIOE_ODR.B4;
sbit LCD_D5 at GPIOE_ODR.B5;
sbit LCD_D6 at GPIOE_ODR.B6;
sbit LCD_D7 at GPIOE_ODR.B7;
int sayi=0, mV=0;
char txt[7], volt[9];

int ADC_Olcum(char kanal){
    unsigned long temp=0;   
    char k=0;
    for(k=0;k<128;k++){
        temp+=ADC1_Get_Sample(kanal);
    }
    return temp>>7;
}

void LCD_Yaz(int okunan_deger){
    mV=okunan_deger*0.7185;
    if(mV>=10000) volt[0]=(mV/10000)+48;
    else volt[0]=‘ ‘;
    volt[1]=(mV%10000)/1000+48;
    volt[2]=‘.’;
    volt[3]=(mV%1000)/100+48;
    volt[4]=(mV%1000)%100/10+48;
    volt[5]=(mV%1000)%100%10+48;
    volt[6]=‘ ‘;
    volt[7]=‘V’;
    Lcd_Out(2,1,volt);
}

void main(){
    GPIO_Digital_Output(&GPIOE_BASE, _GPIO_PINMASK_9);
    GPIOE_ODR.B9=0;
    Lcd_Init();
    ADC1_Init();
    ADC_Set_Input_Channel(_ADC_CHANNEL_1);
    Lcd_Cmd(_LCD_CURSOR_OFF);
    Lcd_Out(1,1,’’Voltmetre’’);
    do{
    sayi=ADC_Olcum(1);
    LCD_Yaz(sayi);
    } while(1);
}