avatar_ete

Bas-Bırak ve Zamana bağlı toggle çalışan tuşlar

Başlatan ete, 16 Aralık 2011, 12:26:13

ete

Bu mesajda işleyeceğimiz konu geçtiğimiz ay (veya daha önce) PicProjede sorulan bir soru üzerine gelişti.
Arkadaşın sorduğu soru şu idi;
ELimizde bir Pic16f628A var. Bunun PortA pinlerine 8 adet Buton bağlıyoruz. Butonlar LOW'a çekilmiş durumda ve butona basılınca pic pinlerine HIGH uyguluyorlar.
PortB de ise 8 adet Led bağlı. PortA dan hangi butona basarsam karşılığına denk gelen PortB deki Led veya Ledlerin yanması isteniyor. Tabiiki aynı anda birden fazla tuşa da basılması söz konusu.
İstenenler bu kadar değil elbette. Devamı şöyle;
- Buton yada butonlara anlık basıp bırakırsam karşılık gelen led de anlık olarak yanıp sönsün.
- Buton yada butonlara 500 ms den fazla basarsam yanan led yanık kalsın. ELimi butondan çekersem led yada ledler sönmesin.
- Aynı buton yada butonlara yeniden anlık olarak basarsam bile yanan ledler sönsün.
Yapılacak iş bu . Şimdi çalışmamıza başlayalım. En başta  PortA pinlerini giriş olarak ayarlıyoruz.
TRISA=255 bu komut iel tamamı giriş yapılmış oldu.
TRISB=0 komutu ile de bütün B portu çıkış yapılmış oldu.

Bize lazım olacak değişkenlerimizi tanımlayalım;
SAYAC VAR WORD   'bizim 500 ms zaman sayacımız olacaktır
ESKI    VAR BYTE     'PortB nin eski halini kayıt ettiğimiz değişken
YENI    VAR BYTE     'PortB nin yeni halini kayıt ettiğimiz değişken
TUS     VAR BYTE     'basılan tuşların kaydı

ESKI=0      '.......bu değişken sıfırlanmadığı için arkadaşın gerçek devresinde ledler yanık olarak açılıyor idi.
Pause 200 'açılış gecikmesi vermeyi unutmayın.

BASLA:
           TUS=PORTA    'bütün tuşları aynı anda okuyoruz. Normalde PORTA LOW da beklediği için bir tuşa basılmadı ise TUS=0 olmalıdır. Basılırsa basılan tuşun binary karşılığı TUS değişkenine yerleşecek dolayısıyla TUS değeri sıfırdan büyük olacaktır.
Şimdi bunu test edelim. Bakalım bir tuşa basılmışmı?
            IF TUS>0   'şayet bir tuşa basılmış ise aşağıdakiler yap.......
               PORTB=(ESKI | TUS)  'Bu işlem ESKI değeri ile TUS değerini OR işlemine tabi tutmaktadır. Kısaca yeni basılan tuşları ESKI ye ilave etmektedir. Böylece yeni basılan farklı tuş var ise karşılığı olan led yanacaktır.
               YENI=TUS 'bu komut ile basılan yeni tusları Yeni isimli değişkene yazıyoruz.
Şimdi artık süre tutmanın zamanı geldi.
               SAYAC=0            'sayacı sıfırla
               WHILE TUS>0         'hala bir tuşa basılı tutuluyor ise
                  TUS=PORTA        'portA dan bütün tuşları oku
                 PAUSE 1
                 SAYAC=SAYAC+1
                 IF SAYAC=500 THEN CIK ''tuşa basma süresi yaklaşık 500msn olmuş ise çık
             WEND
Zaman tutma işleminde süre dolmadan elimi tuştan çekersem program Wend satırından sonrasına gelecektir. Elimi süre doluncaya kadar tuşun üzerinde tutarsam program CIK isimli etikete atlayacaktır. Süre tutam işlemi esnasında sürekli olarak  TUS=PORTA şeklinde tuşların konumunuda mecburen alıyoruz. Zira tusu bırakıp bırakmadığımız bu şekilde belli olacaktır.

        IF (ESKI & YENI)=YENI THEN  'eski durum ile yeni durum aynı ise yani yanık olan led'e karşılık gelen butona basılıyor ise
           ESKI=(ESKI ^ YENI)       'o led'e konum değiştirt. Bu Anlık basma ile konum değiştirme kısmıdır. Eski ile Yeni bitleri XOR işlemine tabi tutuluyorlar. Dolayısıyla hangi tuşa sonradan yeniden basılmış ise ona ait led söndürülmüş olacaktır.
        ENDIF   
      ENDIF
      PORTB=ESKI
      GOTO BASLA
CIK:
      SAYAC=0
      ESKI=ESKI ^ YENI  'aynı şekilde eski ile yeni XOR işlemine tabi tutuldu
      YENI=0                    'yeni sıfırlandı
      PORTB=ESKI           'portB ye eski değeri yazıldı
      WHILE PORTA>0:wend    'Tuslara hala basılı tutuluyor ise bırakıncaya kadar bekle
      GOTO BASLA     've başa dön
END

bütün program bu kadar. Şimdi programı toplu halde tekrar veriyorum.
@ DEVICE pic16F628A                      'işlemci 16F628                                
@ DEVICE pic16F628A, WDT_Off              'Watch Dog timer açık
@ DEVICE pic16F628A, PWRT_ON             'Power on timer açık
@ DEVICE pic16F628A, PROTECT_OFF         'Kod Protek kapalı
@ DEVICE pic16F628A, MCLR_off            'MCLR pini kullanılMIYOR.
@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT  'Dahili osilatör kullanılacak

