Haberler:

Forum kuralları güncellendi LÜTFEN  okuyunuz:  https://bit.ly/2IjR3ME

Ana Menü

buton hakkında

Başlatan yolcu27, 25 Mart 2016, 19:39:57

ete

Çakarın sürekli kesme ile çaktırılması için örnek kod aşağıdadır. Sen ana döngü dediğimiz BASLA - GOTO basla aralığında kendi buton kontrolünü yapacaksın artık.

SYMBOL CAKAR=PORTX.x   '(X yerine POrt ismi mesela C,  x yerinede cakar ledi hangi pine bağlı ise onun bit numarası mesela 0)
SAYAC   VAR   BYTE
ON INTERRUPT GoTo KESME   'kesme oluşursa KESME adlı etikete git.
OPTION_REG=%10000101   	 'Pull up dirençleri İPTAL- Bölme oranı 1/64.
INTCON=%10100000  		 'Kesmeler aktif ve TMR0 kesmesi aktif
TMR0=21   'her 15 ms de bir kesme olacak
PAUSE 200

BASLA:
...
...
GOTO BASLA

DISABLE
KESME:
      SAYAC=SAYAC+1 
      IF SAYAC=20  Then     '15*20=300 ms de bir çakar konum değiştirecek
         TOGGLE CAKAR
         SAYAC=0
      ENDIF
      TMR0=21
      INTCON.2=0        'TMR0 Kesme bayrağı sıfırlanıyor
      RESUME
      ENABLE
 
Ledlerin konum değiştirme süresi 300 ms olarak ayarlandı. Kesme her 15 ms de bir oluşuyor. Ona göre gerekirse artırır yada azaltırsın.

Ete

Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

yolcu27

#16
Hocam çok teşekkür ederim akşam hemen güncelleme yapacağım. Bir sorum daha olacak . ben mesela etiketimde su şekilde bir komut kullanabilir miyim bu çakari etkiler mi .

Cakar ledim portb.7 ye bagli
Portb=%00000001


Burada port b0 A bağlı led yanacak
Bunun gibi 3 tane etiketim olacak portb ye bağlı ledlerinizin yanması için. Ama burada portb7 ye bağlı Cakar ledin pinine 0 yazıyorum bu çakari sondurmez mi.

Ben hem port b deki diğer portlara bağlı ledlerimi kontrol edeceğim ve portb7 deki cakarim da devam edecek. Kullandığım kod ile bu mantıklı gelmiyor bana yanlışım varsa düzeltin


mesaj birleştirme:: 30 Mart 2016, 14:32:04

Ben 500ms olarak ayarlamak için sayacı 33 ayarliyacagim 495ms yapıyor isimi görür.
Bu tmr0=21 yazınca 15ms de kesme oluşması neye gore hesaplanıyor sanırım kristal ile ilgili de olabilir bu.. Ben dahili osilator kullanacağım bunun için bir değişiklik yapmam gerekir mi bir ekleme filan yapmam

yolcu27

@ DEVICE pic16F628A                      'işlemci 16F628                                
@ DEVICE pic16F628A, WDT_ON              '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
cmcon=7
trisa=%00000111   ' a0. a1 a2 pinleri giriş butonlara bağlanacak
trisb=%00000000   '  b portu rölelere gidecek full çıkış
  
symbol cakar=portb.6
sayac var byte
on interrupt goto kesme
option_reg=%10000101
intcon=%10100000
tmr0=21
pause 200

'----------------------------------------------
basla:
portb=%10100000
if porta.1=1 then a
if porta.0=1 then bcd
if porta.2=1 then bce
goto basla

'-----------------------------------------------
a: 
pause 1000
    a1:
    portb=%00100001
    if porta.0=1 then bcd
    if porta.2=1 then bce
    goto a1
    
'-------------------------------------------------

bcd: 
pause 1000
    bcd1:
    portb=%00101110
    if porta.1=1 then a
    if porta.2=1 then bce
    goto bcd1
    
'--------------------------------------------------

bce: 
pause 1000
    bce1:
    portb=%00110110
    if porta.1=1 then a
    if porta.0=1 then bcd
    goto bce1
    
'----------------------------------------------------

disable
kesme:
sayac=sayac+1
if sayac=33 then
toggle cakar
sayac=0
endif 
tmr0=21
intcon.2=0
resume
enable

kodlarım bunlar portb.6 ya bağlı ledim çok sönük şelilde yanıp sönmekte ve butona bastığımda 1 saniye sönmektedir.

