MSP430 LaunchPad ile Assembly Programalaya Giriş 2 - Interrupt İşlemleri

  İnterruptlar işlemci o andaki yaptığı işlemden veya uyku durumdan çıkartmak için kullanılabilir. Bu örnekte işlemcimize, kit üzerinde P1.3 e bağlı olan tuştan ve P1.4 bacağına direk olarak +VCC girişindenden bir kablo vasıtası işe +5V vererek interrupt tetiklemesi yapacağız. Referansımız bu pdf olacaktır (Slau144)



  Yazdığımız kod, interruptun hangi porttan geldiğini anlayacak ve sonucunda P1.3 den interrupt geldiyse kırmızı, P1.4 den interrupt geldiyse yeşil led'i yakarak (xor kullandığımızdan her interrupta durumunu değiştirerek) karşılık verecektir.



041h ve 018h
  Bunlar hexadecimal biçimindeki sayılardır. Sonlarındaki h derleyiciye de bu sayıların hexadecimal olduğunu belirtmek içindir. Diğer bi yazım biçimi de 0x41 ve 0x18 şeklindedir.

041h=01000001 Gördüğünüz gibi 2^6 ve 2^0 bitleri yani P1.6 ve P1.0 bacakları ile işlem yapılacağını belirten bir sayıdır. bic.b komutunu kullanma amacım ise xor kullanırken bir önceki bitin değerini setleme ihtiyacı hissetmemdendir. İki bacağın bitlerini de sildiğimden 2 ledde işleme sönük olarak başlıyacaktır. Neden kodun sonunda .b koyduğuma gelirsek, yazdığımız bütün P1XXX adresleri byte uzunluğundaki adreslerdir bu sebeple .b ile derleyiciye bunu belirtmeliyiz.

018h=00011000 burada da 2^4 ve 2^3 bitleri setlenmiştir.

  Bacaklardan interrupt alabilmek için ayarlamamız gereken bir kaç adres bulunmaktadır bunlar; P1IE, P1IES, P1IFG'dir. Bunlar hakkında ayrıntılı bilgi PDF sf:339 dan alınabilir.

P1IE
  Bu adresin açılımı Port 1 Interrupt Enable dır. Bu adres içerisinde setlediğimiz bitlere karşılık gelen bacaklardan interrupt girişi olmasını aktif hale getiririz. Bu durumda 018h ile 1.4 ve 1.3 ü aktif hale getirdik.

P1IES
  Teknik olarak tetiklemenin yükselen kenarda mı yoksa düşen kenarda mı yapılacağını yazdığımız adrestir. Bu örnekte hangi kenarda yapılacağının bi önemi yoktur.

P1IFG
  Bu adres interrupt bayraklarının depolandığı adrestir. Bir porttan interrupt geldiğinde bu adreste o bacağa ait bit setlenerek hangi bacaktan interrupt geldiği kayıt edilir. Aynı zamanda interrupt'a girilip girilmeyeceği de bu adrese bakılarak karar verilir. Bu nedenle en başta bic.b komutu ile kullanıcağımız portlara ait bitleri temizliyoruz. Ayrıca bu adres interrupt'a girildikten sonra da temizlenmelidir. Eğer temizlenmez ise işlemci interruptan her çıktığında bit setli olduğunda yeniden interrupt servis rutinine atlama yapacaktır.




bis.w #LPM4+GIE,SR 


  
#LPM4 
  Bu komut ile status registerda işlemcini Low Power Mode 4 e girmesi için gereken bitler setler ve işlemci uyku moduna alır.

GIE
  Status Registerdaki (SR) bir interrupt beklendiğini belirten biti setlemek içindir. Bu bit setlenmez ise işlemci interrupt'a girmez. Bu durumda uyku modundan uyanıp gerekli işlemi yapamaz.

nop: Kısaca no operation. Bu komut o satırda işlem yapılamacağını söyler. Bunu yazmamızın sebebi SR ye yazdığımız bitlerin kontrol edilip ona göre davranılması için yeni bir işlem döngüsüne girilmesinin gerekliliğidir. Sadece debugger için gereklidir ama gereklidir.

Port 1 Interrupt Servis Rutini (P1_ISR)



  Burası bizim interrupt servis rutinmizdir. Yani işlemcimize P1.3/4 den interrupt geldiğinde bu rutin çalıştırılacaktır.

and.b    #010h,&P1IFG
  And komutu kaynaktaki bitler ile hedef bitleri logic and ile işleyerek sonuçta elde ettiği veriyi SR içerisinde işler. Bu durumda bizim için önemli olan P1IFG içerisinin sıfır olması yani Zero bayrağının setlenmesidir. AND işlemi;
