MSP430 Launchpad – İki Display Sürme

Bir önceki yazımda tek display üzerinde rakamları göstermekten bahsetmiştim. Bu yazımda ise aynı anda iki display üzerinde sayı göstermeye değineceğim. Bunu yapmanın en basit yolu iki display için de 7’şer pin kullanarak 14 pinle olayı halletmektir. Ama genelde yapılan, displaylerin segmentlerine 7 tane ortak pin götürmek, birer pinle de displaylere sırayla, hızlı bir şekilde gerilim uygulayarak, göz yanılması ile sayıları göstermektir. Buna tarama yöntemi deniyor.

Bunun için MSP430’un iki portunu da kullandım. Pinlerle, displayin segmentleri arasındaki bağlantı ise şu şekilde:

P1.0   => Kullanılmıyor.
P1.1    => A (tüm displaylere gidiyor.)
P1.2    => B (tüm displaylere gidiyor.)
P1.3    => C (tüm displaylere gidiyor.)
P1.4    => D (tüm displaylere gidiyor.)
P1.5    => E (tüm displaylere gidiyor.)
P1.6    => F (tüm displaylere gidiyor.)
P1.7    => G (tüm displaylere gidiyor.)
P2.6    => Soldaki display ortak anot
P2.7    => Sağdaki display ortak anot

Kullandığım denetleyici olan MSP430G2231’in datasheetine bakarak 2. portun pinlerinin, denetleyicinin kaçıncı bacağı olduğunu belirledim. 1. portunkiler ise zaten launchpad üzerinde yazılı. 2. portu giriş / çıkış olarak kullanmak için P2SEL registerına 0x00 verisini yazmam gerekiyor. Bunu yazmdığımda port 2, giriş çıkış olarak kullanılmıyordu.

Kod biraz karışık ve uzun oldu. Assembly’ye pek alışkın olmadığım için tam olarak istediğimi de yapamadım. Oğuzhan hocamın deyimiyle “tam öğrenci işi”. Ama çalışıyor. 🙂 Önce kodu yazayım, arkadan da nasıl yaptığımı açıklamaya çalışayım.

#include "msp430.h"                     ; #define controlled include file

        NAME    main                    ; module name

        PUBLIC  main                    ; make the main label vissible
                                        ; outside this module
        ORG     0FFFEh
        DC16    init                    ; set reset vector to 'init' label

        RSEG    CSTACK                  ; pre-declaration of segment
        RSEG    CODE                    ; place program in 'CODE' segment

init:   MOV     #SFE(CSTACK), SP        ; set up stack

main:   NOP                             ; main program
        MOV.W   #WDTPW+WDTHOLD,&WDTCTL  ; Stop watchdog timer

        MOV.B   #0x00, &P2SEL           ; P2 portu I/O olarak seçildi
        MOV.B   #0xFF, &P1DIR           ; P1 portu çıkış olarak seçildi.
        MOV.B   #0xFF, &P2DIR           ; P2 çıkış 

        MOV.B   #0x00, R5               ; birler basamağı R5 te
        MOV.B   #0x00, R6               ; onlar basamağı R6 da

say:    MOV.B   #0x03, R7               ; kaçar kaçar sayacağı R7 de
art:    INC.B   R5                      ; birler basamağını arttır
        CMP.B   #0x0A, R5               ; 9 oldu mu?
        JZ      onlar_art               ; olduysa onlar_art etiketine dallan
kacar:  DEC.B   R7                      ; kaçar kaçar sayacak, bir azalt
        JNZ     art                     ; yeteri kadar saymadıysa tekrar arttır

        JMP     sayi_bas                ; yeteri kadar saydıysa sayıları basalım

sayi_bas:
        MOV.W   #0x0400,  R8            ; sayma arasındaki boşluk R8de tutuluyor.
bas:
        MOV.B   #0x80, &P2OUT           ; P2 nin 7. biti 1 yapıldı. sağdaki display için.
        CMP.B   #0x00, R5               ; ilgili sayıya ait fonksiyona gidecek.
        JZ      sifir
        CMP.B   #0x01, R5
        JZ      bir
        CMP.B   #0x02, R5
        JZ      iki
        CMP.B   #0x03, R5
        JZ      uc
        CMP.B   #0x04, R5
        JZ      dort
        CMP.B   #0x05, R5
        JZ      bes
        CMP.B   #0x06, R5
        JZ      alti
        CMP.B   #0x07, R5
        JZ      yedi
        CMP.B   #0x08, R5
        JZ      sekiz
        CMP.B   #0x09, R5
        JZ      dokuz

