Kesme

Başlatan demket, 09 Ocak 2012, 15:32:47

demket

Arkadaşlar kolay gelsin, yapmayı planladığım programda tuştakımı ile menü kontrolü yapmayı hedefliyorum, fakat bir çekincem var; kullanıcı menü içinde dolaşırken arka planda işler yürüsün istiyorum. Belirli bir süre menüde işlem yapmadan kalınca da tekrar ana program ekranına geri dönsün istiyorum.

Daha açacak olursak, ısı kontrolü yapıyorum. Fanlar, rezistanslar devreye girip çıkıyor ve sıcaklık değerlerini sdcard a yazıyor. Tuş takımından sinyal geldiğinde (B portu (B4-B7) kesmesi kullanmayı planlıyorum) menüdeki işlemleri yapmak için kesme prosedürü çağırılacak. Menü ekrana yazılacak vs... Bu esnada arka planda fan - rezistans - loglama işlemlerinin devam etmesi için nasıl bir yol izlenmesi gerekir. Mesela, her tuşa basıldığında kesme prosedürü çağrılıp tuşun gerektirdiği işlemi yapıp prosedürden çıkılarak, işlemin devam etmesi mi sağlanmalı? Bu esnada ekranda menüye ait yazılar silinip sıcaklık bilgisi gibi bilgiler basılacak vb...problemler olacak. Gerçi bunu da bir değişkene "ekrandaki menüyü silme" manasında bir değer atayarak çözebiliriz. En son menüden çık komutunu verince sıcaklık bilgisi ekrana basılır.
Ayrıca kişi menüden çıkmayı unuttu. Normal ekrana dönmesi için nasıl bir yol izlenmeli WDT ile yapılabilinir mi mesela?

Doğru yol mu izliyorum?Mantığını kavramaya çalışıyorum. Örnek varsa daha açıklayıcı olacaktır.

skara1214

#1
eğer kişi menude dolaşırken arkada işler yürüsün diyorsan interrupt mantıksız olur çünkü interruptta işler durur ama sana söyle birşey önerebilirim timer kesmesi yarat atıyorum 100 ms de bir kontrol et  menuye girilip girilmediğine burada bak.zaten kişinin butona v.s basması 100 ms  den daha fazladır.100 ms de  bir sistem durur bakar sonra kaldığı işe geri döner.böylece bir kere b1-4 kesmesine girip orada beklemesi önlenmiş olur.Böyle yapınca zaten arkada programlar yürüdügü için kişinin menuda kalıp kalmaması sistemi etkilemez ama istersen söyle bir formülde uygulayabilirsin.bir x tanımlarsın ilk defa menuye girdiğindede bu x i atıyorum 0 dan başlatırsın timer kesmesi oluştugunda eğer menudeyse kişi ve bir değişiklik yoksa x i bir artırırsın 100 ms lik bir kesme oluştugunu varsayarsan x 100 yada sen ne kadar süre atarsan ona geldiğinde otomatik sitedigin işlemi yaparsın ama bence gerek yok ddiğim gibi.
Herkes ölür ama herkes gerçekten yaşamaz

demket

O zaman şöyle olacak, diyelimki timer kesmesi aktifken butona basıldı ---> x isimli değişken sıfırsa menüyü lcd ye bas. x i bir arttır. timer kesmesinde bir düğmeye daha basıldı ---> if x==1 & tus ==1 ise ayarlar menüsüne git ve x= x * 10 + 1 else if x==1 & tus==2 ise tarih menüsüne git ve x = x*10+2 end if  gibi bir timer kesmesi prosedürü oluşturulcak (case kullanımı sanki daha uygun). x burada menüde hangi işlemde kaldığını hatırlaması için. Fakat diyelimki tarihi set edeceğiz ve 8 karakter gireceğiz. O zaman iş çok karışıyor. Aynı yöntemlemi yapacağız. Yoksa bu işin kolay bir yolu var mı?

skara1214

hayır ben anlatmak istedigim o değil dedinizki  menude dolaşırken arkada işler devam etsin .Sizinki gibi bir interrupt kullanılırsa kişi menuye girdiği an başka işler durur benim söylediğimde  50 ms de bir sistemi durdur bak bir tuşa basılmışmı  eğer basılmışsa bunu algıla .Mesela kişi menuye girmek istedi ve enter die bir tuşa bastı(keypaddan bir sayı geliyor entera karşılık),kesmede enterı algılayıp x=1 dersiniz ve anlarsınızki x=1 ise enter tusuna basıldı mainin içerisinde bir if komutu ile enter bilgisini karşılaştırıp enter komutunun yapmasını istediğiniz olayı gerçekleştirirsiniz.Eğer if komutunun içinden çıkarken x=0 yaparsanız her defasında aynı if in içine girmez ve bir işi bir kere yapmış olur.
ayrıca  menude unutmamak için tus takımından gelen her veride bir z=0 tanımlarsınız ve arttırmaya başlarsınız her yeni tus takımı verisindede bu z yi 0 larsınız .z=500 oldgunda tus takımından 10 sn dir veri almıyor olursunuz bunuda böyle algılarsınız .
Herkes ölür ama herkes gerçekten yaşamaz

demket

z olayını anladım.
her 50 ms de bir timer kesmesi sıfırlandığında butona basılmışmıyıda anladım. x mevzusunda da siz ekrana ana programda bastır diyorsunuz anladığım kadarıyla. Örnek varsa çok açıklayıcı olur aslında.

skara1214

ccs c kullanyorum o yüzden yazacağım kod yardımcı olmaz zaten bu sekildede bir kod yok elimde.siz baslayın yapmaya takıldıgınız yerde yardım etmeye çalışırım mantık olarak
Herkes ölür ama herkes gerçekten yaşamaz

demket

Evet biraz moladan sonra kaldığımız yerden konuya devam. 100 ms de bir, timer kesmesini JALV2 de oluşturmak için örneklere baktım. Timer3 kesmesi örneği gözüme çarptı. Fakat örnekte 0,5 ms de bir kesme oluşturulmuş. Bize 100 ms lazım. Nasıl yapabiliriz?

ByTEK

Hangi işlemci kullanılacak ve Kaç mhz'te çalıştırılacak ? Bunları bilirsem yardımım dokunabilir..

demket

20 MHz de 18f4620 kullanıyorum. timer3 ile olan örneği denediğimde (bir led yakıp söndürdüm) çalışıyor. Fakat ledin sönmesi ile yanması arasında geçen süreyi anlamak imkansız. Bu da 0,5 ms de bir kesmenin gerçekleştiğini doğruluyor gibi. Ben 50 - 100 - 500 veya 1000 ms için kontrol süreleri oluşturmak istiyorum. Timer kesmesi esnasında analog değer okuyup bunu forever loop un içinde kullanmak hedefim.

Teşekkürler,

ByTEK

ISISte yada gerçekte osilascop ile anlayabilirsin.. ben bir örnek kod yazayım ekleyeceğim..

demket

Jal timer3 örneğini veriyorum: BÜYÜK HARFlerle notlarımı tuttum herkes anlasın diye.

-- Title: Basic usage of timer3 module
-- Description: This example shows basic usage of timer3 to output a 1khz
--              square wave, while blinking a led.

include 18f4620                    -- target PICmicro
pragma target clock 20_000_000     -- oscillator frequency
pragma target OSC  HS              -- HS crystal or resonator
pragma target WDT  disabled        -- no watchdog
pragma target LVP  disabled        -- no Low Voltage Programming
pragma target MCLR external        -- reset externally

enable_digital_io()                -- make all pins digital I/O

-- timer out def YAPILACAKLARLA İLGİLİ TANIMLAMA
alias timer_out             is pin_a1
alias timer_out_direction   is pin_a1_direction
--
timer_out_direction = output

-- led def BİR DE LEDD TANIMLAMIŞ FOREVER LOOP İÇİNDE DÖNEN KISIM
alias led             is pin_a0
alias led_direction   is pin_a0_direction
--
led_direction = output

enable_digital_io()

-- init pic interrupt settings TIMER3 KESMESİNİN AYARLARI
intcon_gie  = on    ; enables all unmasked interrupts
intcon_peie = on    ; enables all unmasked peripheral interrupts

-- Set this to desired interval. timer3 will count up.
-- Interupt will occur when timer_interval rolls
-- over from 65535 to 0
var word timer_interval = 65535 - 2500 -- 63035 = 1khz square wave at 20mhz,
-- output will change every 0.5ms, full wave in 1ms.
-- interrupt occurs every 0.5ms
-- this value can be calculated:
-- 65535    - ( (1/1khz/2) / ( (1/20_000_000)*4 ) ) = 63035
-- timermax - ( (1/HZ/2) / ( (1/OSC FREQ  )*4 ) ) = timer_interval

-- timer3 setup
tmr3 = timer_interval  -- timer interval
t3con_tmr3cs = 0       -- use internal clock
pie2_tmr3ie  = 1       -- enable the timer3 interrupt bit
t3con_tmr3on = 1       -- 1 = enables timer 3
pir2_tmr3if  = off     -- clear overflow to start timer

-- set timer3 clock prescaler
-- each increment slows clock by a multiple of 2
t3con_t3ckps = 0 -- set prscal of 1:1

----------- TIMER KESMESİ
procedure timer_isr() is
   pragma interrupt          -- interupt procedure
   
   if !PIR2_TMR3IF then      -- check if this is a timer3 interupt
      return                 -- exit interupt if it is not
   end if
   
   PIR2_TMR3IF = off         -- clear overflow to start timer
   
   timer_out = !timer_out    -- TIMER KESMESİ OLDUĞUNDA BUNU YAP (HER 0,5 MİLİSANİYEDE BİR)
   TMR3 = timer_interval     -- set the interval
end procedure

-- main program here
forever loop
   _usec_delay (250_000)
   led = on
   _usec_delay (250_000)
   led = off
end loop

ByTEK

Aşağıdaki Kodu derlediğinde TMR3 kesmesi kullanarak 100ms aralıklarla kesme üretebilirsin. Forever loop arasına yapmak istediğin kodları yazabilirsin..

Eğer Kesme Süresini 100 ms katları şeklinde istersen bir değişken tanımla ve her kesme olduğunda 1 ekle.. Örneğin 500ms gerekli dersen değişken 5 olana kadar 1 ekle 5 olunca (if ile anlayabilirisin) işlem yaptır.


include 18f4620
pragma target clock 20_000_000

pragma target OSC  HS
pragma target WDT  disabled
pragma target LVP  disabled
pragma target MCLR external

enable_digital_io()

pin_b0_direction = output

--------------------------------------------------------------------------------
--       100 ms aralıklarla Kesme Üretip Ledi Yakıp Söndüren Program
--------------------------------------------------------------------------------

TMR3 = 3036                -- Başlangıç Değeri
T3CON_T3CKPS   = 0b11      -- 1:8 prescaler
T3CON_TMR3ON   = on        -- TMR3 Açık
PIE2_TMR3IE    = on        -- TMR3 Kesmesi Etkin
INTCON_PEIE    = on        -- Çevresel Kesmeler Etkin
INTCON_GIE     = on        -- Kesme Kullanımı Etkin

procedure kesme() is
   pragma interrupt
   
       pin_b0 = !pin_b0
   
   TMR3 = 3036             -- Başlangıç Kesme Değeri
   PIR2_TMR3IF = off       -- Kesme Bayrağı Sıfırlanıyor
end procedure
--------------------------------------------------------------------------------

-- Gerekli Kesme Zamanlarını aşağıdaki web sitesinden Ayarlayabilirsin..

-- http://eng-serve.com/pic/pic_timer.html


forever loop

end loop


Tüm dosyalar için : http://s2.dosya.tc/server9/iBpkmn/demketexample.rar.html

demket

İki sorum olacak. Süre uzatmak için kullandığımız değişkeni programın başında değilde timer3 kesmesinin içinde tanımlarsak ne olur. Değişken her kesmede sıfırlanır mı yoksa kaldığı yereden devam mı eder?
Verdiğin linkte timer3 kesmesini göremedim. Yani 20 MHz de 1:8 prescaler da 65535-3036 da 100 ms lik gecikme ürettiğimizi nasıl bulduk.

ByTEK

Alıntı yapılan: demket - 14 Mart 2012, 13:39:38
İki sorum olacak. Süre uzatmak için kullandığımız değişkeni programın başında değilde timer3 kesmesinin içinde tanımlarsak ne olur. Değişken her kesmede sıfırlanır mı yoksa kaldığı yereden devam mı eder?
Verdiğin linkte timer3 kesmesini göremedim. Yani 20 MHz de 1:8 prescaler da 65535-3036 da 100 ms lik gecikme ürettiğimizi nasıl bulduk.

1.soru :

include 18f4620
pragma target clock 20_000_000

pragma target OSC  HS
pragma target WDT  disabled
pragma target LVP  disabled
pragma target MCLR external

enable_digital_io()

pin_b0_direction = output

var byte kesme_suresi = 10   -- Vereceğiniz deger kesme süresini belirler.

-- örnek  : 500 ms için değer 5 olmalıdır. (istenen sure / 100)

--------------------------------------------------------------------------------
--       100 ms aralıklarla Kesme Üretip Ledi Yakıp Söndüren Program
--------------------------------------------------------------------------------

TMR3 = 3036                -- Başlangıç Değeri
T3CON_T3CKPS   = 0b11      -- 1:8 prescaler
T3CON_TMR3ON   = on        -- TMR3 Açık
PIE2_TMR3IE    = on        -- TMR3 Kesmesi Etkin
INTCON_PEIE    = on        -- Çevresel Kesmeler Etkin
INTCON_GIE     = on        -- Kesme Kullanımı Etkin

procedure kesme() is
 var byte sure
   pragma interrupt
      sure = sure + 1
      if sure == kesme_suresi then
        pin_b0 = !pin_b0
        sure = 0
      end if
   TMR3 = 3036             -- Başlangıç Kesme Değeri
   PIR2_TMR3IF = off       -- Kesme Bayrağı Sıfırlanıyor
end procedure
--------------------------------------------------------------------------------

-- Gerekli Kesme Zamanlarını aşağıdaki web sitesinden Ayarlayabilirsin..

-- http://eng-serve.com/pic/pic_timer.html


forever loop

end loop


yukarıdaki kodu incelersen aradığın cevabı bulacaksın..

2. Soru : TMR3 16 bitlik olduğu için o linktede TMR1 için olanıda kullansak yeterlidir. oradaki değerleri değiştirerek istediğin süreyi ayarlayabilirsin..


demket

Çok teşekkür ederim.