1*1 = 1                          1*0 = 0

0*1 = 0                          0*0 = 0

P1.3 portundan interrupt gelmesi durumunda
P1IFG = 0000 1000b biçiminde setlenmiş olacaktır.
010h    = 0001 0000b  dır. bu durumda P1IFG 'nin içerisi tamamiyle 0 olacak ve Zero bayrağı setlenecektir.

P1.4 portundan interrupt gelmesi durumunda
P1IFG = 0001 0000b biçiminde setlenmiş olacaktır.
010h    = 0001 0000b olduğudan P1IFG 'nin içerisi olduğu gibi kalacak bu yüzden and komutu Carry (C) bitini setliyecektir.

  Gördünüz gibi biz ledleri yakma statrejimizi jz red (sıfır ise atla) komutu ile P1.3 den interrupt geldiğinde and.b    #010h,&P1IFG  işleminin sonucunun sıfır gelerek zero bitinin setlemesi sayesinde kırmızı led'i yakacak fonksiyona atlama üzerine kurduk. Eğer siz isterseniz jnc'de kullanabilirsiniz veyahut fonksiyonların yerini değiştirerek jc ile de yazabilirsiniz.

bic.b #10h,&P1IFG ve bic.b #08h,&P1IFG
  Başta bahsettiğim gibi bu bitler işlemin bitişinde temizlenmelidir. İşin aslında and komutu ile yaptığımız işlemde P1.3 ün interrupt flag'ını temizlemiş olsak da ilk olarak yazdığım kodda buna dikkat etmemişim. Gereksiz yazılacak her komut programınızın karışmasına, büyümesine, hantallaşmasına sebep olur çünkü işlemci her kod için bir kaç saat döngüsünü harcar.

reti (Return Interrupt)
  Girdiğimiz interrupt rutininden çıkarak işlemciyi en son işlettiği kodun bulunduğu yere geri yollar. Bu bir donanımsal bir interrupt olduğundan sp içerisine hem sr hemde pc yazılmaktadır. Eğer işlemci interrupttan çıktıktan sonra uyku modundan çıkmasını isterseniz reti den hemen önce bic.b #LPM4,(0)SP komutu ile sp içerisine kaydedilen sr bitlerinden LPM4 bitlerini temizliyebilirsiniz. Eğerki interruptan çıktıktan sonra programın son kaldığı yere değilde sizi istediğiniz bir label'a atmamasını isterseniz mov.b #label,(2)SP ile sp ye kayıtlı pc yi değiştirebilirsiniz. Mesela interrupttan çıktıktan sonra mainloop'a atlamak istiyorsunuz diyelim mov.b #mainloop,(2)SP işinizi görecektir ancak mainloop'a gittikten sonra işleme devam edilmesi için önceden bic.b #LPM4,(0)SP yazmayı unutmayın.

ORG 0FFE4h
DW P1_ISR


 0FFE4h P1 in interrupt vektörüdür. Bu vektörlere ilk eğitimdeki PDF_1 den ulaşabilirsiniz.
DW P1_ISR işlemciye interrupt'a girdiğinde hangi etiketten itibaren kodu işleteceğini söyler.
ORG ile 0FFE4h adresinden sonra data yazılacağını belirtiriz ve DW ile (açılımı sanımı direct write) de istediğimis veriyi o adrese yazarız. Bu durumda P1_ISR flash içerisindeki yazıldığı adres yazılmaktadır.

Beğendiyseniz lütfen soldaki butona tıklayarak +1 leyin

Yorumlar

  1. P1IES: Kesmenin düşen kenarda mı yoksa yükselen kenarda mı oluşacağını seçiyorsun işte.. Bu arada güzel olmuş

    YanıtlaSil
  2. Sağol kardeşim :). Onu biliyordumda nasıl çalıştığını bilmiyordum sonradan öğrendim biraz kurcalayınca belleği. Aslında P1IN belleği 020h belleğinde tutuluyormuş onu incelerken eğer bir porta voltaj verirsem 1 iken 0 a düşüyor benim anlamadığım kısım o düşen kenar yükselen kenar neye göre yapılıyordu onu çözdüm gibi (0 iken 1 oluyormu ona bakmadım). Biraz daha karıştırdıktan sonra eklicem bu yazdıklarımıda konuya :)

    YanıtlaSil

Yorum Gönder

Bu blogdaki popüler yayınlar

KTU Mikroişlemciler Dersi 2013 Vize 4. Soru Çözümü

A4 Tech Oscar X7 the system cannot locate the object specified Hatasının Çözümü

KTU Mikroişlemciler Dersi 2014 Vize Çözümleri