Merhaba,
Bu yazımızda önce UART haberleşmenin ne olduğuna değinip daha sonra uygulama kısmına geçeceğiz. UART Universal Asycnhoronous Receiver Transmitter (ya da USART, Universal Asycnhoronous Receiver Transmitter) anlamına gelen iki yönlü bir haberleşmedir. UART ileride uygulamalarını yapacağımız I2C ve SPI gibi fiziksel bir bağlantı kurar fakat I2C ve SPI’dan farklı olarak bir Clock sinyaline ihtiyaç duymamaktadır. Haberleşen iki cihaz arasında “Baud Rate” adı verilen bir atım oranı kullanır. Bu oran 1200, 4800, 9600, 19200, 38400 ve 115200 olarak konfigüre edilebilmekte ve haberleşme hattının her iki yanında bulunan cihaz için aynı olacak şekilde seçilmelidir. I2C ve SPI’dan bir diğer farkı ise birden fazla cihazın aynı UART hattına bağlanamayacağıdır (Dezavantajlı bir durum).
Veri transferi gerçekleşirken önce bir “Start” biti gönderilir ve ardından göndermek istediğimiz veri haberleşme yoluna aktarılır. Verilerin doğruluğunu kontrol etmek adına UART haberleşme “Parity” biti kullanır ve parity biti veri paketlerinin hemen arkasında bulunur. Parity biti “odd” veya “even” olabileceği gibi dilerseniz kullanılmamak üzere “none” olarak konfigüre edilebilir. Son adımda ise haberleşmesinin sonunu belirtmek adına bir “Stop” biti (2 bit olarak da gönderilebilir) gönderilir. Şekil 2’de veri paketlerinin genel görümünü inceleyebilirisiniz.
Uygulamamıza başlamadan önce yine bu noktada durup geliştirme kitinizin datasheetini incelemenizi rica ediyorum. “USART Communication” başlığı altında kitinizin kaç adet UART kanalına sahip olduğu ve kitinizin üzerinde bulunan USB portuna hangi kanalın bağlı olduğu gibi önemli bilgileri edinmelisiniz. Kullandığım STM32F767ZI için bu durumun nasıl olduğuna Şekil 3 ile göz atalım.
STM32F767ZI için USART 3 kanalının USB portuna bağlı olduğunu ve PD8 ile PD9 pinleri ile kullanıldığını görmekteyiz. Pin adının önemi ise CubeMX üzerinden konfigürasyon yaparken bazı fonksiyonların alternatif pinlerinin olmasıdır. Bu durumda sizler bu alternatif pinleri de kullanarak aynı çevresel birimi kullanabilmiş olacaksanız. Alternatif pinlerin nedeni daha karmaşık bir dizayn yaparken işinizi kolaylaştıracak farklı seçeneklerin bulunmasını sağlamaktır. Konfigürasyonu yaparken bunu dikkate almak faydalı olacaktır.
Şekil 4 üzerinde gösterildiği gibi önce “Connectivity” sekmesinden USART 3’e tıklayıp, açılan pencereden haberleşme modunun asenkron olacağını belirtiyoruz. Şimdi dikkat edilmesi gereken husus yeşil renkte olan konfigüre edilmiş pinler olacaktır. Görüldüğü üzere datasheetin söylediği USB potuna bağlı olan USART 3 pinleri PD8 ve PD9 idi ve seçilen pinler o pinler değildir. Bu durumda alternatif pinler olan PD8 ve PD9’u seçmemiz gerekecektir. Alternatif pinini görmek istediğiniz pinin üzerine gelip sırasıyla Ctrl+sol tık yapmanız yeterli olacaktır. Alternatif pinin rengi açık mavi olarak siz bu şekilde tıkladığınız sürece yanacaktır (Biraz görmesi problem olabilir ?). Alternatif USART 3 pinlerini dokümandan öğrendiğimize göre söz konusu pinlere tıklayıp açılan sekmeden USART3_Rx ve USART3_Tx olarak ayarlayacağız. Yeni görünümümüz Şekil 5’te gösterildiği olacaktır. Yapacağımız adımları uzatmamak adına “Parameter Settings” sekmesinde herhangi bir değişiklik yapmadan bırakıyoruz. Ancak sizler dilerseniz daha önce bahsetmiş olduğumuz Baud Rate, Parity biti vb. konfigürasyonlarla oynayabilirsiniz. Tabi her iki cihaz için de aynı olmak şartıyla…
Buradan sonraki adımları artık öğrendiğinize göre programımızı yazmaya başlayabiliriz. Keil tarafında programımız açıldığında her zaman olduğu gibi “functions” sekmesinden UART fonksiyonlarına göz atalım.
Birçok metot kullanımımıza sunulmuş durumdadır. Bazı farklı UART kullanımlarını ileride sizlerle paylaşacağımızın bilgisini vermeden devam etmeyelim. Burada çok temel düzeyde bilgisayarınıza bir string göndermekle başlayalım. Ardından bilgisayardan sizin göndereceğiniz yanıtı debug kısmında bir watch tablosu üzerinde gösterelim. Veri aktarımı için HAL API bizlere HAL_UART_Transmit, veri edinimi içinse HAL_UART_Receive adında iki adet temel fonksiyon sunmaktadır. Aşağıdaki programı inceleyerek konuyu irdelemeye devam edelim.
Öncelikle yukarıda “uint8_t” veri tipinde ve dilediğimiz boyutta bir array tanımlamakla başlıyoruz. Şekil 7’ de görüldüğü gibi bu uygulamada biz 8 elemanlı “receiveBuffer” adında bir değişken tanımladık. Bir kereliğine mahsus olarak “while” döngüsü dışında bir mesaj yolladık. HAL_UART_Transmit fonksiyonu parametre olarak kullandığınız birimin adını, göndermek istediğiniz veriyi, göndermek istediğiniz verinin boyutunu ve son olarak bir “timeout” değeri alır. Bir sonraki adımda ise döngü içerisinde sürekli veri olup olmadığını kontrol etmek adına HAL_UART_Receive fonksiyonunu çağırdık. Sürekli olarak veri olup olmadığını kontrol ettiğimiz bu duruma “polling” metodu denir. İleriki uygulamalarda sürekli kontrol etmek yerine interrupt ve DMA metotlarına göz atacağız. HAL_UART_Receive fonksiyonu parametre olarak kullandığınız birimin adını, veriyi tutacağınız değişkeni, maksimum kaç byte veri alacağımızı ve son olarak bir “timeout” değerini alır. Gönderdiğimiz veriyi bilgisayarda görüntülemek ve sonrasında kitinize veri gönderebilmek adına herhangi bir seri terminal programı kullanabilirsiniz (Arduino IDE’nin seri portu, Hercules, RealTerm vb.). Biz bu uygulamamızda kullanımının basit olduğunu düşünerek Hercules programını kullanıyoruz.
Kitinizi programladıktan sonra debug moduna geçip receiveBuffer değişkeninin bir gözlem tablosuna aktaralım (Önceki yazılarımızdan hatırlayabilirsiniz). Programı çalıştırdıktan sonra uygulamamızda olup bitenleri hercules üzerinden görüntüleyebiliriz.
Gözlem tablosunda “merhaba!” mesajını görebildiyseniz kendinizi başarmış sayabilirsiniz ?. Bir sonraki uygulamamızda görüşmek üzere hoşça kalın.