sol:    MOV.B   #0x40, &P2OUT           ; P2 nin 6. biti 1 yapıldı. soldaki display için.
        CMP.B   #0x00, R6
        JZ      sifir2
        CMP.B   #0x01, R6
        JZ      bir2
        CMP.B   #0x02, R6
        JZ      iki2
        CMP.B   #0x03, R6
        JZ      uc2
        CMP.B   #0x04, R6
        JZ      dort2
        CMP.B   #0x05, R6
        JZ      bes2
        CMP.B   #0x06, R6
        JZ      alti2
        CMP.B   #0x07, R6
        JZ      yedi2
        CMP.B   #0x08, R6
        JZ      sekiz2
        CMP.B   #0x09, R6
        JZ      dokuz2

tut:    DEC.W   R8                      ; r8 azalıyor
        JNZ     bas                     ; yeteri kadar ekranda tutuldu mu

        CMP.B   #0x09, R5               ; birler basamağı 9 mu
        JNZ     say                     ; değilse saymaya devam et
        CMP.B   #0x09, R6               ; onlar basamağı 9 mu
        JNZ     say                     ; değilse saymaya devam et

        MOV.W   #0x00, R5               ; sayı 99 olursa buraya düşer.
        MOV.W   #0x00, R6               ; birler ve onlar basamağına 00 yaz
        JMP     say                     ; ekranda yeteri kadar kaldıysa sonraki sayı için alt etiketine dallanıyor.

onlar_art:
        INC.B   R6                      ; Onlar basamağını bir arttır
        MOV.W   #0x00, R5               ; birler basamağına 0 yaz
        JMP     kacar                   ; kaçar kaçar sayacak, bir azaltmaya geri dön

bekle:  MOV.B   #0xB0, R9               ; sağ ve sol displaylerin açık kalma süreleri burada geçiyor.
bekle2: DEC     R9
        JNZ     bekle2
        RET

; Sayıların alt programları sağ display için

sifir:
        MOV.B   #0x81, &P1OUT
        CALL #bekle
        JMP     sol
bir:
        CALL #bekle
        MOV.B   #0xF3, &P1OUT
        JMP     sol
iki:
        MOV.B   #0x49, &P1OUT
        CALL #bekle
        JMP     sol
uc:
        MOV.B   #0x61, &P1OUT
        CALL #bekle
        JMP     sol
dort:
        MOV.B   #0x33, &P1OUT
        CALL #bekle
        JMP     sol
bes:
        MOV.B   #0x25, &P1OUT
        CALL #bekle
        JMP     sol
alti:
        MOV.B   #0x05, &P1OUT
        CALL #bekle
        JMP     sol
yedi:
        MOV.B   #0xF1, &P1OUT
        CALL #bekle
        JMP     sol
sekiz:
        MOV.B   #0x01, &P1OUT
        CALL #bekle
        JMP     sol
dokuz:
        MOV.B   #0x21, &P1OUT
        CALL #bekle
        JMP     sol

; Sayıların alt programları sol display için

sifir2:
        MOV.B   #0x81, &P1OUT
        CALL #bekle
        JMP     tut
bir2:
        MOV.B   #0xF3, &P1OUT
        CALL #bekle
        JMP     tut
iki2:
        MOV.B   #0x49, &P1OUT
        CALL #bekle
        JMP     tut
uc2:
        MOV.B   #0x61, &P1OUT
        CALL #bekle
        JMP     tut
dort2:
        MOV.B   #0x33, &P1OUT
        CALL #bekle
        JMP     tut
bes2:
        MOV.B   #0x25, &P1OUT
        CALL #bekle
        JMP     tut
alti2:
        MOV.B   #0x05, &P1OUT
        CALL #bekle
        JMP     tut
yedi2:
        MOV.B   #0xF1, &P1OUT
        CALL #bekle
        JMP     tut
sekiz2:
        MOV.B   #0x01, &P1OUT
        CALL #bekle
        JMP     tut
