Portb.0 kesmesinde hata nerde ?

Başlatan solidus, 30 Ağustos 2009, 14:42:23

solidus

ADCON1=7
TRISA=%11111111
TRISB=%11111111
TRISC=%10101111
OPTION_REG=%10000000

ON INTERRUPT GOTO KESME
INTCON=%10010000
              "
              "
              "
              "
DISABLE
KESME:
LCD_LED=1
PAUSE 2000
INTCON.1=0
LCD_LED=0
RESUME
ENABLE

İşlemcimiz 16f876. Amacımız ise portb.0 kesmesini kullanarak portc.6'dan LCD aydınlatmasını yapabilmek. Sorun şu kesme etiketinin altında PAUSE 2000 kullandığımda işlemci başka bir işlem yapmadan bekliyor. Ancak bu sürenin sonunda işlem yapmaya başlıyor. Kesme rutini içinde kullanıldığında PAUSE komutunda hiç bir işlem yapılmadığını biliyoruz. Dolayısıyla LCD aydınlatması sönmeden ayar v.b işlemleri yapamıyoruz.Bu durumu nasıl engelleyebiliriz ?
Kimine göre kralım kimine göre yalanım… Herkes rahatına baksın, ben adamına göre adamım..

XX_CİHAN_XX

Yirmi yaşındaki bir insan, dünyayı değiştirmek ister . Yetmiş yaşına gelince , yine dünyayı değiştirmek ister, ama yapamayacağını bilir.

selvi

us adli bir  degisken tanimlarsin.rb0 kesmesi olustugunda us=1 olsun.islemleri kesme disinda yaparsan daha uygun olur.kesmenin olusmasinda sorun olmamasi icin pause 2000 i daha kucuk arcalara bolmelisin.cunku pause komutu islenirken kesme olusmaz.programi  yaabilirsen sorun cozulebilir.ager sorununu yanlis anlamadiysam .
US VAR BYTE
I  VAR WORD
US=0:I=0
DONGU:
IF US=1 THEN
US=0
LCD_LED=1
FOR I=0 50000
PAUSEUS 20 
PAUSEUS 20
NEXT I
LCD_LED=0
ENDIF
.
.
.
GOTO DONGU
KESME:
DISABLE
US=1
INTCON.1=0
RESUME
ENABLE
END
Yaşam anlamlandırıldıkça kutsaldır....

ibrsel

For next döngüsü içerisinde işlemciyi oyalayarak bekleme gerçekleştirebilirsin..

solidus

Alıntı yapılan: "ibrsel"For next döngüsü içerisinde işlemciyi oyalayarak bekleme gerçekleştirebilirsin..

Bir örnek verebilirmisin ?
Kimine göre kralım kimine göre yalanım… Herkes rahatına baksın, ben adamına göre adamım..

Ziya

kesme içerisinde delay komutları ilave stack kullanımına neden olur. Yazılımındaki en derin stack üzerine +1 kesme ve +pause kumutundan gelen call deyimleri nedeniyle 8 bayt LIFO stack alanı çok çabuk dolacaktır, hele lcd komutları kullanırsanız +3 veya +4 alan daha kaybedersiniz. Bu da ana programınızda en fazla 3 stack alanı kullanabileceğiniz anlamına gelir. Kesme içerisinde stack tüketmeyen algoritmalar kullanmakta fayda var.