nerede hata acaba neyi yanlış anladım?

dursuncemal

burada zanedersem  pic16F628A, WDT_ON  ve dongulerinin icinde WDT sifirlamiyorsun senin programin surekli resete gidiyor kanimca. pic16F628A, WDT_OFF yapip denersen belki olur.
not:basic bilmedigim icin yanilabilirim.
:=

ete

#19
Bu programda hiç doğru yer yok. Bir port pinine "1" verisen o pinden HIGH çıkar. Aynı pine "0" verirsen LOW çıkar. Aynı pine bağlı ledi yakmak için pine "1" vermen gerekiyor. Veriyorsunda ama hemen arkasından "0" da veriyorsun led yanmakla yanmamak arasında gidip geliyor. Üstelik yanmasını görecek kadar süre tanımadığın için led üzerinde sadece biraz sönük yanma gibi bir efekt görüyorsun.

Bir porta değer verirken o port pinlerinden bazılarına önceden verdiğin değerlerin etkilenmemesini sağlaman gerekiyor.
Şimdi sesli düşünelim. PORTB.6 pinine kesme içinde değer veriyorsun. Diyelimki HIGH verdi Toggle komutu. Kesmeden çıkar çıkmaz program portb=%10100000 şeklindeki komutla karşılaşıyor ve PORTB.6 ya LOW veriyor. Led de tabii olarak sönüyor.
Peki ne yapmak lazım. Önce hangi pinde değişiklik yapacak isem sadece onu bırakıp diğer pinlerin kaydını almam gerek. Diyelimki portb=%10100000 komutu ile aslında PORTB.7 ye HIGH vermek istiyoruz. O halde önce portun 7 nolu pin haric kaydını almamız gerekiyor.
KAYIT=PORTB & %01111111  Burada PORTB pinlerini %01111111 ifadesi ile AND işlemine sokuyoruz. Böylece Pinlerden "1" olanlar 1 kalıyor, "0" olanlar ise sıfır olarak Kayıt isimli değişkene yerleşiyor.  Şimdi Kayıt ile %10000000 değerini OR işlemine sokarsak Kayıt değerinin 7 ci bitini 1 yapmış oluruz. O halde komutun tamamı, PORTB=(PORTB & %01111111) | (%10000000) aynı işi PORTB=PORTB & (%01111111)+128 şeklinde de yapabiliriz. Zira 128 binary olarak %10000000 dir.
O halde Hangi bite değer verecek isen o hariç diğerlerininkaydını alacak ve sonra o bite karşılık gelen decimal sayıyı aldığın kayda ekleyeceksin.

İkinci hata, Kesme kullanılan programlarda PAUSE kullanmaman gerekiyor. Zİra Basic kesme oluştuğunda işlediği komutu bitirmeden kesme etiketine gitmez. Pause 1000 dediğin zaman 1000 ms bekleyip sonra kesme etiketine gidecek ve böylece senin programında aksayacaktır.
Orada 1000 ms lik bir gecikme yaratmak istersen onu bir döngü ile halletmen ve döngüde kısa zaman dilimleri kullanman gerekiyor.
Örnek vereyim, 1000 ms için
FOR I=0 to 49999
  Pauseus 5
  pauseus 5
  pauseus 5
  pauseus 5
Next
şeklinde bir döngü kurarsan bu yaklaşık 1000 ms lik bir gecikme yaratır. Ama dikkat edersen en büyük gecikme 5us olduğu için program en fazla 5us içinde kesme etiketine gider. Böylece programın aksamaz. Aslında bu döngüde komut gecikmeside önemliölçüde etkili olur bu nedenle son satırda yer alan Pauseus 5 ifadesini çıkartabilirsin. Çıkartmış olduğun satır komut gecikmelerini karşılamış olacaktır.

O halde bir I (Word) değişkeni tanımlayacaksın. Sonra bir alt program oluşturacaksın. Adına BEKLE dersin. Oraya yukarıdaki döngüyü yazıp altına bir RETURN koyacaksın.
SOnra ana program içinde Pause 1000 gördüğün yere GOSUB BEKLE yazacaksın işin tamam olacak.

Bu iki önemli hatayı düzelt programda düzgün çalışmaya başlayacaktır
Şimdi fazla upraşmaman için yazdığın programa baktım;
- BASLA etiketininaltında PORTB.7 pinini aktif ediyorsun. Bunu yapmak için aşağıdaki kodu kullan.
  PORTB=(PORTB & %01111111)+128

