C ile AVR Programlama -23- UART Kütüphanesi
avr-libc kütüphanesinde bir örnek projede yer alan usart kütüphanesi olsa da AVR’de bu tarz kütüphanelerin resmi sürümleri Arduino’da olduğu gibi yoktur. Bizim yapmamız gereken teknik veri sayfasını (datasheet) okumak ve bunun üzerinden C/C++ dilinde kod yazmaktır. Fakat AVR’nin açık kaynak programcılık anlayışında olan bir kullanıcı kitlesi olduğu için kullanıcılar tarafından yazılan kütüphaneler internette ücretsiz kullanıma sunulmaktadır. Biz de yazdığı kütüphaneleri AVR topluluğu tarafından yaygınca kullanılan bir geliştiricinin kütüphanesini inceleyip kütüphane referansını size anlatacağız. Amatör kütüphaneler oldukça fazla olsa da kaliteli ve taşınabilir (portable) kütüphane yazmak usta işidir. Bu inceleyeceğimiz kütüphane de genel olarak taşınabilirliği ve işlevi yüksek bir kütüphanedir. Bu kütüphanenin fonksiyonlarını tek tek açıklayacağız. Öncelikle kütüphane dosyalarını aşağıdaki bağlantıdan indirip bilgisayarımızda açalım.
http://homepage.hispeed.ch/peterfleury/uartlibrary.zip
Kütüphanenin referans kılavuzu yazıldığı için kütüphaneyi açıp tek tek kodları incelemek zorunda değiliz. O yüzden öncelikle değer tanımlamaları ve makrolar ile başlayalım ve sonra fonksiyonlara geçelim.
#define UART_BAUD_SELECT( baudRate, xtalCpu ) (((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) -1UL)
Bu makro UART iletişim için baud oranınnı belirlemek için kullanılır. Önceki yazımızda baud oranını nasıl yazmaçlara yazmak için bir işlem uyguladığımızı anlatmıştık. Aynı işlem burada da uygulanmaktadır fakat xtalCpu ve baudRate adında iki değerden bahsedilmektedir. Bunlar bizim belirleyeceğimiz değerler olup xtalCpu sistemin saat hızı (16000000UL gibi) baudRate ise baud oranıdır (9600 gibi).
#define UART_BAUD_SELECT_DOUBLE_SPEED( baudRate, xtalCpu ) ( ((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) -1UL)) | 0x8000)
Bu makro yukarıdaki makronun aynısı olup Atmega’nın çift hız modunda kullandırır.
#define UART_RX_BUFFER_SIZE 32
UART iletişimde alıcının tampon belleğinin kaç bayt olacağını belirler. Bu değer 2’nin katları olmalıdır.
#define UART_TX_BUFFER_SIZE 32
UART iletişimde vericinin tampon belleğinin kaç bayt olacağını belirler. Bu değer 2’nin katları olmalıdır.
void uart_init(unsigned int baudrate)
Bu fonksiyon UART birimini hazır hale getirmeye yarar. Argüman olarak aldığı baudrate ise baud oranıdır. UART_BAUD_SELECT() makrosu ile aldığı baudrate değerini işlemci yazmaçlarına yazdırır.
unsigned int uart_getc ( void )
By fonksiyon tampon bellekteki bayt verisini almaya yarar. Yani UART okuma bu fonksiyon tarafından gerçekleştirilir. Bu fonksiyon değer olarak ilk sekiz bitte tampondan okunan veriyi son sekiz bitte (üst baytta) ise durum mesajını geri döndürür. Durum mesajları şu şekildedir,
- 0 : UART biriminden veri alımı başarılır
- UART_NO_DATA : Alınacak bir veri yok.
- UART_BUFFER_OVERFLOW : Tampondan veri taşması. Yeterince hızlı veri okunmadığı için tampondaki bazı veriler kayboldu.
- UART_OVERRUN_ERROR : UART’da overrun durumu oluştu. UART’ın UDR yazmacındaki mevcut karakter kesme tarafından yeni karakter gelmeden önce okunamadı. Bir veya birkaç karakter kayboldu.
- UART_FRAME_ERROR : Veri çerçevesi hatası
void uart_putc ( unsigned char data )
Gönderilecek veri tamponuna bir baytlık veri eklemeye yarar. Aldığı argüman unsigned char yani byte değerinde olup 0-255 arasıdır.
void uart_puts ( const char* s )
Gönderilecek veri tampon belleğine harf dizisi verisi koymaya yarar .
void uart_puts_p ( const char* s)
Program hafızasına yerleştirilmiş harf dizisi verisini göndermeye yarar.
void uart1_init (unsigned int baudrate)
İkinci uart birimi olan ATmega mikrodenetleyiciler için ikinci UART’ı tanımlamaya yarar.
unsigned int uart1_getc (void)
void uart1_putc ( unsigned char data )
void uart1_put2 ( const char* s)
void uart1_puts_p (conts char* s)
Bu fonksiyonlar UART1 için tanımlanmıştır ve yukarıda aynı addaki fonksiyonlarla aynı görevi gerine getirdiği için açıklama gereği duymuyoruz. Şimdi kütüphanenin test programını inceleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
/************************************************************************* Title: Example program for the Interrupt controlled UART library Author: Peter Fleury <pfleury@gmx.ch> http://tinyurl.com/peterfleury File: $Id: test_uart.c,v 1.7 2015/01/31 17:46:31 peter Exp $ Software: AVR-GCC 4.x Hardware: AVR with built-in UART/USART DESCRIPTION: This example shows how to use the UART library uart.c *************************************************************************/ #include <stdlib.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include "uart.h" /* CPU saat hızını belirle değilse hata mesajı ver. */ #ifndef F_CPU #error "F_CPU undefined, please define CPU frequency in Hz in Makefile" #endif /* Buradan UART baud oranını belirliyoruz */ #define UART_BAUD_RATE 9600 int main(void) { unsigned int c; char buffer[7]; int num=134; /* * Initialize UART library, pass baudrate and AVR cpu clock * with the macro * UART_BAUD_SELECT() (normal speed mode ) * or * UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode) */ uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); /* * kesmeleri etkinleştiriyoruz */ sei(); /* * Transmit string to UART * The string is buffered by the uart library in a circular buffer * and one character at a time is transmitted to the UART using interrupts. * uart_puts() blocks if it can not write the whole string to the circular * buffer */ uart_puts("String stored in SRAM\n"); /* * Transmit string from program memory to UART */ uart_puts_P("String stored in FLASH\n"); /* * Use standard avr-libc functions to convert numbers into string * before transmitting via UART */ itoa( num, buffer, 10); // convert interger into string (decimal format) uart_puts(buffer); // and transmit string to UART /* * Transmit single character to UART */ uart_putc('\r'); for(;;) { /* * Get received character from ringbuffer * uart_getc() returns in the lower byte the received character and * in the higher byte (bitmask) the last receive error * UART_NO_DATA is returned when no data is available. * */ c = uart_getc(); if ( c & UART_NO_DATA ) { /* * no data available from UART */ } else { /* * new data available from UART * check for Frame or Overrun error */ if ( c & UART_FRAME_ERROR ) { /* Framing Error detected, i.e no stop bit detected */ uart_puts_P("UART Frame Error: "); } if ( c & UART_OVERRUN_ERROR ) { /* * Overrun, a character already present in the UART UDR register was * not read by the interrupt handler before the next character arrived, * one or more received characters have been dropped */ uart_puts_P("UART Overrun Error: "); } if ( c & UART_BUFFER_OVERFLOW ) { /* * We are not reading the receive buffer fast enough, * one or more received character have been dropped */ uart_puts_P("Buffer overflow error: "); } /* * send received character back */ uart_putc( (unsigned char)c ); } } } |
Burada yukarıdan itibaren başlayarak kodları Türkçe açıklayalım. Öncelikle 17. satırda uart.h başlık dosyasını programımıza ekliyoruz. Sonrasında ise F_CPU değerini tanımlamamız gerektiği için (delay kütüphanesinde olduğu gibi) bir hata mesajı ile bu denetlenmiş. Bunu da 21. ve 23. satırlar arasında görebiliriz. UART_BAUD_RATE değerini bizim tanımlamamız gerektiği için 26. satırda uart baud oranı değeri 9600 olarak tanımlanmış. 43. satırda uart_init fonksiyonunun kullanımına örnek verilmiş ve bizim önceden belirlediğimiz değerler argüman olarak alınmış. 48. satırda ilk gördüğümüz sei() fonksiyonu kullanılmıştır. Bu fonksiyon kesmeleri etkinleştirmek için kullanılır. Kütüphane UART kesmeleri ile çalıştığı için bunu açmamız gerekir. 57. satırda uart_puts() fonksiyonu ile SRAM’da tutulan string verisi gönderilmiştir. 62. satırdaki uart_puts_p() fonksiyonu ile de program hafızasında tutulan string verisi gönderilmiştir. 69. ve 70. satırlarda ise integer yani tam sayı değerinin nasıl string değerine dönüştürüleceği ve bunun gönderileceği gösterilmiştir. 76. satırda ise tek bir karakter verisinin UART ile nasıl gönderileceği gösterilmiştir.
87. satırda unsigned int olarak tanımlanan c değişkenine gelen UART verisi yüklenmiştir. 88. satırda kontrol yapıları ile c değişkeninde durum veya hata mesajları denetlenmiş ve buna göre kodların işletilmesi için örnek karar yapıları verilmiştir.
125. satırda ise alınan veriyi tekrar göndermek için bir kod yazılmıştır.
UART kütüphanesini bu örnek programdaki fonksiyonların sözdizimine ve kullanılışına bakılarak kullanmamız gereklidir. Şimdilik AVR’nin USART birimi ile ilgili anlatacaklarımızın sonuna geldik. Bir sonraki konuda görüşmek üzere.
Hatırlatma, UART kütüphanesi kesmeleri kullandığından programa interrupt.h dosyasını eklemeniz ve kesmeleri etkinleştirmeniz gereklidir. Aksi halde çalışmaz.
Kapak Resmi :https://d3s11pzv7w3h1q.cloudfront.net/wp-content/uploads/IC-ATMEGA8A-PU-2.jpg
UYARI!!
Bu sitede yayınlanan yazılar orjinal içerik olup faydalanılan kaynaklar belirtilmiştir. Yazarın izni olmaksızın tamamen alıntı yapılamaz, kopyalanamaz. Kaynak göstermek kaydıyla (Yazının adı, yazar adı ve link) kısmen alıntı yapılabilir.
Merhabalar. Bu kütüphaneyi atmega328 için sorunsuz kullandım. Şimdi atmega128a için kullanmaya çalışıyorum ama olmadı bir türlü. Baud ve f_cpu değerlerini tanımladım ancak değişmesi gereken başka bir yer mi var acaba? neden olmamış olabilir?
bağlantılarımda hata varmış şimdi başardım çok şükür. 🙂
Merhaba software uart ile birlikte kullanmak için örnek bir çalışmanız var mı?