Kesme ve Count Yardım Lütfen

Başlatan trajan, 23 Ağustos 2016, 17:42:49

trajan

Merhaba öncelikle siteye yeni üye oldum, burada bazı konuları da sürekli olarak takip ediyorum.
Benim üzerinde çalıştığım projede bazı problemlerim var.
Pic12f683 te yapmak istediğim;

* Buton Kesme Yapacak
* Aynı Butonla Kesmeden sonra daha kaç kere basıldığı kontrol edilecek
* Eğer hiç basılmamışsa program başa dönecek 
* Eğer kesmeden sonra 2 defa daha basılıp bırakılmışsa Ayar bölümüne geçecek,

kodda en son geldiğim nokta aşağıdaki gibidir. Fakat bir türlü çalıştıramadım. Count ya saymıyor kısacası Ayar etiketine gönderemedim. Yardımcı olursanız sevinirim. Teşekkürler.

@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_ON

OSCCON     =%01100001               ' Dahili Kristal Kullanılacak
CMCON0     = 7                      ' Karşılaştırıcı Kapalı
ADCON0     =%10000000               ' Analog Dijital Konvertör Sola yaslı
ANSEL      =%01110010               ' 1. Pin Analog Giriş
INPUT GPIO.0

on interrupt goto KESME             ' Kesme Olduğunda KES'e git

OPTION_REG =%11000000               ' Pullup Kapalı, Yükselen Kenar Kesme
INTCON     =%10010000               ' Kesmeler Açık, GPIO.2 Kesmesi Aktif

DEFINE OSC 4                        ' Dahili Kristal 4Mhz Çalışacak
DEFINE ADC_BITS 10                  ' Analog / Dijital Çevrim Sonucu 10 Bit
DEFINE ADC_CLOCK 3                  ' Clock Kaynağı (3=rc)
DEFINE ADC_SAMPLEUS 50              ' Örnekleme Zamanı (Micro Saniye)

ROLE  CON 5                         ' GPIO.2 Role Olarak Ayarlandı.
POTA  VAR WORD                      ' Potansiyometre Değişkeni 0-1024 Arası
LDR   VAR WORD                      ' LDR değişkeni 0-1024 Arası
X     VAR BYTE                      ' X Değişkeni 0-255 Arası
HAS   VAR BYTE                      ' Hassasiyet 0-255 Arası
DURUM VAR BYTE                      ' Durum 0-255 Arası
X = 0

eeprom 0,[1,240]                    ' EPROM'un 0. ve 1. Adresine Sabitleri Yaz.
                                    ' Durum 1 = Açık 0 = Kapalı

BASLA:                              ' Program Başlangıcı
ENABLE
IF GPIO.2 = 1 THEN GOTO KES
HIGH ROLE
GOTO BASLA

KES:
COUNT GPIO.0, 4000, X      ' Anahtardan 4 sn. İçinde Değer Oku.
KES2:
IF x = 0 AND GPIO.0 = 0 THEN GOTO BASLA
IF X = 2 THEN GOTO AYAR
GOTO KES2


AYAR:
'Ayar Kodları

DISABLE
KESME:
LOW ROLE
INTCON.1=0
RESUME KES

END

trajan

Neden count komutuna GPIO.0 yazdınız derseniz devrede butonu 0. pine de bağladım aynı anda, acaba kesme yapan butonu count okumazmı diye ama o da kar etmedi.

ete

#2
Öncelikle programdaki hataları yada eksiklikleri dile getirelim.
1. ANSEL      =%01110010  değerini vererek GPIO.1 pinini analog giriş olarak seçmişsin ama programda buna ait hiç bir komut yok.

2. 12F683 de INT bacağı (Yani RB0 kesme bacağı) GPIO.2 pinidir. Bu bacaktan giriş yapıp kesme yaratacak isen öncelike bu bacak Giriş olarak ayarlanmalıdır. Programda buna ait bilgi göremedim ben. Bu nedenle kesme çalışmaz. Ya INPUT GPIO.2
Yada TRISIO.2=1 demen gerekir idi.

3. ROLE CON 5 şeklindeki komut ROLE isimli değişkene sabit 5 değerini verir. Bu ROLE=5 ile aynı komuttur tek farkı CON kullandığın zaman 5 sayısını değiştiremezsin. CON (CONSTANT yani SABIT in kısaltılmışıdır). Bu durumda senin amaçladığın GPIO.2 pinini RoLE olarak atama işlemi başarısız olmuş demektir. Bunun Yolu SYMBOL ROLE=GPIO.2 şeklinde atamadır. Ancak röle adının bu INT bacağına verilmemesi gerektiğini düşünüyorum. Buradan hem giriş bekleyip hemde oraya röle bağlamak anlamsız olurdu değilmi. Röle başka bir bacakta çalışmalı bana kalırsa.

4.BASLA etiketinden sonra yer alan ENABLE komutunun orada işlevsel bir görevi yok maalesef. Bu komut kesme alt programı sonuna eklenmesi gerekirdi. Görevi ise DISABLE ile pasif hale getirilen kesme oluşturma işlemini kesmeden çıkmadan önce yeniden aktive etmektir. Senin programda bu işlem yarım kalmış olacak idi çalışsaydı tabiiki.

5. Kesme işlemi kesme oluşturan ve INTCON registeri ile aktive edilmiş bir kesme sebebi ile oluşturulan bir işlemdir. Programı kesme etiketine veya onun bir öncesine yollayarak kesme fonksiyonu çalıştırılamaz. Buşekilde program hataya girer.
Sen Goto Ayar diyerek programı kesme öncesi alt programa yollamışın. Oraya not düşmüşsün ayar kodları diye ama o kodların sonunda bir GOTO varmı yokmu belli değil maalesef. Şayet yok ise ayar kodlarından sonra program kesme etiketine gelecek demektir. Bu ise stack taşması yaratacak ve sonunda o program kilitlenecektir.

6. Kesme oluştuğu zaman işlemci o anda işleiği komut satırını (ASM olarak) hemen Stack içine atar ve Kesme etiketine atlar.
Kesme içindeki işini bitirdikten sonra RESUME - ENABLE komutlarını görür görmez Stack içinden geldiği adresi geri alır ve aynı adrese dönüş yapar. RESUME KES komutu ile sen programı geldiği yere değilde sabit bir adrese yollamaya zorluyorsun. Bu komut bir müddet sonra stack taşması yaratır. Zira stack içine atılan geliş adresi alınmadan program KES etiketine gitmeye zorlanmış olur. Bu şekilde bir yöntem kullanacak isen kesme kullanmaya gerek ok zaten. Kesme nin amacı ne zaman nerede INT pini aktif olacak belli olmadığı içindir. Dolayısıyla ne yapılacak ise otomatik yapılıp otomatik gelinen yere dönülmesi daha mantıklıdır. İşin bu kısmınıda düzeltmen gerekir.

7. COUNT komutu kullanarak programı orada 4 sn müddetle bloke etmiş oluyorsun.Bu arada başka işlerde yapılıyor ise onları kaçırmış olacaksın bunun farkındasın değilmi. Topu tıppu sayacağın 2 giriş ise bunu kesme ile saydırmak daha akıllıca olurdu. Zira kesme içinde yalnızca roleyi reset ediyorsunki buda anlamsız. Programda mantık hatası var anlayacağın.

Tespitlerim bunlar. Şimdi nasıl olmalı idi dersen;
INT pini giriş yapılıp kesmeye bağlanmalı.

Programın kesme haricindeki kısmı 500 ms lik TMR1 sayacı altında çalışmalı ve bu çalışma INT kesmesi oluştuğunda TMR1 sayacıda aktif edilmeli ve 4000ms lik sayma işlemi başlatılmalı.  TMR1 sayacı 500  ms lik dilimleri saymalı ve dilim sona erdiğinde SAY=SAY+1 yapılıp 8 adet dilim sayılmışmı bakılmalıdır. Sayılmış ise INT kesmesi sayacı değerine (KES) bakılıp 2 ise program ayar kısmına gönderilmeli değil ise registerler sıfırlanıp aynı işlem tekrar başlatılmalıdır.
Kesme kısmında KES=KES+1 şeklinde kesme sayılmalı ve RESUME ENABLE ile çıkılmalıdır.
Söyleyeceklerim bunlar.
Ete


trajan

Hocam İlgilendiğiniz için teşekkür ederim. Aslında pic konusunda biraz acemiyim. Genelde .Net teknolojileri geliştiriyorum.
Sizden rica etsem  bir örnek verebilirmisiniz? Program aşamaları:
1. Ldr den gelen ışık bilgileri okunacak. Karanlıksa Işık yakılacak, aydınlıksa ışık sönecek (Röle Bunun için)
2. Işık açık veya kapalıyken butona basılırsa veya basılı tutulursa ışık direk kapanacak.
3. Eğer Işık açık veya kapalıyken butona 3 kez basılıp bırakılırsa program ayar bölümüne gidecek.

esas yapmak istediğim bu. Önce kesme kullanmadan denedim gecikmeler oluyor. O yüzden kesme ile yapmaya karar verdim. Fakat dediğiniz gibi taşmalar oluyor muhtemelen çalıştıramadım. Kısacası kesme oluştuğunda röle tetiklemesini direk kesmeli aynı butondan 2 basış daha algılarsa ayar bölümüne gitmeli yapmak istediğim tam olarak bu. İlginiz İçin Teşekkür Ederim.

ete

Bazı konulara açıklık getirmek gerek. Ldr ışığı yaktı diyelim butona basınca ışık sönecek ama ldr ışığı tekrar yakmaya çalışacaktır. Buton ışığı söndürmüş ise ldr onu yakamamalı. Ama bu durumda ışık tekrardan nasıl yanacak. Bunlar işin detayları ama bence önemli noktalar.
Etw

trajan

Hocam;
* Pic ldr den gelen değeri okuyacak hassasiyet değişkeniyle karşılaştırıp geceyse  lambayı yakacak gündüzse yakmayacak veya söndürecek bu ana programımız. Burası sürekli çalışacak.
* Eğer butona 1 kez basılır bırakılırsa (Kesme) lambayı söndürecek ve ana programa dönecek. (Geceyse Lamba Tekrar Yanar.)
* Eğer butona basılı tutulursa buton bırakılmadığı sürece gündüzde olsa gece de olsa lamba sönük kalacak, buton bırakıldığında tekrar ana programa dönecek. (Geceyse Lamba Tekrar Yanar.)
* Eğer butona herhangi bir zamanda 3 kez basılır bırakılırsa program Ayar bölümüne gidecek.

Sanırım daha ayrıntılı oldu   

trajan

kesme ile yapsak ayar bölümüne gönderemiyoruz çünkü her kesme de resume ile ana programa dönüyor. O zaman butona 3 kez basıldığını kontrol edemiyoruz butona her basıldığında kesme oluşuyor. İşin içinden çıkamadım :)

ete

Kesme kısmı butona basılma sayısını sayar. Ana program bölümü sayılan adedi kontrol eder.
Ete

trajan

#8
Deneme amaçlı aşağıdaki programı yazdım fakat bazen 3. kesmede bazen 2. kesmede nadiren 1. kesmede ayara gidiyor anlamadım.

@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_ON

OSCCON     =%01100001
CMCON0     = 7
ANSEL      =%01110000
K VAR BYTE
K=0

on interrupt goto KES               ' Kesme Olduğunda KES'e git

OPTION_REG =%11000000               ' Pullup Kapalı, Yükselen Kenar Kesme
INTCON     =%10010000               ' Kesmeler Açık, GPIO.2 Kesmesi Aktif

OUTPUT GPIO.5
INPUT  GPIO.2

BASLA:
IF K = 3 THEN GOTO AYAR
IF GPIO.2 = 0 THEN
GPIO.5 = 1
ELSE
GPIO.5 = 0
ENDIF
GOTO BASLA

DISABLE
KES:
K = K + 1
GPIO.5= 0
INTCON.1 = 0
RESUME
ENABLE

AYAR:
K = 0
PAUSE 5000
GOTO BASLA

END


ete

Bana kalırsa program doğru çalışıyor ancak sen izleyemiyorsun.
Aşağıdaki örneği dene ve gör istersen,

Ete

@ __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
DEFINE OSC 4
OSCCON=%01100001
CMCON0 = 7
'ADCON0=%10000000
ANSEL=0
WPU=%00000100
OPTION_REG=%00000000
GPIO=0
TRISIO=%00000100
K VAR BYTE 56
pause 300

INTCON=%10010000
on interrupt goto KESME               ' Kesme Olduğunda KES'e git

BASLA:
IF K = 3 THEN GOTO AYAR


GOTO BASLA

DISABLE
KESME:
K = K + 1
GPIO.5=1
PAUSE 50
INTCON.1 = 0

RESUME
ENABLE

AYAR:
K = 0
'PAUSE 1000
GPIO.5=0
GOTO BASLA

END

trajan

#10
Hocam; Direk Pic'e attım çalışmadı :(
Tepkisi butona basınca led yanıyor, tekrar basınca led sönüyor. Entegrede bi problem olabilir mi acaba? üstteki yazdığım programda normalde çalışması lazım

trajan

#11
Hocam K değişkenini program başında 0 ladım ve kesmedeki Pause süresini arttırınca düzeldi çalıştı. İlginiz ve alakanız için çok teşekkür ederim.

Powered by EzPortal