- A1 etiketi altında ise PORTB.0 pini aktif ediliyor. AMa PORTB.7 de söndürülmüş oluyor. O halde aşağıdaki kodu kullanabiliriz.
  PORTB=(PORTB & &01111110)+1

- bcd1: etiketi altında ise B.1-B.2-B.3 pinleri 1 oluyor diğerleri sönmüş oluyor. O halde aşağıdaki kodu kullanabiliriz.
Portb=(PORTB & %01100000)+%00001110     
Böylece istediğimiz pinlerin değerlerini bozmadan (özellikle PORTB.6 ve PORTB.5 pinlerinin değerleri hep sabit kalıyor) istediğimiz pinleri yakıp söndürmüş olacağız.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

yolcu27

#20


Hocam 3 defa okudum ince ince  bu şekilde bir sıkıntı oluşacağını fark etmiştim. Dediğiniz gibi yapacağım .

Portb5 ve portb6 lar sabit olması gerekiyor değer olarak evet çünkü biri sürekli yanacak biriside Cakar olacak kesme ile. Diğer port değerlerini hangisinin yanması gerekse ona göre duzeltirim.
uzun uzun anlatmışsınız hocam sanırım sizde öğretmensiniz bukadar açıklayıcı akıcı yazmak kolay değildir. İlgili düzeltmeleri yapıp sizi bilgilendiririm buradan. Yeniden teşekkürler

ete

Öğretmen değilim ama amatör öğreticiyim. Bilen insan bildiğini anlatırken çok defa karşısındaki de bazı şeyleri biliyor gibi düşünür. Bilerek yapılan bir şey değil bu içgüdüsel olarak yapılır ve dolayısıyla ayrıntıları atlar. Ben ise karşımdaki hiç bir şey bilmiyormuş gibi anlatırım. Uzun zaman içine bu alışkanlığı kazandım.

Ete

Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

yolcu27

#22
hocam kodları şu şekilde güncelledim  portb.5 sabit olacak şekilde yanıyor portb.6 çakar olarak yanıyor.

butonlara bastıkça güzel bir şekilde 1sn yeye yakın bir zamanlamada ilişkili etikete yöneliyor.



a etiketinden  bcd etiketine geçerken o bekleme süresinde portb.0 a bağlı ledim yanmış şekilde bekliyor . süre geçince portb1 b2 b3 ledlerim yandığı anda sönüyordu.

benim istediğim o 1 saniye bekleme süresinde ledler yanmasın ve çakar devam etsin. bunuda bekle etiketine ilk 5 portu tek tek sıfıra çekerek yaptım.

birde kaç saniye kayıtta kalıyor acaba bu portb bilgileri enerji kesip verdiğimde  2 3 sn sonra yeniden. aynı kalan ledler devam ediyor

bir defa tüm ledlerin yandığını gördüm bu neden olmuş olabilir acaba?

birde ben burada 4mhz kristal kullanmak istersem kesmede ve bekle etiketinde değiştirmem yerler var mıdır?


kodlarda yanlış gördüğünüz bir yer var mı acaba ileride sıkıntı yaratabilecek?

@ DEVICE pic16F628A                      'işlemci 16F628                                
@ DEVICE pic16F628A, WDT_ON              '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
cmcon=7
trisa=%00000111   ' a0. a1 a2 pinleri giriş butonlara bağlanacak
trisb=%00000000   '  b portu rölelere gidecek full çıkış
i var word  
symbol cakar=portb.6
sayac var byte
on interrupt goto kesme
option_reg=%10000101
intcon=%10100000
tmr0=21
pause 200

'----------------------------------------------
basla:
 PORTB=(PORTB & %01011111)+%10100000
if porta.1=1 then a
if porta.0=1 then bcd
if porta.2=1 then bce
goto basla

'-----------------------------------------------
a: 
gosub bekle
    a1:
      PORTB=(PORTB & %01100000)+%00000001
    if porta.0=1 then bcd
    if porta.2=1 then bce
    goto a1
    
'-------------------------------------------------

bcd: 
gosub bekle
    bcd1:
   Portb=(PORTB & %01100000)+%00001110     
    if porta.1=1 then a
    if porta.2=1 then bce
    goto bcd1
    
'--------------------------------------------------

bce: 
gosub bekle
    bce1:
    Portb=(PORTB & %01100000)+%00010110     
    if porta.1=1 then a
    if porta.0=1 then bcd
    goto bce1
    
