Bu yazımda assembly dilini kullanarak STM32F4 Discovery kiti ile Uart haberleşmeyi göstereceğim. İlk olarak Uart’ın ne olduğu ile başlayalım. Uart yani Universal Asynchronous Receiver/Transmitter, elektronik iki cihaz arasında kullanılan en eski ve en basit haberleşme protokollerinden biridir. İletişim Rx + Tx olmak üzere iki tel ile yapılır. Full-duplex yapıdadır.
Yukarıdaki resimde protokol görülebilir. İletişim 1 start biti ile başlar, bu bit her zaman ‘0’ değerindedir. Start bitinin ardından veriyi içeren bitler gelir, veri uzunluğu genelde 8 bit bittir ancak uygulamaya göre 5, 6, 7 … şeklinde de ayarlanabilir. Veri bitlerinin ardından parity bitleri gelir. Parity verinin doğruluğunu sağlamak için kullanılır , kullanılması zorunlu değildir, 1 ya da 2 bit olabilir. Son olarak iletişimin sonlandığını belirten stop biti vardır, bu bit her zaman ‘1’ değerindedir.
İletişimin hızı baudrate ile ölçülür. 1 baudrate, 1 saniyede 1 baud aktarıldığını gösterir. Genelde 9600, 19200, 57600 gibi değerler kullanılır ancak uygulamaya göre farklı değerler de kullanılabilir.
Şimdi Stm32f4 Discovery kiti üzerinde uygulamasini yapalim. İlk olarak mikrodenetleyicinin clock ayarını yapalım. Bunun için STM Stm324f için nin yayınladığı Referance Manuel’in (RM0090) RCC kısmına bakalım. Referance Manuelde gördüğümüz gibi Stm32f407’nin clock donanımı aşağıdaki gibidir.
Biz uygulamada kitin üzerinde bulunan 8Mhz kristali kullanacağız. PLL ve bölücü kullanmadan işlemci 8Mhz'de çalışacak. Bunun için HSE donanımını aktifleştirip, clock kaynağını HSE seçeceğiz. Bunları yapabilmek için Reference Manuel’den RCC donanımının registerlerine bakıyoruz. RCC_CR registerinin 16.bitini ‘1’ yaparak HSE’yi aktifleştirmiş oluyoruz. İkinci olarak RCC_CFGR registerinin 1:0 bitlerini ‘01’ yaparak işlemcinin clock kaynağını HSE olarak belirlemiş oluyoruz. Son olarak kullanacağımız GPIO (GPIOA) ve USART (USART2) donanımlarının clocklarını AHB1 ve APB1 clock hattına bağlamamız gerekiyor. USART2 için RCC_APB1ENR registerinin 17.bitini ‘1’ yapmamız, GPIOB için de RCC_AHB1ENR registerinin 0. Bitini ‘1’ yapmamız gerekiyor. Clocking ile ilgili yaptığımız işlemleri assembly ile yazarsak:
RCC EQU 0x40023800
RCC_Ayarları
PROC
LDR R0, =RCC ;RCC register adresini R0'a yükle
LDR R1, [R0]
ORR R1, R1, #0x00010000
STR R1, [R0] ;HSE yi aktif et
LDR R1, [R0, #0x08]
ORR R1, R1, #0x0001
STR R1, [R0, #0x08] ;Mikrodenetleyicinin clock kaynağını HSE yap
MOVT R1, #0x0002
STR R1, [R0, #0x40] ;APB1 den USART2 nin clock unu aktif et
MOV R1, #0x0001
STR R1, [R0, #0x30] ;AHB1 den GPIOB nin clock unu aktif et
ENDP
Sırada GPIO ayarları var. Bu projede iletişim için USART2 donanımına bağlı PA2 ve PA3 pinleri kullanıldı. USART haberleşmesi için pinlerin pull-up şeklinde konfigürasyon edilmesi gerekir. Bunun için yine Referance Manuelin GPIO registerlerine baktığımızda, GPIOA_PUPDR registerinin 5:2 bitlerinin ‘1010’ yapılması gerekiyor. İkinci olarak bu pinlerin USART2 donanımına bağlanabilmesi için pinllerin, Alternate function tipinde olması ve Alternate function'ın USART2 olarak ayarlanması gerekiyor. Alternate function için GPIOA_MODER registerinin 5:2 bitlerinin ‘1010’ şekline, GPIOA_AFRL registerinin 15:8 bitlerinin ‘0111 0111’ şekline ayarlanması gerekiyor. Yaptılarımızı assembly ile yazarsak:
GPIOA EQU 0x40020000
GPIO_Ayarları
PROC
LDR R0, =GPIOA ;GPIOA register adresini R0 a yaz
LDR R1, [R0]
ORR R1, R1, #0x00A0
STR R1, [R0] ;GPIOA_2,3 ü alternate function olarak ayarla
LDR R1, [R0, #0x0C]
ORR R1, R1, #0x0050
STR R1, [R0, #0x0C] ;GPIOA_2,3 pinlerini pull-up yap
LDR R1, [R0, #0x20]
ORR R1, R1, #0x7700
STR R1, [R0, #0x20] ;GPIOA_2,3 ü USART2 ye bağla
ENDP
Son olarak USART donanımının konfigürasyonu var. Bu uygulamada baud rate 9600 olarak seçilmiştir. Referance Manuel in USART kısmında Baudrate hesabı için aşağıdaki denklem verilmiş.
Burada baud rate, USART donanımının çalışma frekansı yani APB1 üzererinden gelen clock frekansı, donanımın istenilen baud rate için ayaralanmasını sağlayan değer, ise oversampling'dir. Biz oversampling kullanmayacağımızdan bu bitin değeri ‘0’ olacaktır. İşlemi 9600 baud rate için yaparsak;
Bulduğumuz bu değeri USART2_BRR registerine yazmak için mantissa ve fraction şeklinde ikiye ayırmamız gerekmekte.
Mantissa değerini USART2_BRR registerinin 15:4, Fraction değerini ise 3:0 değerine yazıyoruz. USART donanımını, veri gönderme ve almayi aktif etmek için USART2_CR1 registerinin 2, 3 ve 13. bitlerini ‘1’ yapıyoruz. Yaptıklarımızı assembly ile yazarsak:
USART2 EQU 0x40004400
USART_Ayarları
PROC
LDR R0, =USART2
MOV R1, #0x0341
STR R1, [R0, #0x08] ;USART2 nin baudrate sini 9600 olarak ayarla
MOV R1, #0x200C
STR R1, [R0, #0x0C] ;USART2 yi aktif et
ENDP
Bu ayarları yaptıktan sonra USART donanımı çalışmaya hazır. Test için echo uyglaması yapalım. Programın algoritması aşağıdaki gibi olacaktır:
Rx’ten gelen bir veri olup olmadığını USART2_SR registerindeki RXNE (Read Data Register not Empty) bitinden öğrenebiliriz. Program aşağıdaki gibi olacaktır:
USART2 EQU 0x40004400
LDR R0, =USART2
Echo
LDR R1, [R0]
AND R1, R1, #0x0020
CMP R1, #0x0020 ;USART2 nin RXNE bitini kontrol et
BNE Echo ;Eğer veri gelmemişse başa dön
LDR R1, [R0, #0x04] ;USART2 ye gelen veriyi R1 e yaz
STR R1, [R0, #0x04] ;R1 deki veriyi USART2 ile gönder
B Echo ;Başa dön
Ve sonuç:
çok iyi benim için önemli olan assembler programdır , emeklemeden yürümemek gerekir
assembler programla ilgili yazılarınıza (PWM - TİMER - RTC) vs... devam etmenizde fayda var
sadece STM32F degil DSPIC lerle ilgili assembler programlarınızı görmek istiyorum
Bertan bey yazılarınızı yeni keşfetmenin hem üzüntüsü hem de sevinci içerisindeyim. Ellerinize sağlık. Sizlere bir mail attım FPGA programlama ile ilgili, olumsuz da olsa geri dönüş yapabilir misiniz ? Kolaylıklar diliyorum, Bu güzel işlerinizin devamının gelmesi dileği ile, hoşçakalın.