kesmeden geri donmeden devam etmek ?

Başlatan ibo1973, 06 Ağustos 2008, 12:03:37

ibo1973

arkadaşlar yazdığım program oldukça uzun ve içinde bir sürü pause lar var benim sıkıntım kesmelerle ilgili  sorunum şu program

page1:
disable ' kesmeyi sadece burada kapatabiliyorum
gosub degeroku

                if deger=1f then  'iş1              
                         enable
                         intcon=%10010000
                         on interrupt goto page1                                      
                         yapılan iş var burda
                          pause 100
                          yapılan iş
                          pause 100
                          pause 100
                          yapılan iş
                          pause 100
                          gosub sonlandir
                          intcon.1=0
                          disable
                          endif
             

 if deger=21 then  'iş2              
                          yapılan iş var burda
                          pause 100
                          yapılan iş
                          pause 100
                          pause 100
                          yapılan iş
                          pause 100
                          gosub sonlandir
                          endif

goto page1
degeroku:
burda değer okuyor ve gelen varsa returnla geri donuyor
return


sonlandir:
yapilan işlerin sonlandirmasi rutini var burda
return

evet ornek bu çeşitli yazım hataları olabilir derdimi anlatmak için ornek olarak yazdım


şimdi sorum şu  bu kesmeyi koyduğum yerde pauseler var bu pauselerin ve işlerin kesme gelmediği zamanlarda çalışması lazım geliyor ama keseme gelincede orneğin iş 2 ye gitmesi gerekiyor aslında verdiğim ornekte zaten kesme gelince iş birden çıkıp iş 2 ye gidiyor  ama sorun şu ki resume ile devam etmiyorum iş 2 ye gidince ordaki iş bitince page1 e gidiyorum ve butun kesme orneklerinde keseme olştuğu anda  kesmeleri iptal edin diyor ama ben iptal edemem iş izin vermiyor buna pauselerinde içinde bulunduğu bu iş kesme gelince kesilip iş 2 ye gitmesi veya ilgili başka bir yere donmemek üzere gitmesi lazım geliyor ve 10- 15 defa kesme yapıp çalışıyorda ama sonra sapıtıp kalıyor çalışmamaya başlıyor

yani ozetle
1- kesmenin olduğu yerde pause 40-50 tane kadar var
2- kesme oluşunca kesmenin olduğu yere geri donmuyorum başka yerlere dallanıyorum
3- kesme oluşup işe dallanınca kesmeyi kapatmıyorum iş izin vermiyor

kesmeyi sizce işte nasıl kulanmalıyım sapıtmasın diye ?

teşekkür ederim

picusta

Ilk olarak yapman gereken interrupt'tan ana programa daha çok kod transfer etmek. Interrupt'ta bir iki kosul test et, sonra flag set et, ana programda flagleri oku ve ona göre isini yap.
Pause komutu yerine timer interrupt'u kullanan kendi pause fonksyonunu yaz, interruptlar kesilmez böylece.
Yetmezse preemptif çoklu görev kabiliyetine sahip bir isletim sistemi kullanman. Interruptler ile bir yere kadar gelebilirsin.
PIC18 kullaniyorsan iki interrupt kademesi oldugunu unutma, öncelikli interrupt düsük öncelikli interruptu kesebilir.

karbal656

Kesmelerde program nerede kalmışsa kesme rutini sonunda tekrar aynı yerden başlaması için pic te bir adres registeri kullanılır.
Her kesme oluştuğunda kesmenin olduğu yer adres registerine kaydedilir.
kesmeden geri dönüşte bu register otomatik olarak sıfırlanır.Fakat eger rutin içerisinde başka yerlere dalanmalar olmuş ise ve tekrar geri dönüş sözkonusu olmuyorsa adres registeri şişme yapar. Bu şişmenin sonucunda pic sapıtır.Bunu engelemek için kesme rutininde mümkün olduğunca dallanmalara izin vermemelisin.
Örneğin:
IF DEGER=1F THEN   IS_1

BU kodu kesme rutinde kullanırsan kesme rutininden çıkan program
adres registerinin şişmesine sebep olur ve bir süre sonra pic sapıtır.
Başarılar.

Lütfi AYYILDIZ

Pause yerine aşağıdaki gibi gecikme kullansan kesmelerin daha sağlıklı çalışır.
GOSUB GECIKME
........
GECIKME:
        FOR X=0 TO 1000
        PAUSEUS 100
        NEXT
        RETURN

ibo1973

Alıntı yapılan: "karbal656"Kesmelerde program nerede kalmışsa kesme rutini sonunda tekrar aynı yerden başlaması için pic te bir adres registeri kullanılır.
Her kesme oluştuğunda kesmenin olduğu yer adres registerine kaydedilir.
kesmeden geri dönüşte bu register otomatik olarak sıfırlanır.Fakat eger rutin içerisinde başka yerlere dalanmalar olmuş ise ve tekrar geri dönüş sözkonusu olmuyorsa adres registeri şişme yapar. Bu şişmenin sonucunda pic sapıtır.Bunu engelemek için kesme rutininde mümkün olduğunca dallanmalara izin vermemelisin.
Örneğin:
IF DEGER=1F THEN   IS_1

