C ile AVR Programlama -22- USART Kullanımı ve Örnek Kod İncelemesi

AVR’nin USART yazmaçlarını önceki yazımızda bitirmiştik. Artık bu yazmaçlar üzerinden nasıl program yazılacağı ve USART biriminin nasıl kullanılacağını anlatalım. Yazmaçların ADC birimine göre biraz daha ayrıntılı olması ve farklı iletişim tiplerinin ortak kullandığı bitler olması biraz kafamızı karıştırabilir. USART prensipte çok basit olduğu için sadece bayt alma ve bayt gönderme olarak kısa fonksiyonlar yazarak bunu gerçekleştirmemiz mümkündür. Aynı ADC biriminde olduğu gibi öncelikle USART birimini hazır hale getirmek için bir fonksiyon yazmak zorundayız. Bu fonksiyonu yazarak işe başlayalım.

USART birimi yüklenmesi için şu adımlar gerçekleştirilmelidir,

  1. Baud Oranı Ayarlanmalıdır
  2. Veri Boyutu Ayarlanmalıdır
  3. TXEN ve RXEN bitleri ile Alıcı ve Verici Etkinleştirilmelidir.
  4. Eşlik biti ve Stop bitlerinin sayısı ayarlanmalıdır.

Şimdi bunu program kodu üzerinden görelim.

Bu örnek kodda her komutun ne iş gördüğünü açıklamada yazsak da komutlara bakarak anlamak için bunu yazmaçlar üzerinden anlatmak lazımdır. Öncelikle yukarıda tanımladığımız makroların işlevinden bahsedelim. Yukarıda baud 9600 olarak belirlenmiştir. Bunu anlamak kolay olsa da BAUDRATE olarak tanımlanan makrodaki matematik işlemi bize yeni görünecektir. Mikrodenetleyicinin teknik veri sayfasında UBRR yazmacına yazılacak baud oranının hesabına dair bir formül mevcuttur. Bu kod bu formülün kod haline dönüşmüş şeklidir. Merak edenler için aşağıda formülü verelim.

Kısaca açıklarsak F_CPU değerinde bulunan işlemcinin saat hızı ile BAUD değerinin 16’ya çarpımı bölünür ve bundan 1 çıkarılır. Delay fonksiyonlarında olduğu gibi F_CPU tanımını yapmamışsak yapmamız gerekir. Örneğin #define F_CPU 16000000UL komutu işlemci saat hızının 16MHz olduğunu belirtir.

UBRRH = (BAUDRATE>>8);

Bu kod elde edilen BAUDRATE değerinin bitlerini 8 bit sağa kaydırarak ilk bitleri 8 bitlik ölçüde açığa çıkarır. Örneğin elimizde 12 bitlik bir “0000111111111111” değeri olsun. Bunu sekiz bitlik bir yazmaca yüklediğimizde sağdaki sekiz bit yüklenecek fakat soldaki sekiz bit yüklenemeyecektir. Bunu Yüksek ve Düşük yazmaçlarına sığdırmak için öncelikle sağdaki sekiz birlik düşük yazmaç değerini atmamız gerekir. Bu işlemden sonra değerimiz “00000000000001111” olacaktır. Böylelikle bu dört bit yüksek yazmacın ilk dört bitine yazılacaktır. Geri kalan değer ise bir sonraki komutta düşük yazmaca yazılacaktır. Elimizdeki mikrodenetleyici 8-bit olduğu için böyle büyük değerleri sığdırmak zorunda kalıyoruz.

UBRRL = BAUDRATE;  Burada düşük yazmaca BAUDRATE’in tamamı yazdırılmış gibi görünse de aslında sağdaki sekiz biti yazdırılmıştır. Geri kalan bitler de yazdırıldığına göre baud oranı değerini yazdırma ve bu oranı ayarlama işlemi bitmiş oluyor.

UCSR0B|= (1<<TXEN)|(1<<RXEN);  UCSRB yazmacındaki TXEN ve RXEN bitleri bir (1) yapılır. Bu aynı ADC’de ADEN bitinin bir (1) yapılması gibi alıcı ve vericiyi etkinleştirir.

UCSR0C|= (1<<UCSZ0)|(1<<UCSZ1);  Veri formatının nasıl seçildiğini anlamamız için tekrar yazmaçlara bakmamız lazım. Burada UCSZ0 ve UCSZ1 bitleri bir (1) yapılmıştır. Tablodan anlaşıldığı üzere iletişim 8 bitlik bir veri genişliğinde yapılacaktır. Bundan başka iletişim UMSEL bitlerinin 00 olmasıyla asenkron olduğu için değiştirme gereği duymadık.