dokuz2:
        MOV.B   #0x21, &P1OUT
        CALL #bekle
        JMP     tut

        END                             ; (endless loop)

Evet, uzun demiştim değil mi? 🙂 Adım adım başlayalım açıklamaya.

Önce port koşullamalarını yapıyorum. P2’yi giriş / çıkış olarak kullanacağımı belirttim. Ardından P1 ve P2’yi çıkış olarak ayarladım. R5 registerında, o an ekrana bastıracağım sayının birler basamağını, R6’da ise onlar basamağını tutuyorum. R7 registerına 0x03 değerini atadım, çünkü üçer üçer sayacak. Bu registerı her sayışta azaltarak ve sıfrla karşılaştırarak, displaydeki sayıların üçer üçer artmasını sağlayacağım. Her sayışta R5 registerının 0x0A’ya, yani decimal olarak 10 sayısına eşit olup olmadığına bakıyorum. Eğer 10 olduysa, sayımın onlar basamağını arttırmalı, birler basamağına da 0 yazmalıyım. İşte onlar_art etiketine dallandığımda bu olay gerçekleşiyor.

Sayım bir arttığında R7’yi bir azaltıyorum, bu şekilde R7 sıfır olana kadar saydırıyorum. R7 0 olduğunda benim esas sayım üç artmış oldu. Bu durumda bulduğum bu sayıyı artık displayde göstereceğim. Bunun için sayi_bas etiketine dallanıyorum.

sayi_bas etiketinde, ilk önce R8’e, 0x400 değerini atıyorum. Bu değeri sürekli azaltarak sayının ekranda kalma süresini ayarlamış olacağım. Yani o an displayde gösterdiğim sayı 21 ise, 21 sayısının ne kadar süre gözükeceğini bu registerın değeri ile belirliyorum.

Sonra bas etiketli bölüme geldim. Burası, aslında yazımın başında dediğim, yapmak istediğimi yapamadığım yerlerden biri. Sağ ve sol display için kullanacaktım bunu, ama geri dönüşü ayarlayamadığım için sağ ve sol display için ayrı yapmak zorunda kaldım.

Neyse, bas etiketindeyim. Sağdaki displayde sayı göstereceğim. O zaman sağdaki ortak anot ucuna 1 uygulamam gerekir. Aynı zamanda sol displayin ortak anot ucu da 0 olmalı. Bunun için P2.7’yi set ediyorum. Sonra sırayla R5 registerını, yani sayımın birler basamağını kontrol ediyorum. CMP komutu iki değeri karşılaştırıyor, eğer aynı iseler zero bayrağını set ediyor. Bu durumda karşılaştırmamın sonucunda zero bayrağı set olmuşsa, demek ki birler basamağında o rakamı göstereceğim. Bunun için de rakamın, yazıyla yazılmış hali olan etikete dallanıyorum.

Örneğin sayımın birler basamağında 7 var. O zaman R5’te de 7 değeri vardır. CMP ile kontrol edip R5’teki değerin 7 olduğunu buluyorum. Sonra “yedi” isimli etikete dallanıyorum. Burada displaye 7 basılması için gereken bitleri set edip P1’e yazıyorum. Ardından, 7 rakamının o displayde çok kısa bir süre durması için bekle altprogramına dallanıyorum. Burada standart bir bekleme olayı. Ancak sürenin kısa olması gerekiyor. Bu beklemeyi de R9 registerına atadığım sayıyı azaltarak yapıyorum.

Bir süre bekledikten sonra, bekle altprogramından dönüyorum ve  sol displaye onlar basamağındaki rakamı yazmak için “sol” isimli etikete dallanıyorum. Bu sefer P2.6’yı set ediyorum. Bu durumda soldaki display aktif, diğeri pasif durumda. Burada, yine birler basamağındaki işlem gerçekleşiyor. Yalnız bu sefer R5 yerine, onlar basamağını tutan R6 registerını kontrol ediyorum ve örneğin R6’da 3 varsa, “uc2” isimli etikete dallanıyorum. Burada da ilgili rakam için P1 ayarlanıyor, bir süre “bekle” altprogramında bekleniyor ve “tut” etiketine dallanılıyor.