BU kodu kesme rutinde kullanırsan kesme rutininden çıkan program
adres registerinin şişmesine sebep olur ve bir süre sonra pic sapıtır.


Başarılar.
teşekkür ederim sanırım benimde sorunum bu olabilir çünkü yukarda yazdığım gibi geri dönüş söz konusu değil

peki geri dönüş söz konusu olmadığına göre  adres registeri veya artık neresiyse nasıl temizliyicem

geri dönüş olması mumkun değil(yapılan iş icabı) program içinde pic18f2550 kulanıyorum


örnek bir kod yazman mümkünmü veya elinde bu kod olan birisi buraya ekleyebilirmi ?

ibo1973

Alıntı yapılan: "cobra07"Pause yerine aşağıdaki gibi gecikme kullansan kesmelerin daha sağlıklı çalışır.
GOSUB GECIKME
........
GECIKME:
        FOR X=0 TO 1000
        PAUSEUS 100
        NEXT
        RETURN

teşşkür ederim ama sorun pauselerle ilgili değil zaten bu dediğini kitaplarda ve internette her yerde yazmışlar ama hatırlatman için teşşekür ederim kesmeler sağlıklı hale gelince zaten bunu yapıcam aslında yapmasamda olur 1 sn lik bir geçikme benim için sorun olmaz.

ibo1973

Alıntı yapılan: "picusta"Ilk olarak yapman gereken interrupt'tan ana programa daha çok kod transfer etmek. Interrupt'ta bir iki kosul test et, sonra flag set et, ana programda flagleri oku ve ona göre isini yap.
Pause komutu yerine timer interrupt'u kullanan kendi pause fonksyonunu yaz, interruptlar kesilmez böylece.
Yetmezse preemptif çoklu görev kabiliyetine sahip bir isletim sistemi kullanman. Interruptler ile bir yere kadar gelebilirsin.
PIC18 kullaniyorsan iki interrupt kademesi oldugunu unutma, öncelikli interrupt düsük öncelikli interruptu kesebilir.

teşşekür ederim

ama tam olarak anlamadım biraz anlar gibi oldum ama ne yapmam gerektiğini anlamadım müm künse bir kaç kod ile örnek yazabilirmisin teşşekür ederim

Tagli

18F serisinde hardware stack (dallanmalar sırasında eski adresi kaydeden yığın) üzerinde değişiklik yapabilirsin. PicBasic Pro'da nasıl yapılıyor bilmiyorum ama ASM'de "POP" diye bir komut vardı, bu komutla geri dönme yapmadan yığının tepesindeki değeri silebilirsin ve sonra da programa hiçbir şey olmamış gibi devam edersin, yani sanki kesmeden çıkmış gibi olur. Denemedim ama işe yarayacağını sanıyorum. Ama yine de böyle yöntemlerden mümkün olduğunca kaçınılmalı bence, hata yapma ihtimalini arttırır düşüncesindeyim.
Gökçe Tağlıoğlu

ibo1973

Alıntı yapılan: "Tagli"18F serisinde hardware stack (dallanmalar sırasında eski adresi kaydeden yığın) üzerinde değişiklik yapabilirsin. PicBasic Pro'da nasıl yapılıyor bilmiyorum ama ASM'de "POP" diye bir komut vardı, bu komutla geri dönme yapmadan yığının tepesindeki değeri silebilirsin ve sonra da programa hiçbir şey olmamış gibi devam edersin, yani sanki kesmeden çıkmış gibi olur. Denemedim ama işe yarayacağını sanıyorum. Ama yine de böyle yöntemlerden mümkün olduğunca kaçınılmalı bence, hata yapma ihtimalini arttırır düşüncesindeyim.

cevabın için teşşekür ederim hafızan içinde tebrik ederim yani iyi hatırlamışşın evet gerçektende po diye bir komut var 18f serisi için ama kulanımıyla ilgili herhangi bir şey bulamadım basicte zaten yok ama asm sinide bulamadım

POP --  Pop top of return stack 1 0000 0000 0000 0110    
PUSH --  Push top of return stack 1 0000 0000 0000 0101
http://www.piclist.com/techref/microchip/18c/inst.htm alıntıdır
asm den anlamıyorum ama bir örenk kod olsa asm yazıp kodu araya ekleyip endasm ilede programa dahil edip deneyebilirdim.
sorunu hala çözemedim yardımlarınızı ve fikirlerinizi bekliyorum arkadaşlar teşşekür ederim

Tagli

Alıntı yapılan: "18FXX2 Datasheet"
The ability to pull the TOS value off of the stack and replace it with the value that was previously pushed onto the stack, without disturbing normal execution, is achieved by using the POP instruction. The POP instruction discards the current TOS by decrementing the stack pointer. The previous value pushed onto the stack then becomes the TOS value.