DEFINE OSC 4
TRISA=255
TRISB=0
CMCON=7
PortB=0
SAYAC VAR WORD 56
ESKI VAR BYTE  58
YENI VAR BYTE  59
TUS  VAR BYTE  60
ESKI=0
pause 200
BASLA:
      TUS=PORTA    'bütün tuşları aynı anda oku
'      YENI=ESKI    'tuşların önceki konumunu yaktığı ledlerin durumunu PortB den al
      IF TUS>0 THEN
        PORTB=(ESKI | TUS) 'basılan yeni tuş varsa bunu eski duruma ekle
        YENI=tus           'yeni durum olarak bütün basılmış tuşların değeri kabul et
        SAYAC=0            'sayacı sıfırla
        WHILE TUS>0         'hala bir tuşa basılı tutuluyor ise
          tus=PORTA        'portA dan bütün tuşları oku
          PAUSE 1
          SAYAC=SAYAC+1
          IF SAYAC=500 THEN CIK ''tuşa basma süresi yaklaşık 500msn olmuş ise çık
        WEND
        IF (ESKI & YENI)=YENI THEN  'eski durum ile yeni durum aynı ise yanık olan buton karşılığına basılıyor ise
           ESKI=(ESKI ^ YENI)       'o led'e konum değiştirt. Anlık basma ile konum değiştirme kısmıdır.
        ENDIF   
      ENDIF
      PORTB=ESKI           
      GOTO BASLA
     
CIK:  sayac=0
      ESKI=ESKI ^ YENI
      YENI=0
      PORTB=ESKI
'      WHILE PORTA<255:wend 'pull_up lı sistemde bu açık
      WHILE PORTA>0:wend 'pull down lı sistemde bu açık
      GOTO BASLA


Konuyu toparlarsak;
- Önce bir tuşa basılmışmı bakyoruz.   (IF TUS>0 Then )
- Basılmış ise basılan tuşa karşılık gelen ledi yakıyoruz. (  PORTB=ESKI | TUS  )
- Sonra zaman tutuyoruz. Burada iki alternatifmiz var ya TUŞ, 500 ms basılı tutulacak yada daha kısa sürede bırakılacak
- 500 ms basılı tutuluyor ise CIK etiketine gidip orada, Eski ile Yeni yi XOR yapıyrouz. Böylece yanık olan ve sönmesi gereken led var ise söndürüyoruz. Sönmüş halini PortB ye yeniden veriyoruz ve tuş bırakılana kadar bekleyip başa dönüyoruz.
- Şayet tuşa 500 ms den daha az basılmış ise; Eski basılmış olan ile yeni basılmış aynımı bakıyoruz. Aynı ise Yine ESKI ile YENI yi XOR işlemine tabi tutup elde edilen değeri PortB ye yazıyoruz. Bu işlem sonucunda hızlı basıp bırakma sonucu önceden yanık olan ledi söndürmüş oluyoruz.
Hepsi bu kadar. Umarım anlaşılmıştır.

Şimdi bir ödev versem acaba yaparmısınız.
Bu sistem Tuşlar LOW'a çekili ve basınca HIGH verecek şekilde çalışıyor. Tersini yani Tuşlar Pullup lı ve basınca LOW veriyor şeklinde bu sistemi çalıştırmak istersek programı nasıl düzenlemeliyiz.?

Ete

umitco

IF TUS>0              yerine     IF TUS<255
WHILE TUS>0      yerine     WHILE TUS<255
WHILE PORTA>0  yerine     WHILE PORTA<255

eksik vamı ?

ete

Aslında eksik varmı diye sormak yerine iki dakikada devreyi kurup denemek daha uygun olurdu. Eksik var elbette.
TUS=PORTA komutunda portA pullup lı ise TUS=255 olur ve buda bütün ledlerinbaşlangıçta yanmasına sebep olur!!!!.

Doğru yoldasın.

Ete


kotan04

Merhaba buton ile ilgili muhteşem bir eğitsel olmuş hocam elleriniize sağlık butonlar ile ilgili uygulamalar çok ilgimi çekiyor bu konuya çalışacağım teşekürler ete hocam..

zoptrik

Port.a nın bütün bacaklarını pull up yaptıktan sonra;
WHILE PORTA>0  yerine     WHILE PORTA<255
TUS=porta yerine TUS=255-porta
doğru mudur?
DEHA; İMKANSIZDA MÜMKÜNÜ GÖREBİLMEK DEMEKTİR.GEMİLERİN KARADA DA YÜZEBİLECEĞİNİ SEZMEK, MEHMETLERDEN BIRINI "FATİH" YAPAR...!

ete

Zoptrik doğru cevabı verdi sayılır.
Yalnızca 3 adet değişiklik pullup lı buton sistemi için yeterli oluyor. Burada önemli bir komutun işlevini belirtmek gerekiyor. Bütün işi düzeltende o zaten.
TUS=PORTA  yerine pullup lı sistemde TUS=~PORTA şeklinde bir komut kullanarak portA değerini değillerseniz. İş çözülmüş oluyor zaten. Zira normalde 255 olan porta değeri bu komut sayısinde sıfır değerine çevrilmiş oluyor. Bir yerde TUS=255-PORTA komutu ile aynı görevi yerine getiriyor denilebilir.

Ete

BU durumda programda 2 adet TUS=PORTA komutu var. Bunları TUS=~PORTA şeklinde değiştirir ve CIK satırından sonra yer alan;
WHILE PORTA>0:wend   komut satırı yerine  WHILE PORTA<255:wend  satırını yazarsanız iş çözülmüş oluyor.

Ete

Powered by EzPortal