Şimdi veri gönderme ve veri alma fonksiyonlarını inceleyelim.

Burada UDRE veri yazmacı bayrağı bir (1) olmadığı sürece program döngüde tutulur ve sonrasında UDR yazmacına fonksiyonun argüman olarak aldığı data değeri yazılır. İşlem bu kadardır.

Öncelikle UCSRA yazmacındaki RXC bayrak bitinin bir (1) olup olmadığı kontrol edilir. Veri alma tamamlanınca bu bit bir (1) olacağı için döngüden çıkılır. Sonrasında UDR yazmacının içindeki değer fonksiyondan döndürülür.

 

Temel olarak USART işlemi bu kadardır. Sonraki yazıda diğer kodları inceleyeceğiz ve konumuza devam edeceğiz.

Kaynaklar:

ATmega328P – Microchip Technology , http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf, Erişim Tarihi: 18.08.2018

Yash Tambi, Mayank Prasad, The USART of the AVR, http://maxembedded.com/2013/09/the-usart-of-the-avr/, Erişim Tarihi 21.08.2018

 

Kapak Resmi : http://10rem.net/media/82343/Windows-Live-Writer_b3541542a059_B73E_image_21.png

UYARI!!

Gökhan Dökmetaş

"Arduino Eğitim Kitabı" ve "Arduino ve Raspberry PI ile Nesnelerin İnterneti" kitaplarının yazarı. Başkent Teknoloji ve Dedektör Merkezi'nde Ar-ge Sorumlusu. Araştırmacı-Yazar.

You may also like...

9 Responses

  1. İlker Aykut dedi ki:

    Hocam merhaba while (!( UCSRA & (1<<UDRE))); bu kodu tam olarak anlayamadım.Yukarıdaki açıklamada Burada UDRE veri yazmacı bayrağı bir (1) olmadığı sürece program döngüde tutulur ve sonrasında UDR yazmacına fonksiyonun argüman olarak aldığı data değeri yazılır şeklinde açıklanmış ama (1<<UDRE) kısmı UDR Yİ 1 YAPMIYOR MU ?

    • Gökhan Dökmetaş dedi ki:

      Hayır udre bir olmuyor 1 değeri udre bitinin numarası kadar sola kaydırılıp UCSRA ile AND işlemine tabi tutuluyor. Giriş/Çıkış işlemlerini anlattığım derse yeniden bakın.

  2. İlker Aykut dedi ki:

    #define BAUDRATE ((F_CPU)/(BAUD*16UL)-1) hocam buradaki UL nin yazılma amacı nedir?

  3. İlker Aykut dedi ki:

    Hocam F_CPU yerine 16000000 yazınca hata verdi?Sebebi nedir acaba?

  4. Ersin Bulan dedi ki:

    Hocam İyi günler

    UCSRA yazmacında UDRE biti 1 ise UDR bellek boştur yani veri gönderilmiştir demek.

    while (!( UCSRA & (1<<UDRE))); bu döngüde
    UCSRA yazmacının 3. biti (UDRE) 1 ile AND'de tabi tutuluyor.

    UCSRA yazmacındaki UDRE biti 1 iken while (0) şeklinde olmaktadır ve blogun çalışmaması lazım
    UCSRA yazmacındaki UDRE biti 0 iken while (1) şeklinde olmaktadır ve blog çalışmaktadır

    yanlış mı anlıyorum while bloğunu?
    Yardımcı olbilir misiniz?

    • 1 ile UDRE biti VE işlemine tabi tutuluyor. Burada kadar doğru ama soldaki DEĞİL (!) operatörünü de hesaba katmak lazım. Bu durumda bitler terslenmiş oluyor.

  5. Ersin Bulan dedi ki:

    UCSRA yazmacında
    ** UDRE biti 1 için => DEĞİL (!) terslenmiş haliyle while bloğunun (0) olmaktadır
    dolayısıyla bloğun çalıştırılmaması ve veri gönderilmemesi gerekmektedir, bellek boş olmasına rağmen
    UDRE biti 0 için => DEĞİL (!) terslenmiş haliyle while bloğunun (1) olmaktadır

    bu kodda kaçırdığım vey ayanlış anladığım kısım nedir

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.