AVR Programlama – ADC

ADC Nedir?

Analog dijital dönüştürücü, sürekli bir voltaj değerini (analog), daha sonra dijital hesaplama için kullanılabilen dijital bir cihaz tarafından anlaşılabilen bir binary değere (dijital) dönüştüren bir devredir. Bu ADC devreleri, kendi başlarına ayrı bir ADC IC’leri olarak bulunabilir veya bir mikrodenetleyiciye gömülebilir. Kısaca ADC (Analog to Digital Converter) olarak adlandırılırlar.

Bu yazıda Atmega328p mikrodenetleyicisi içerisinde bulunan dahili ADC biriminin özelliklerine, registerlarına ve kullanımına değineceğiz.

Atmega328p ADC birimi özellikleri;

  • 10 bit çözünürlük
  • 8 kanal giriş
  • Dahili sıcaklık sensörü()
  • 65 ile 260 μS arası çevrim zamanı
  • 150 kSPS e kadar ölçüm
  • 1.1V seçilebilir referans voltajı
  • 0-VCC arası ADC giriş voltajı
  • ADC çevrim tamalanma kesmesi

Yukarıda orta seviye projelerde adc kullanımı için ilgilendiğimiz özellikleri sıraladım. Fakat Atmega328p deki ADC birimi daha bir çok ileri seviye özelliğe (gürültü önleme, uyku modu vs) sahip bunlara datasheetten ulaşabilirsiniz.

ADC Çevrim Zamanı

ADC çevrimi, ADCSRA registerındaki ADCSC biti set edildikten sonra ADC clock cycle’ının yükselen kenarında başlar. Normal bir ADC çevrimi 13 ADC clock cycle’ı kadar zaman alır. Fakat, ADC birimi aktif hale getirildikten sonraki ilk çevrim 25 ADC clock cycle’ı zamanda gerçekleşir.

Normal çevrimde, 13 ADC clock cycle’ı kadar geçen çevrim zamanına ek olarak 1.5 ADC clock cycle’ı da örnekleme ve tutma zamanı için harcanır. Bir ADC çevrimi toplam olarak 13.5 ADC clock cycle’ı kadar sürer.

ADC Çözünürlük Ve Ölçüm Değeri Arasındaki İlişki

ADC birimimiz 10 bit çözünürlükte olduğu için çevrim sonucumuz 0 ile 210 yani 1024 arasında olacaktır. Elde ettiğimiz binary verinin analog karşılığını aşağıdaki formül ile bulabiliriz.

Buradaki “ADC” çevrim sonucu elde ettiğimiz değer. VIN ADC giriş pinine uygulanan analog değer, VREF ise bizim belirlediğimiz referans değeri yani 1024’e karşılık gelecek olan değer.

ADC Registerları

REFS1:0 : Bu bitleri referans voltajı seçerken kullanırız. Değerleri aşağıdaki tablodaki gibidir.

ADLAR : Bu bit değeri elde ettiğimiz 10 bitlik sonucu ADCH ve ADCL data registerlarına yazma türünü belirler. Eğer ADLAR biti set edilirse 10 bitlik adc değeri 16 bitlik hafızada sola dayalı olarak yerleştirilir, RESET konumunda iken de sağa dayalı olacaktır. Aşağıdaki görsel daha anlaşılır hale getirecektir.

MUX3:0 : Bu bitler adc giriş kanalını seçmemizi sağlar. Değerler aşağıdaki tablodaki gibidir.

ADEN : Bu biti set etmek ADC birimini aktif hale getirir. Aynı şekilde ADC birimini kapatmak için ADEN biti 0 yapılır.

ADSC : Bu bit ADC çevrimini başlatmak için kullanılır. Tek çevrim modunda ADSC biti set edildiği zaman çevrim başlar.

ADATE : Bu bitin bir yapılması ADC otomatik tetikleme modunu aktif hale getirir.

ADIF : ADC kesme bayrağıdır.

ADIE : Bu biti 1 yapmak ADC çevrim tamamlanma kesmesini aktif hale getirir.

ADPS2:0 : Bu bitler, sistem saat frekansı ile ADC saat frekansı arasındaki bölme faktörünü belirler. Değerler aşağıdaki tablodadır. ADC birimini istediğimiz saat frekansında çalıştırabiliriz.

ADC Örnek

 #define F_CPU 16000000UL
 #include <avr/io.h>
 #include <util/delay.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 

 #define USART_BAUDRATE 9600
 #define UBRR_VALUE (((F_CPU/(USART_BAUDRATE*16UL)))-1)
 
 void serial_init();
 void serial_sends(char* s);
 void serial_send(unsigned char data);
 void adc_init(void);
 int adc_read(void);

 
 
 
 int main(void)
 {

 char data[31];
 int adcdeger = 0;
 DDRC &= ~(1<<5); // ADC5 kanalının bağlı olduğu PC5 i giriş olarak tanımladık
     
     serial_init();
     adc_init();
     
     while (1) 
     {
       adcdeger = adc_read();  // ADC5 kanalından ölçüm yap
       sprintf(data,"ADC deger : %d \n \r",adc deger); // ölçülen degeri karakter dizisine at
       serial_sends(data); // karakter dizisini uart a gönder
       _delay_ms(1); // 1ms bekle
    }
 }
 void adc_init(void)
 {
     ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));   // 125Khz ADC referans saati
     ADMUX |= (1<<REFS0); // Referans AVCC yani 5V
     ADCSRA |= (1<<ADEN); // ADC'yi Aç
     ADCSRA |= (1<<ADSC); // İlk deneme ölçümünü yap ve diğer ölçüme hazır hale getir.
 }
 int adc_read(void)
 {
     ADMUX &= 0XF0;
     ADMUX |= (1<<2)|(1<<0); //ADC5 Kanalı seçildi
     ADMUX &= ~(1<<3);
     ADMUX &= ~(1<<1);
     ADCSRA |= (1<<ADSC);  //ADC çevrimi başladı
     while(!(ADCSRA & (1<<ADIF))); // çevrimin bitmesini bekle
     return ADCW; // ADCH ve ADCL degerlerinin bir arada bulunduğu register
 }
 void serial_init()
 {
      
     UBRR0=UBRR_VALUE; // baud rate ayarla
     UCSR0B|=(1<<TXEN0); //TX aktif
     UCSR0B|=(1<<RXEN0); //RX aktif
     UCSR0B|=(1<<RXCIE0); //RX complete interrupt
     UCSR0C|=(1<<UCSZ01)|(1<<UCSZ01); // no parity, 1 stop bit, 8-bit data
 }
 void serial_sends(char* s)
 {
     // gönderilen karakter NULL olana kadar adresi bir arttırarak gönder
     while(s > 0) serial_send(s++);
 }
 void serial_send(unsigned char data)
{
 UDR0 = data; // data yı gönder 
 while(!(UCSR0A&(1<<UDRE0))){}; //Bir önceki byte gönderilene kadar bekle
}


Bu örnekte kullandığım UART ile ilgili daha fazla bilgiye AVR Programlama USART yazımdan ulaşabilirsiniz.

ADC örneği devre şeması

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s