'----------------------------------------------------


bekle:
portb.0=0
portb.1=0
portb.2=0
portb.3=0
portb.4=0
 
 FOR i=0 to 4999
  Pauseus 5
  pauseus 5
  pauseus 5
  pauseus 5
  
Next
return
disable
kesme:
sayac=sayac+1
if sayac=33 then
toggle cakar
sayac=0
endif 
tmr0=21
intcon.2=0
resume
enable


yolcu27

Devreyi aç kapa yaptığında portb0 1 2 3 4 e bağlı olan ledlerim belli bir kurala bağlı olmadan yanmış olarak açılıyor. Kapatıp 10sn filan bekleyince sorun yok .

Birde ilk açılışta portb7 ve portb5 açık 200ms sonra portb6 çalmaya başlamakta

Bunlar benim için çok büyük sorunlar değil ama aşmak isterim yinede

ete

#24
Basla satırından evvel yer alan PAUSE 200 gecikmesinden öncesine;
PORTB=0:PORTA=0 
şeklinde portları sıfırlayan bir satır ilave etmen gerekir. Çünki ilk açılışta portlar rastgele değer alır.
Bunu önlemek için portları sıfırlamak gerekir.

Yukarıdaki mesajında anlamadığım noktalar var.
"benim istediğim o 1 saniye bekleme süresinde ledler yanmasın " bu ne demek. Hangi ledler yanmasın hangisi sönmesin anlamadım.
Çakar ledi sürekli aktif zaten. PORTB.5 deki ledi de başlar başlamaz yakıyorsun. Bu durumda söylediğin anlamsız gibi oluyor bana göre.
A etiketinden bcd etiketine giderken, gecikme süresince  ilk 5 ledin her hangi birinin yanmasını istemiyor isen,
BCD etiketinin altına şu komutları ilave etmen gerekecek. Bundan önce TEMP isimli bir BYTE değişkeni daha tanımlaman uygun olacaktır.
BCD:
TEMP=PORTB                         'portB nin kopyasını aldık
PORTB=PORTB & %11100000  'ilk 5 biti sıfırladık
GOSUB BEKLE                        'beklemeye gittik
PORTB=TEMP                         'PORTB ye kopyalanan durumu yeniden geri verdik
BCD1:
..
..


Tüm ledlerin bir kereliğine neden yandığını bilemiyorum.
Sistem dahili OSC kullanarak zaten 4Mhz de çalışmaktadır. Dahili OSC yerine harici kristal takayım diyorsan yalnızca aşağıdaki değişiklik gerekir.
@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT  yerine,
@ DEVICE pic16F628A, XT_OSC
Ayrıca her iki durumda da sigorta ayarlarından sonra,
DEFINE OSC 4
komut satırını ilave etmen doğru olur. İşlemcinin gecikme rutinlerini doğru ayarlayabilmesi için sistemin hangi frekansta çalıştığını bilmesi gerekir. Bu komut da o işi yapar.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

yolcu27

#25
Evet hocam o 1 sn bekleme suresi etiketler arasındaki geçişte ki sure. Ben bunu dediğim gibi yaptım o ilk 5 led o bekleme süresi içinde sönmesi için. Bekle etiketine o 5 ledin sönmesi için portlarini sıfıra çektim.
Açıkçası tek sorunum  arada enerji kesip verince  ledlerin rastgele yanmasiydi. Bunuda pause dan önce porta=0 portb=0 ile hallederiz artık.

Define osc 4 te kristal değerinin hangi hızla çalışacağını belirliyor sanırım
Şimdi aklıma şöyle bir şey daha geldi bu kesme ile doğru hesaplamalar sonucunda dijital bir saat yapılabilir sanırım lcd ye yazilacak sekilde. dışarıdan başka bir entegre filan gerektirmeden.

dursuncemal

Alıntı yapılan: yolcu27 - 01 Nisan 2016, 12:54:30


Şimdi aklıma şöyle bir şey daha geldi bu kesme ile doğru hesaplamalar sonucunda dijital bir saat yapılabilir sanırım lcd ye yazilacak sekilde. dışarıdan başka bir entegre filan gerektirmeden.


evet yapabilirsin ama sadece yazdigin bir programa ozel zamanlamalar icin kullanabilirsin.gercek zamani gosterecek bir saat yapman cok zor.gercek zamani bir saat yapabilmen icin rtclerde kullanilan kristali kullanman gerekir.onlarda bile zaman kaymalari meydana gelir.
:=

yolcu27

#27
Yeni konu açmak istemedim buradan devam edeyim sorularıma.

şimdi @ete hocamızın bahsettiği gibi port kaydı alarak çakar ledimi etkilemeden buton kontrolü ile gerekli olan etiketlere yönlendirmeyi yapabiliyorum.

benim şuan düşündüğüm ise etiketler içerisinde sabit bir şekilde ledleri yakmak değilde bir sıra ile yakmak. örnek vermek gerekirse

LEDLER
portb=%00000001
pause 500
if porta.1=1 then BASLA
if porta.2=1 then BASLA
if porta.3=1 then BASLA
portb=%00000011
pause 500
if porta.1=1 then BASLA
if porta.2=1 then BASLA
if porta.3=1 then BASLA
portb=%00000111
pause 500
if porta.1=1 then BASLA
if porta.2=1 then BASLA
if porta.3=1 then BASLA
portb=%00001111
portb=%00000001
pause 500
if porta.1=1 then BASLA
if porta.2=1 then BASLA
if porta.3=1 then BASLA
portb=%00000011
pause 500
if porta.1=1 then BASLA
if porta.2=1 then BASLA
if porta.3=1 then BASLA
portb=%00000111
pause 500
if porta.1=1 then BASLA
if porta.2=1 then BASLA
if porta.3=1 then BASLA
portb=%00001111

GOTO LEDLER


şeklinde ama bu ledlerin arasına yine buton kontrolü koymak istiyorum misal olarak 3 butonum var bunlardan birine basılınca BASLA etiketine gitmesi gerekiyor

bu kodu aralara koyarak şu şekilde yapınca bekleme süresinden dolayı gecikme oluyor.


Bu buton kontrolünü pause dan  önce kullanirsam bekleme ne durumda olur acaba



mesaj birleştirme:: 05 Mayıs 2016, 14:37:42

aklıma hep nedense amelece çözümler geliyor.

şimdi düşündümde pause 500 yazan yeri bölsem de şöyle yapsam 100 ms de bir baksa basılmış mı basılmamış mı diye olmaz mı sizce?  kod satırları çoook uzayacak ama bunun başka yöntemi nedir

pause 100
gosub oku
pause 100
gosub oku
pause 100
gosub oku
pause 100
gosub oku
pause 100
gosub oku

oku:
if porta.1=1 then BASLA
if porta.2=1 then BASLA
if porta.3=1 then BASLA
return

ete

#28
Aşağıdaki satırları silip ,
pause 500
if porta.1=1 then BASLA
if porta.2=1 then BASLA
if porta.3=1 then BASLA

yerine,
GOSUB BEKLE
IF GIT=1 THEN BASLA
yaz.
BEKLE etiketi içine de şunları ekle
BEKLE:
GIT=0  'GIT BIT değişkeni 
FOR W=0 to 500
  PAUSE 1
  IF (PORTA & %00001110)>0 THEN GIT=1
NEXT 
RETURN

Gecikme uygulanırken butonlardan birisine basılırsa programın hemen BASLA etiketine gitmesini istersen THEN GIT=1 yerine;
...THEN
  GIT=1:RETURN
ENDIF
yazman gerekir.
Böylece epeyce kısalmış olur programın.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

yolcu27

Hocam şu şekilde kullanirsam sanırım son butona basılmışmi diye bakar değilmi diğer iki buton için kontrol geçmiş oluyor sanırım

if porta.1=1 then BASLA
if porta.2=1 then BASLA
if porta.3=1 then BASLA
pause 500
   


Pause dan önce koydum
Bu şekilde de sadece porta.3 e bakar degil mi en son satır var çünkü.

Şimdi programa biraz daha buton eklemek zorundayım.

Bu sefer a0 a1 ve a6 portlarindaki butona basınca BASLA etiketine.

a2 a3 ve a4 te de X Y Z etikletletine gitmesi gerekiyor.
Bende bu kontrollerin hepsini bir oku adlı etikete yazdım.
Dediğim gibi 100 ms de bir bu etikete gidip gelecek ve bakacak.  Bir deneyeyim. Eğer dediğim gibi olmazsa sizin dediğiniz yolu denerim .  fazla komuttan zarar gelir mi bilmiyorum ama 4 mhz yada 8mhz de dahili osilator ile 16f628 de çalışacak bunlar