rb.0 için kesme tanımlamak yerine ana programda rb.0 kesmesine ait flagi kontrol etmek işinizi daha kolaylaştıracaktır. (flag'i resetlemek için rb.0 ı bir defa okutmanız gerekir.)
Bu günden sonra hiç kimse sarayda, divanda, meclislerde ve seyranda Türk dilinden başka dil kullanmaya. (13 Mayıs 1277) Karamanoğlu Mehmet Bey

solidus

Alıntı yapılan: "Ziya"kesme içerisinde delay komutları ilave stack kullanımına neden olur. Yazılımındaki en derin stack üzerine +1 kesme ve +pause kumutundan gelen call deyimleri nedeniyle 8 bayt LIFO stack alanı çok çabuk dolacaktır, hele lcd komutları kullanırsanız +3 veya +4 alan daha kaybedersiniz. Bu da ana programınızda en fazla 3 stack alanı kullanabileceğiniz anlamına gelir. Kesme içerisinde stack tüketmeyen algoritmalar kullanmakta fayda var.

rb.0 için kesme tanımlamak yerine ana programda rb.0 kesmesine ait flagi kontrol etmek işinizi daha kolaylaştıracaktır. (flag'i resetlemek için rb.0 ı bir defa okutmanız gerekir.)

Hocam bunu nasıl yapabileceğime dair küçük bir örnek verebilirseniz daha kolay anlaşılacak...
Kimine göre kralım kimine göre yalanım… Herkes rahatına baksın, ben adamına göre adamım..

ibrsel

Selvi hocam For next döngüsü ile ilgili örnek vermiş zaten..
Örneğin 10 sn bekleme yapmak istiyorsun diyelim..Bu esnada interrupt oluşur isen işlemcin beklemede olduğu için bunu algılamayacaktır..öyleyse bekleme zamanını minumum değere bölüp bunu döngü içerisinde tekrarlatabilirsin..

Örneğin:

   For a=1 to 100
         Pause 100   '' 0,1 saniye bekle
   Next a

Gibi..0,1 saniye bekletip bunu 100 defa tekrarlatır isen 10 sn beklemeye denk gelmiş olursun..Tabiki bu yaklaşık değer. Çünkü For ve next komutlarının işlevi için işlemci birkaç ms harcayacaktır..Ama 10 sn sürekli bekleme yapmamış olacaksın. bu arada gelecek olan kesme sinyalini de yakalamış olursun..Ayrıca döngü değerini arttırıp bekleme süresini daha da küçültebilirsin..

solidus

DISABLE
KESME:
IF US=1 THEN 
US=0 
LCD_LED=1 
FOR I=0 to 40000 
PAUSEUS 20 
NEXT I 
LCD_LED=0
ENDIF
US=1
INTCON.1=0
RESUME
ENABLE
End


Programın en sonuna kesme etiketini ve işlemleri koydum. Fakat bu durumda da aynı problemi yaşıyoruz. 40000*20mikrosn'lik gecikme bitmeden pic başka bir işlem yapmıyor. Simülasyonda dikkat çeken bi hata da 3 adet butondan herhangi birine 2 kez basmadan lamba yanmıyor. Kesme de hata mı yaptım acaba ?
Kimine göre kralım kimine göre yalanım… Herkes rahatına baksın, ben adamına göre adamım..

Ruzgarbey

Alıntı yapılan: "solidus"
DISABLE
KESME:
IF US=1 THEN 
US=0 
LCD_LED=1 
FOR I=0 to 40000 
PAUSEUS 20 
NEXT I 
LCD_LED=0
ENDIF
US=1
INTCON.1=0
RESUME
ENABLE
End


Programın en sonuna kesme etiketini ve işlemleri koydum. Fakat bu durumda da aynı problemi yaşıyoruz. 40000*20mikrosn'lik gecikme bitmeden pic başka bir işlem yapmıyor. Simülasyonda dikkat çeken bi hata da 3 adet butondan herhangi birine 2 kez basmadan lamba yanmıyor. Kesme de hata mı yaptım acaba ?

merhaba arkadaşlar.anladığım kadarı ile rb.0 kesmesi kullanarak lcd ekranın aydınlatmasını 10 saniye ve belirlenek bir süre yanık kalması isteniyor.ama lcd nin yanık kaldığı sürede pic yine işlem yapsın diyorsak timer kesmesini kullanmanızı tavsiye ederim.hem lcd nizin lambası kesme oluştuğu sürece veya sizin istediğiniz süre yanık kalır hemde picin yapmasını istediğiniz işlemleri yapar.hazır kod olarak değilde mantık olarak vereyim.tanımlamalarda timer kesmesinide tanımlayın.rb0 kesmesi oluştuğunda timer kesmesini aktif edin.ve her timer kesmesinde sayac oluşturup sayac istenilen değere geldiğinde eğer herhangi bir rb0 kesmesi daha oluşmamıssa lcd ledi söndürüp timer kesmesini pasif yapın.kesme işlemlerinde pause kullanmak sakıncalıdır çünkü pic bekleme yaptığı için oluşan kesmeyi algılama yapamaz.similasyondaki sorunda bundan kaynaklandığını sanıorum.saygılarımla..
Hayatta En Hakiki Mürşid İlimdir. M.K. ATATÜRK

solidus

@Ruzgarbey,
bu dediklerinizi toparlamak istersek nasıl bir kod yazmamız gerek ?
Kimine göre kralım kimine göre yalanım… Herkes rahatına baksın, ben adamına göre adamım..

Ruzgarbey

Alıntı yapılan: "solidus"@Ruzgarbey,
bu dediklerinizi toparlamak istersek nasıl bir kod yazmamız gerek ?
rb0 kesmesinde ne yapmak istiyorsunuz.yani bir butona basıldığında ekran ne kadar yanacak.tekrar butona basılırsa ekran yanmaya devam edecekmi..bunları belirtirseniz bişiler yapmaya çalışırız.saygılarımla..
Hayatta En Hakiki Mürşid İlimdir. M.K. ATATÜRK

solidus

Alıntı yapılan: "Ruzgarbey"
rb0 kesmesinde ne yapmak istiyorsunuz.yani bir butona basıldığında ekran ne kadar yanacak.tekrar butona basılırsa ekran yanmaya devam edecekmi..bunları belirtirseniz bişiler yapmaya çalışırız.saygılarımla..

Herhangi bir anda 3 butondan herhangi birine basıldığında LCD aydınlatması yanacak mesela 8sn süre ile..Ama düğmeye bastıktan 3 sn sonra düğmelerden herhangi birine tekrar basılırsa 8sn yeniden başlayacak.. Süre sonunda LCD aydınlatması sönecek..
Kimine göre kralım kimine göre yalanım… Herkes rahatına baksın, ben adamına göre adamım..

Ruzgarbey

Alıntı yapılan: "solidus"
ADCON1=7
TRISA=%11111111
TRISB=%11111111
TRISC=%10101111
OPTION_REG=%10000000

ON INTERRUPT GOTO KESME
INTCON=%10010000
              "
              "
              "
              "
DISABLE
KESME:
LCD_LED=1
PAUSE 2000
INTCON.1=0
LCD_LED=0
RESUME
ENABLE

İşlemcimiz 16f876. Amacımız ise portb.0 kesmesini kullanarak portc.6'dan LCD aydınlatmasını yapabilmek. Sorun şu kesme etiketinin altında PAUSE 2000 kullandığımda işlemci başka bir işlem yapmadan bekliyor. Ancak bu sürenin sonunda işlem yapmaya başlıyor. Kesme rutini içinde kullanıldığında PAUSE komutunda hiç bir işlem yapılmadığını biliyoruz. Dolayısıyla LCD aydınlatması sönmeden ayar v.b işlemleri yapamıyoruz.Bu durumu nasıl engelleyebiliriz ?

en basit şekilde yazmaya çalışacağım..

INTCON = %11000000    ' Tmr0 aktif
OPTION_REG=%01010101   'Pull up dirençleri İPTAL- Bölme oranı 1/64.
tmr0=0
Lcdk=0

DISABLE
KESME:
if INTCON.1=1 then
z=1 ' rb0 kesmesi oluşmussa
Led_isik=0   ' her Rb0 kesmesinde Sayacı sıfırla ve 8sn yan
SAYAC=0
Lcdk=0
endif
if z=1 then
if Lcdk=0 then  'Işık daha önce yakıldımı?
LCD_Led=1  ' Aydınlatmayı Yak
Lcdk=1
endif
SAYAC=SAYAC+1  ' rb0 kesmesi oluştuğunda saymaya başla
if SAYAC=61 then ' sayac 61 olduğunda 1 sn
SAYAC=0
Led_isik= Led_isik +1
endif
if Led_isik=8 then ' bu süre içinde başka kesme olmadıysa
LCD_LED=0
Led_isik=0
SAYAC=0
Z=0
Lcdk=0
endif
endif
RESUME
ENABLE

Umarım işine yarar.saygılarımla...
Hayatta En Hakiki Mürşid İlimdir. M.K. ATATÜRK

solidus

@Ruzgarbey,
@ DEVICE pic16F876              ' System Device	
@ DEVICE pic16F876, WDT_ON      ' Watchdog Timer
@ DEVICE pic16F876, PWRT_ON     ' Power-On Timer
@ DEVICE pic16F876, BOD_ON      ' Brown-Out Detect
@ DEVICE pic16F876, LVP_OFF     ' Low-Voltage Programming
@ DEVICE pic16F876, CPD_OFF     ' Data Memory Code Protect
@ DEVICE pic16F876, PROTECT_OFF ' Program Code Protection
@ DEVICE pic16F876, XT_OSC

Define LCD_DREG      PORTC ' LCD data portunu belirle 
Define LCD_DBIT      4 ' 4 bit'lik veri yolu 
Define LCD_RSREG     PORTC ' LCD register seçme portunu belirle 
Define LCD_RSBIT     2 ' LCD register seçme bitini belirle 
Define LCD_EREG      PORTC ' LCD enable portunu belirle 
Define LCD_EBIT      3 ' LCD enable bitini belirle 
Define LCD_LINES     2 ' LCD'deki satir sayisi
ADCON1=7
TRISC=%00000000
ON INTERRUPT GOTO KESME
INTCON = %11000000 ' Tmr0 aktif 
OPTION_REG=%01010101 'Pull up dirençleri İPTAL- Bölme oranı 1/64.

LCDK VAR BYTE
Z VAR BYTE
Led_isik VAR BYTE
SAYAC VAR BYTE
LCD_Led VAR PORTC.1 
tmr0=0 
Lcdk=0
BASLA:
PAUSE 300
LCDOUT $FE,$80,"MERHABA"
LCDOUT $FE,$C0,"KESME ILE LCD"
LCDOUT $FE,$94,"AYDINLATIYORUZ"

DISABLE 
KESME: 
if INTCON.1=1 then 
z=1 ' rb0 kesmesi oluşmussa 
Led_isik=0 ' her Rb0 kesmesinde Sayacı sıfırla ve 8sn yan 
SAYAC=0 
Lcdk=0 
endif 
if z=1 then 
if Lcdk=0 then 'Işık daha önce yakıldımı? 
LCD_Led=1 ' Aydınlatmayı Yak 
Lcdk=1 
endif 
SAYAC=SAYAC+1 ' rb0 kesmesi oluştuğunda saymaya başla 
if SAYAC=61 then ' sayac 61 olduğunda 1 sn 
SAYAC=0 
Led_isik= Led_isik +1 
endif 
if Led_isik=8 then ' bu süre içinde başka kesme olmadıysa 
LCD_LED=0 
Led_isik=0 
SAYAC=0 
Z=0 
Lcdk=0 
endif 
endif 
RESUME 
ENABLE

END


kodlarla bu şekilde küçük bir şey yapmaya çalıştım. Ama gene de sorun var gibi. Proteus dosyasını ve gerekli dosyaları inclermisiniz ?

Kesme İle LCD Aydınlatma Dosyalar
Kimine göre kralım kimine göre yalanım… Herkes rahatına baksın, ben adamına göre adamım..