Normalde bir kesmeyi sonlandırdığın zaman (ASM'de return türündeki komutlardan herhangi biri olabilir, genelde RETIE kullanılır) program, yığına yerleşmiş en son adrese gider (yani yığının en üstündeki adres) - ki bu kaldığı yere geri dönmektir - , ve bu adresin işi bittiği için yığın işaretçisini bir azaltır (stack pointer), yani bu son adres değeri çöpe atılır gibi düşün.

Peki kesme bölümüne girdikten sonra return demezsek ne olur? Geri dönmeyeceğimiz bir adres değeri yığında gereksiz yere yer kaplar. 16F serisinde yığın derinliği 8'dir (ve bu yüzdendir ki PicBasic Pro, 4'ten fazla iç içe fonksiyon çağırmaya izin vermez, anlaşılan kalan 4'ü de kendi asm'ye dönüşüm işlemlerine ayırmış). 18F serisinde bu derinlik 31, yani bu konuda daha rahatsın, ama sen kesmeye tekrar tekrar girdikçe sonunda bu yığın da dolacaktır. 16F serisinde maalesef yığına müdahale edemiyorduk. Yığından bir değer silmenin tek yolu return ile geri dönmekti ve o zaman yığın işaretçisi azaltıldığı için adres silinmiş gibi oluyordu. 18F serisindeki POP komutu geri dönmeden yığın işaretçisini azaltmanı sağlar, böylece yığının dolması derdinden kurtulursun, kesmeden geri dönmen de gerekmez.

Sanırım senin yapman gereken şey kesme bölümünün sonuna RETURN yazmayıp onun yerine POP'u asm kodu olarak eklemen. Sonra da programa sanki hiç kesmeye girmemişsin gibi devam et. Ama elbette kesme ile ilgili bayrakların ayarlarını unutma. Çoğu bayrak kesmeden sonra eski haline geri gelmez, bu işlemi programda yapman gerekir.
Gökçe Tağlıoğlu

ibo1973

Alıntı yapılan: "Tagli"
Alıntı yapılan: "18FXX2 Datasheet"
The ability to pull the TOS value off of the stack and replace it with the value that was previously pushed onto the stack, without disturbing normal execution, is achieved by using the POP instruction. The POP instruction discards the current TOS by decrementing the stack pointer. The previous value pushed onto the stack then becomes the TOS value.

Normalde bir kesmeyi sonlandırdığın zaman (ASM'de return türündeki komutlardan herhangi biri olabilir, genelde RETIE kullanılır) program, yığına yerleşmiş en son adrese gider (yani yığının en üstündeki adres) - ki bu kaldığı yere geri dönmektir - , ve bu adresin işi bittiği için yığın işaretçisini bir azaltır (stack pointer), yani bu son adres değeri çöpe atılır gibi düşün.
Peki kesme bölümüne girdikten sonra return demezsek ne olur? Geri dönmeyeceğimiz bir adres değeri yığında gereksiz yere yer kaplar. 16F serisinde yığın derinliği 8'dir (ve bu yüzdendir ki PicBasic Pro, 4'ten fazla iç içe fonksiyon çağırmaya izin vermez, anlaşılan kalan 4'ü de kendi asm'ye dönüşüm işlemlerine ayırmış). 18F serisinde bu derinlik 31, yani bu konuda daha rahatsın, ama sen kesmeye tekrar tekrar girdikçe sonunda bu yığın da dolacaktır. 16F serisinde maalesef yığına müdahale edemiyorduk. Yığından bir değer silmenin tek yolu return ile geri dönmekti ve o zaman yığın işaretçisi azaltıldığı için adres silinmiş gibi oluyordu. 18F serisindeki POP komutu geri dönmeden yığın işaretçisini azaltmanı sağlar, böylece yığının dolması derdinden kurtulursun, kesmeden geri dönmen de gerekmez.

Sanırım senin yapman gereken şey kesme bölümünün sonuna RETURN yazmayıp onun yerine POP'u asm kodu olarak eklemen. Sonra da programa sanki hiç kesmeye girmemişsin gibi devam et. Ama elbette kesme ile ilgili bayrakların ayarlarını unutma. Çoğu bayrak kesmeden sonra eski haline geri gelmez, bu işlemi programda yapman gerekir.

sonuç olumlu problem ortadan kalktı
[code]
dongu:
intcon.1=0
@pop
disable

anaprogram:
if rx=$15 then
             intcon=%10010000                              
             enable
             usbservice
             on interrupt goto dongu  'iş kesme
             burada tabiki yapılan işler var pauseler  oldukça uzun bi satır
             endif
goto anaprogram
end
 
yaptığım bu ilerde bu sorunla karşılaşanlar 18f serisi için bunu gozden geçirebilirler.

çok çok teşekkür ederim dediğim gibi sorun çözüldü.