Buraya kadar sayımın birler basamağını ve onlar basamağını birer kez çok kısa bir süre displaylerde göstermiş oldum. Ancak bu o kadar hızlı oldu ki, gözle görmek imkansız. Bu yüzden bir süre daha sırayla ve hızlı bir şekilde onlar ve birler basamağını displaye basmam lazım. Bu süreyi de “tut” etiketinde, R8 i azaltarak kontrol ediyorum. Azalttıktan sonra da tekrar “bas” etiketine, yani birler basamağını belirlediğim etikete dönüyorum. Bu sayede aynı sayıyı displaylerde birden fazla göstererek, gözle farkedilecek uzunlukta sayının displaylerde gözükmesini sağlıyorum.

Burada R8 ile R9 arasındaki fark şu: R9’da, displaylerdeki rakamların ayrı ayrı gösterilme süresi belirleniyor. Yani “bekle” altprogramıyla bu işi yapıyorum. R8’de ise sayının tamamının displaylerde kaç kez peşpeşe gösterileceği belirleniyor.

Eğer R8, 0 olmuşsa, sayı, displaylerde yeterli uzunlukta tutulmuş demektir. Burada birkaç kontrol yapıyorum. 3’er 3’er saydığımızda, en büyük iki basamaklı sayı 99 olur. 99’a geldikten sonra kodun 00’a dönmesini istiyorum. Bu yüzden R5 ve R6’yı 9 ile karşılaştırıyorum. Eğer ikisi de 9’a eşitse, ikisine de 0 yazıyorum. Yok değilse, saymaya devam etmek için en üste, “say” etiketine gidiyorum. Böylece sayım tekrar üç artacak ve aynı işlemler tekrarlanacak. Sonuç olarak displayler üzerinde üçer üçer artan sayılar göreceğiz.

Kod da, anlatım da uzun oldu. Kodu yazmaya geceyarısı 4’te başladığımı ve assembly’ye pek fazla aşina olmadığımı göz önüne alırsak pek de fena sayılmaz. Umarım sıkıcı olmamıştır, umarım anlaşılabilir ve faydalı olmuştur. Son olarak da uygulamanın çalışırkenki videosunu paylaşayım, ve yazımı sonlandırayım.

Share
  1. berk,transistör kullanman daha yararlı olurdu 2. display için,en azından şimdlik 2 tane display var fakat daha sonra çok daha karmaşık şeyler yapmak istersen şimdiden transistörlere alışmak lazım 😀 2 kat verim alırsın

    • 2 tane display olduğu için kullanmadım zaten. Yüksek akım çekebilecek elemanları sürerken kullanmak tabii ki faydalı olacaktır çipin sağlığı açısından. 🙂

  2. merhaba bu üzerinde gelen denetleyici ile yapılan çalışmammı yoksa ek bir denetleyicimi aldınız?
    Çünkü üstündeglen iki denetleyicidede 14 bacak mevcut

    • Evet, üzerinde gelen MSP430G2231 ile yapılmış bir devre bu. Denetleyicide 14 bacak var, bunlardan 10 tanesini I/O ucu olarak kullanabiliyoruz. 7 adet displaylere giden ortak data ucu, 2 adet de displayleri aktifleştirmek için uç, toplamda 9 I/O pini kullanıldı. Yazının en başında hangi pini nereye bağladığım da yazıyor. Oradan bakabilirsiniz. Kolay gelsin…

  3. MSP430 ve Karakter LCD ile Refleks Ölçer | Berk Baykal - pingback on 30 Mayıs 2011 at 02:40
  4. MSP430 ve Karakter LCD ile Refleks Ölçer « MCU Turkey - pingback on 31 Mayıs 2011 at 21:06
  5. cagdas yılmaz

    mrb güzel çalışma olmuş ama bana isis cizimi lazım birde varmı acaba bu devreyi borda kurucam bnde kodlarda pek iyi deilim

  6. cagdas yılmaz

    birşey daha sorucam ben yaptım 3 er 3 er sayıyor onu birer birer saydırmak istiyorum hangi kodu deiştirmemiz lazım

  7. MSP430 ve Karakter LCD ile Refleks Ölçer « MCU Turkey - pingback on 10 Aralık 2013 at 15:02

Yorum Yap


Not - Bunları KullanabilirsinizHTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Geri İzleme: