çalışmayan program

Başlatan efkan, 28 Haziran 2020, 09:25:02

efkan

Merhabalar.
Benim bir sorunum var.Sorunum şu ;aşagıda verdigim kodla hazırlanmış devrem çalışıyordu fakat bir süre sonra hiç çalışmaz oldu.Hiç bir tepki vermiyor.Amatörüm bu işte onuda belirtim.

LIST P=16F84
INCLUDE "P16F84.INC"
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
SAYAC1 EQU 0X0C   ;sayac1 adresini belirle
ORG 0X00          ;0x00 adresinden başla
GOTO BASLA        ;basla etiketine git
ORG 0X04          ;kesme oluşursa 0x04 adresine git
GOTO KESME
BASLA
BSF STATUS,5            ;bank 1'e git
BSF OPTION_REG,INTEDG   ;yükselen kenarda port 0'a kesme uygula
CLRF TRISA              ;port a yi çıkış yap
MOVLW B'00000001'       ;portb 0. bitini giriş,gerisini çıkış yap
MOVWF TRISB
BCF STATUS,5            ;bank 0'a geç
BSF INTCON,GIE          ;tüm kesmelere izin ver
BSF INTCON,INTE         ;portb 0. biti harici kesmesine izin ver
CLRF PORTA              ;porta yı temizle (0 yap)
CLRF PORTB

KESME
BCF INTCON,INTF         ;rb0 kesme yok
BTFSS PORTB,0           ;rb0'a bak 1 mi?
GOTO $ -1               ;hayır tekrar kontrol et
CALL GECIKME            ;evet gecıkmeye dallan
BSF PORTA,0             ;ra0 1 yap
BTFSC PORTB,0           ;rb0 0 mı kontrol et
GOTO $ -1               ;hayır tekrar kontrol et
BCF PORTA,0             ;evet ra0'ı 0 yap
GECIKME                 ;gecıkme alt programı
MOVLW 0XFF              ;sayac1'i 255 yap
MOVWF SAYAC1
DONG
DECFSZ SAYAC1,F         ;sayac1 den 1 çıkar sonuç 0 mı
GOTO DONG               ;hayır tekrar 1 çıkar
RETURN                  ;evet bsf porta ya git
RETFIE
DONGU
GOTO DONGU
END

Sorun nerde belirtirseniz sevinirim.

ete

ASM den çok iyi anlamam ama bazı sorunları görecek kadarda anlarım.
Senin programında bir mantık hatası var ve bu hata sanırım stack taşmasına sebep oluyor ve bir müddet sonra programın kilitleniyor.
Program üzerinde sorunun yeri ve nasıl düzelteceğimizi aşağıda açıklıyorum.
Önce sorunu açıklayalım. Kesme alt programında bir gecikme döngün var. Bu döngüye  CALL GECIKME  komut satırı ile ulaşıyorsun. Burada sorun yok. Program GECIKME etiketine gidiyor ve orada istenilen gecikmeyi yaratıp RETURN komutu ile dönüyor. Burada da sorun yok. Sorun döndükten sonra başlıyor. Zira program gecikme alt prohgramından döndükten sonra bir alt satırdan devam ediyor. Orada ne var bakalım;
BSF PORTA,0             ;ra0 1 yap
BTFSC PORTB,0           ;rb0 0 mı kontrol et
GOTO $ -1               ;hayır tekrar kontrol et
BCF PORTA,0             ;evet ra0'ı 0 yap
GECIKME   
olan satırların sorunu anlayacak kadar olanlarını aldım.
PORTA.0 biti SET ediliyor
PORTB.0 =0 mı kontrol ediliyor Değil ise tekrar aynı satıra gelinip tekrar kontrol ediliyor. PORTB.0=0 ise PORTA.0=0 yapılıp zurnanın zurt dediği yere geliyor program.
Yani tekrar GECİKME alt programına giriyor. Burası öyle bir yerki yanlızca CALL yada GOSUB ile gelinmesi gereken bir yer çünki sonunda RETURN var. Buraya giren program tekrar gecikme işini yaratıp RETURN komutu ile karşı karşıya kalıyor ve gelirken stack den bir adres almadığı için şaşırıp nereye gideceğini bilemiyor ve muhtemelen burada kilitleniyor.
Sorun bu. Peki nasıl düzelteceğiz.  Program işini bitirdikten sonra GECIKME alt programına girmemeli ve geri dönerek KESME alt programından çıkmalı. Bu nedenle aşağıda RETURN komutundan sonra yer alan RETFIE komutu kesmeden çıkış komutudur. O komutun GECIKME etiketinden bir öncesinde yer alması gerekirdi. O halde program aslında şöyle olmalı idi.
KESME
BCF INTCON,INTF         ;rb0 kesme kapalı
BTFSS PORTB,0           ;rb0'a bak 1 mi?
GOTO $ -1               ;hayır tekrar kontrol et
CALL GECIKME            ;evet gecıkmeye dallan
BSF PORTA,0             ;ra0 1 yap
BTFSC PORTB,0           ;rb0 0 mı kontrol et
GOTO $ -1               ;hayır tekrar kontrol et
BCF PORTA,0             ;evet ra0'ı 0 yap
RETFIE
GECIKME                 ;gecıkme alt programı
MOVLW 0XFF              ;sayac1'i 255 yap
MOVWF SAYAC1
DONG
DECFSZ SAYAC1,F         ;sayac1 den 1 çıkar sonuç 0 mı
GOTO DONG               ;hayır tekrar 1 çıkar
RETURN                  ;evet bsf porta ya git

END

Bu değişikliği yapıp programı derle ve yeniden dene. Sorun düzelmiş olması gerekir.
Ete

efkan

Alıntı yapılan: ete - 28 Haziran 2020, 09:49:43ASM den çok iyi anlamam ama bazı sorunları görecek kadarda anlarım.
Senin programında bir mantık hatası var ve bu hata sanırım stack taşmasına sebep oluyor ve bir müddet sonra programın kilitleniyor.
Program üzerinde sorunun yeri ve nasıl düzelteceğimizi aşağıda açıklıyorum.
Önce sorunu açıklayalım. Kesme alt programında bir gecikme döngün var. Bu döngüye  CALL GECIKME  komut satırı ile ulaşıyorsun. Burada sorun yok. Program GECIKME etiketine gidiyor ve orada istenilen gecikmeyi yaratıp RETURN komutu ile dönüyor. Burada da sorun yok. Sorun döndükten sonra başlıyor. Zira program gecikme alt prohgramından döndükten sonra bir alt satırdan devam ediyor. Orada ne var bakalım;
BSF PORTA,0             ;ra0 1 yap
BTFSC PORTB,0           ;rb0 0 mı kontrol et
GOTO $ -1               ;hayır tekrar kontrol et
BCF PORTA,0             ;evet ra0'ı 0 yap
GECIKME   
olan satırların sorunu anlayacak kadar olanlarını aldım.
PORTA.0 biti SET ediliyor
PORTB.0 =0 mı kontrol ediliyor Değil ise tekrar aynı satıra gelinip tekrar kontrol ediliyor. PORTB.0=0 ise PORTA.0=0 yapılıp zurnanın zurt dediği yere geliyor program.
Yani tekrar GECİKME alt programına giriyor. Burası öyle bir yerki yanlızca CALL yada GOSUB ile gelinmesi gereken bir yer çünki sonunda RETURN var. Buraya giren program tekrar gecikme işini yaratıp RETURN komutu ile karşı karşıya kalıyor ve gelirken stack den bir adres almadığı için şaşırıp nereye gideceğini bilemiyor ve muhtemelen burada kilitleniyor.
Sorun bu. Peki nasıl düzelteceğiz.  Program işini bitirdikten sonra GECIKME alt programına girmemeli ve geri dönerek KESME alt programından çıkmalı. Bu nedenle aşağıda RETURN komutundan sonra yer alan RETFIE komutu kesmeden çıkış komutudur. O komutun GECIKME etiketinden bir öncesinde yer alması gerekirdi. O halde program aslında şöyle olmalı idi.
KESME
BCF INTCON,INTF         ;rb0 kesme kapalı
BTFSS PORTB,0           ;rb0'a bak 1 mi?
GOTO $ -1               ;hayır tekrar kontrol et
CALL GECIKME            ;evet gecıkmeye dallan
BSF PORTA,0             ;ra0 1 yap
BTFSC PORTB,0           ;rb0 0 mı kontrol et
GOTO $ -1               ;hayır tekrar kontrol et
BCF PORTA,0             ;evet ra0'ı 0 yap
RETFIE
GECIKME                 ;gecıkme alt programı
MOVLW 0XFF              ;sayac1'i 255 yap
MOVWF SAYAC1
DONG
DECFSZ SAYAC1,F         ;sayac1 den 1 çıkar sonuç 0 mı
GOTO DONG               ;hayır tekrar 1 çıkar
RETURN                  ;evet bsf porta ya git

END

Bu değişikliği yapıp programı derle ve yeniden dene. Sorun düzelmiş olması gerekir.
Ete


Öncelikle yardımınız için teşekkür ederim.Dediginizi yaptım ama yine çalışmıyor.Donanımsal bir hata mı var acaba?

ete

BU programın önceden çalışıyor olmasına inanmıyorum. Çok acemice yazılmış hataları var.
Başka bir sorun daha gördüm. Basla etiketinden sonra program yapacaklarını yapıyor ve başka bir komut satırı olmadığı için KESME etiketine geliyor ve oraya giriyor. Buda stack problemi yaratacak bir eksiklik. Aşağıdaki programı dene.
Ete


LIST P=16F84
INCLUDE "P16F84.INC"
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
SAYAC1 EQU 0X0C   ;sayac1 adresini belirle
ORG 0X00          ;0x00 adresinden başla
GOTO BASLA        ;basla etiketine git
ORG 0X04          ;kesme oluşursa 0x04 adresine git
GOTO KESME

BASLA
BSF STATUS,5            ;bank 1'e git
BSF OPTION_REG,INTEDG   ;yükselen kenarda port 0'a kesme uygula
CLRF TRISA              ;port a yi çıkış yap
MOVLW B'00000001'       ;portb 0. bitini giriş,gerisini çıkış yap
MOVWF TRISB
BCF STATUS,5            ;bank 0'a geç
BSF INTCON,GIE          ;tüm kesmelere izin ver
BSF INTCON,INTE         ;portb 0. biti harici kesmesine izin ver
CLRF PORTA              ;porta yı temizle (0 yap)
CLRF PORTB
goto DONGU

KESME
BCF INTCON,INTF         ;rb0 kesme yok
BTFSS PORTB,0           ;rb0'a bak 1 mi?
GOTO $ -1               ;hayır tekrar kontrol et
CALL GECIKME            ;evet gecıkmeye dallan
BSF PORTA,0             ;ra0 1 yap
BTFSC PORTB,0           ;rb0 0 mı kontrol et
GOTO $ -1               ;hayır tekrar kontrol et
BCF PORTA,0             ;evet ra0'ı 0 yap
RETFIE
GECIKME                 ;gecıkme alt programı
MOVLW 0XFF              ;sayac1'i 255 yap
MOVWF SAYAC1
DONG
DECFSZ SAYAC1,F         ;sayac1 den 1 çıkar sonuç 0 mı
GOTO DONG               ;hayır tekrar 1 çıkar
RETURN                  ;evet bsf porta ya git

DONGU
@ NOP
@ NOP
GOTO DONGU
END

ete

Aynı programı Basicde yazıp çalıştırdım. İlişikteki dosyada devre şeması program ve hx dosyası mevcut.
Öncelikle hex dosyasını alıp elindeki işlemciye yükle ve çalıştır bakalım çalışacakmı.
Böylece işlemciyi test etmiş olursun.

Daha sonra devre şemasına bak. Hem simulasyon hemde JPG dosyası olarak verdim. Sİmulasyonu açamaz isen jpg uzantılı dosyayı aç ve gerçek devrenle karşılaştır. Aynısı olmalı. Yanlızca kristal yerine rezonatör kullanıyorsan ki 3 bacaklıdır o zaman orta uç GND ye yandaki uçlar ise kristal bacaklarının bağlı olduğu pinlere bağlanacaktır.

Umarım çalıştırabilirsin.

Ete

efkan

Herşey için yine teşekkürler.Ben kesme kullanmadan ayrı kod hazırladım ve oldu.Çalışıyor program.Bahsettigim kodlar aşağıda


LIST P=16F84
INCLUDE "P16F84.INC"
__CONFIG _CP_OFF& _WDT_OFF& _XT_OSC& _PWRTE_ON
SAYAC1 EQU 0X0C
ORG 0X00
BASLA
BSF STATUS,5
CLRF TRISA
MOVLW B'00000010'
MOVWF TRISB
BCF STATUS,5
CLRF PORTA
CLRF PORTB
GIT
BTFSS PORTB,1
GOTO GIT
CALL GECIKME
BSF PORTA,0
GITC
BTFSC PORTB,1
GOTO GITC
CALL GECIKME
BCF PORTA,0
GECIKME
MOVLW 0XFF
MOVWF SAYAC1
DONG
DECFSZ SAYAC1,F
GOTO DONG
RETURN
DONGU
GOTO DONGU
END

efkan

Aynı sorun bu son programda da oldu.Uzun süre mikroişlemci enerjide kalınca  belli bir süre sonunda  mikroişlemci sanki doyuma ulaşıyor gibi davranıyor ve ra0 bitindeki led yanmıyor.Neden kaynaklanır bu?

ete

#7
Hatalarından ders almıyorsun. Sorun burada. Sana yaptığın hataları detaylı açıkladım ve çözüm önerdim. Sen yeniden program yazdın aynı hatayı orda da tekrarladın. Tekrar açıklıyorum bu son programdaki hatanı. Hatanın olduğu bölüme bakacak olursak;
GIT
BTFSS PORTB,1
GOTO GIT
CALL GECIKME
BSF PORTA,0
GITC
BTFSC PORTB,1
GOTO GITC
CALL GECIKME
BCF PORTA,0

GECIKME
MOVLW 0XFF
MOVWF SAYAC1
DONG
DECFSZ SAYAC1,F
GOTO DONG
RETURN
GIT etiketinden itibaren program kendisinden istenilenleri yapıyor. GITC etiketine geliyor.
Burada PORTB.0 pininin tekrar LOW olup olmadığına bakılıyor ve LOW oluncaya kadar (Buton bırakılıncaya kadar) program oradan ayrılmıyor. Sonunda PORTB.1=0 olduğunda Program tekrar GECIKME alt programına gidip yeniden bir gecikme sağlıyor ve geri dönüp BCF PORTA,0 komutu ile PORTA.0 bitini sıfırlıyor. İşte sorun burada başlıyor. PORTA.0=0 yapıldıktan sonra program bir sonraki satıra geçiyor. Orada ne var dersin?????  Tabiiki GECIKME alt programı.
GECIKME alt programına daha öncede söylediğim gibi yanlızca CALL veya GOSUB ile gidilmesi gerekir. Çünki sonunda RETURN bulunuyor. Sen ise aynı hatayı tekrarlayarak direk GECIKME alt programına giriyorsun. Sonunda RETURN var ama program stack dan bir geliş adresi almadan buraya geldiği için yine şaşırıyor ve sonunda şişip kilitleniuyor.
GECIKME etiketinden bir öncesine GOTO GIT şeklinde komut yerleştirmen gerekiyor. Böylece programın aynı şeyleri yeni baştan tekrarlayacak hale gelir ve direk GECIKME alt programına dalmamış olur.
Diğer kesme olan programda çalışır bunu unutma.

Muhtemelen CALL GECIKME - RETURN mekanizmasının nasıl çalıştığını bilmiyorsun. Onuda açıklayayım.
Program CALL GECIKME komutunu görünce bulunduğu adres değerini Stack'a yazar ve doğruca GECIKME etiketine gider. Orada gecikmeyi yaratıp RETURN komutunu görünce Stack dan geldği adresi alıp o adrese (geldiği yere) geri döner.
Sende ne oluyor peki, program GECIKME alt programına zorunlu giriş yapıyor hemde CALL GECIKME komutu olmadan. Orada gecikmeyi yaratıp RETURN komutunu görüyor ve Stack dan adres alıp geri dönmeye çalışıyor. Çünki sistem böyle çalışıyor. Alabileceği bir adres olmayınca da ne yaptığını bilemiyorum ama en son kayıt edilmiş bir adresi alıp gidiyor olabilir. Oda muhtemelen yanlış bir adres oluyordur ve sonunda sistem bir noktada kilitleniyordur.
 

Ete

Powered by EzPortal