16f88 işlemci program kilitlenmesi !

Başlatan sinasos, 21 Mart 2017, 12:48:14

sinasos

merhaba arkadaşlar,
ısı ve nem kontrolü için sağdan soldan bulduğum bilgileri birleştirerek hazırladığım programda zaman zaman kilitlenmeler oluyor. örneğin menü tuşuna basınca veya birkaç saat sistem çalışınca kilitleniyor. acaba hangi kısmı atlıyorum ve hatamı göremiyorum bu konuda özellikle ete hocamın ve bilen arkadaşların yardımlarını bekliyorum.
teşekkürler.

not : dht22 sensörü için bulabildiğim düzgün çalışan bir program olmadığı bulduğum kadarını ekledim. belki orada da hata olabilir bilen dostlara sesleniyorum. :)



Include "modedefs.bas"         
@ DEVICE pic16F88
@ DEVICE pic16F88, WDT_OFF
@ DEVICE pic16F88, PWRT_ON
@ DEVICE pic16F88, BOD_OFF
@ DEVICE pic16F88, LVP_OFF
@ DEVICE pic16F88, PROTECT_OFF
@ DEVICE pic16F88, MCLR_OFF
@ DEVICE pic16F88, INTRC_OSC_NOCLKOUT

DEFINE OSC 4
'-------------------------- LCD Tanımlama --------------------
DEFINE LCD_DREG PORTB 'LCD data bacakları hangi porta bağlı?
DEFINE LCD_DBIT 4 'LCD data bacakları hangi bitten başlıyor?
DEFINE LCD_RSREG PORTB 'LCD RS Bacağı Hangi Porta bağlı ?
DEFINE LCD_RSBIT 1 'LCD RS bacağı Hangi Bite bağlı ?
define lcd_RWREG    PORTB
define LC_RWBIT     2
DEFINE LCD_EREG PORTB 'LCD Enable Bacağı Hangi Porta bağlı?
DEFINE LCD_EBIT 3 'LCD Enable Bacağı Hangi bite bağlı ?
DEFINE LCD_BITS 4 'LCD 4 bit mi yoksa 8 bit olarak bağlı?
DEFINE LCD_LINES 2 'LCD Kaç sıra yazabiliyor
OPTION_REG.7=1

TRISA=0  'A portu çıkış olarak ayarlandı.
TRISB=0  'B portu çıkış olarak ayarlandı.
PORTA=0
OSCCON=%01101100'4 mhz osilatör
ADCON1 = %10000000
ANSEL=0

nem     var word             '16-bit var to store humidity
isi     var word             '16-bit var to store temperature
x           var byte             'general var
pulse       var byte [41]        'store pulse var
p           var bit  [41]         'store pulse var

dht_port    var PORTA.0
y       var byte
DERECE  CON 223     ' ° işareti

isim    var byte
isim1   var byte
nemim   var byte
nemim1  var byte

AYAR    VAR BYTE
syc     var byte
AYR     VAR BIT
tus     var bit
tus1    var bit
n       var bit
m       var bit

a       var byte
b       var byte

USTISI  VAR BYTE
ALTISI  VAR BYTE
USTNEM  VAR BYTE
ALTNEM  VAR BYTE

symbol yukari=portA.4
symbol asagi=portA.2
symbol MENU=portA.3
symbol isirole=porta.7
symbol nemrole=porta.6
LOW YUKARI:LOW ASAGI:LOW MENU
clear
high dht_port
y=0

read 0, USTISI
read 1, ALTISI
read 2, USTNEM
read 3, ALTNEM
read 4, A
read 5, B

LOW isirole:LOW NEMROLE
'*********************************** ANA PROGRAM *******************************
basla:
gosub SENSOROKU
gosub GOSTER
GOSUB SINIRBAK
ana:
    if menu=1 then goto konum
goto basla
'******************************** ANA PROGRAM SONU *****************************

'****************************** YAN PROGRAMLAR *********************************
SINIRBAK:
if ustisi<=isim and a<=isim1 then low isirole :n=0
if altisi>=isim and b>=isim1 then high isirole:n=1
if ustnem<=nemim then LOW nemrole:m=0
if altnem>=nemim then HIGH nemrole:m=1

return
'*******************************************************************************
'SENSORYOK:
'           LCDOUT $FE,$02,"   SENSOR YOK   "
'           LCDOUT $FE,$C0," LUTFEN TAKINIZ " 
'           PAUSE 1000               
'           RETURN

GOSTER:
    LCDOUT  $FE,1
    LCDOUT  $FE,$80," NEM : ",dec2 nemim,".",dec1 nemim1," %","  ", dec m
    LCDOUT  $FE,$C0," ISI : ",dec2 isim,".",dec1 isim1,derece,"C","  ",dec n
    PAUSE   100
RETURN

AYARLANDI:
       IF MENU=1 then AYARLANDI
       gosub temizle
       LCDOUT $FE,$80, "    AYARLAR     "
       LCDOUT $FE,$C0, "   KAYDEDiLDi   "
       AYAR=1
       SYC=0
       PAUSE 500
       
        GOSUB TEMIZLE
        goto BASLA   

TEMIZLE:
        lcdout $fe,1
RETURN
'******************************* MENÜ PROĞRAMI *********************************
konum:
WHILE MENU=1:WEND
GOSUB TEMIZLE
SYC=0
AYARLAR:
IF YUKARI=1 THEN
WHILE YUKARI=1:WEND
SYC=SYC+1
  IF SYC=5 THEN SYC=0
ENDIF

IF ASAGI=1 THEN
WHILE ASAGI=1:WEND
SYC=SYC-1
  IF SYC=255 THEN SYC=4
ENDIF
GOSUB DURUM
GOTO AYARLAR

DURUM:
SELECT CASE SYC
CASE 0         
LCDOUT $FE,$80, " UST ISI AYARI  "
LCDOUT $FE,$C0, " ISI : ",dec2 USTISI,".",dec1 a,derece," C     "
IF MENU=1 then
WHILE MENU=1:WEND
GOTO bir
ENDIF
CASE 1         
LCDOUT $FE,$80, " ALT ISI AYARI  "
LCDOUT $FE,$C0, " ISI : ",dec2 ALTISI,".",dec1 b,derece," C     "
IF MENU=1 then
WHILE MENU=1:WEND
GOTO iki
ENDIF
CASE 2         
LCDOUT $FE,$80, " UST NEM AYARI "
LCDOUT $FE,$C0, " NEM : ",dec USTNEM ," %      "
IF MENU=1 then
WHILE MENU=1:WEND
GOTO uc
ENDIF
CASE 3 
LCDOUT $FE,$80,    " ALT NEM AYARI  "
LCDOUT $FE,$C0,    " NEM : ",dec ALTNEM ," %      "
IF MENU=1 then
WHILE MENU=1:WEND
GOTO dort
ENDIF
CASE 4
lcdout $fe,$80,"    MENUDEN     "
LCDOUT $FE,$C0,"     CIKIS      "
IF MENU=1 THEN AYARLANDI
END SELECT
RETURN
'********************************* menü kısmı *****************************************
BIR:   
GOSUB TEMIZLE:read 0, USTISI:read 4, a       
SET1: 
            LCDOUT $FE,$80, " UST ISI AYARI  "
            LCDOUT $FE,$C0, "=>ISI : ",dec USTISI,".",dec1 a,derece," C     "

           IF YUKARI=1 then
              A=A+1
                IF A=10 THEN
                A=0:USTISI=USTISI+1
                ENDIF
              IF USTISI=100 THEN USTISI=0
              PAUSE 100
           ENDIF
           IF ASAGI=1 then
              A=A-1
                IF A=255 then
                A=9:USTISI=USTISI-1
                ENDIF
              IF USTISI=255 THEN USTISI=99
              PAUSE 100
           ENDIF
               
         IF MENU=1 THEN
         WRITE 0,USTISI:PAUSE 2
         WRITE 4,A:PAUSE 2
         GOTO konum
         ENDIF

GOTO SET1

IKI:   
GOSUB TEMIZLE:read 1, ALTISI :read 5, B
set2:
           LCDOUT $FE,$80, " ALT ISI AYARI  "
           LCDOUT $FE,$C0, "=>ISI : ",dec ALTISI,".",dec1 b,derece," C     "

           IF YUKARI=1 then
              b=b+1
                IF b=10 THEN
                b=0:ALTISI=ALTISI+1
                ENDIF
              IF ALTISI=50 THEN ALTISI=0
              PAUSE 100
           ENDIF
           IF ASAGI=1 then
              b=b-1
                IF b=255 then
                b=9:ALTISI=ALTISI-1
                ENDIF
              IF ALTISI=255 THEN ALTISI=99
              PAUSE 100
           ENDIF
               
         IF MENU=1 THEN
         WRITE 1, ALTISI:PAUSE 2
         write 5, b:pause 1
         GOTO konum
         ENDIF

GOTO SET2       

UC:     
GOSUB TEMIZLE:read 2, USTNEM
set3:
            LCDOUT $FE,$80, " UST NEM AYARI  "
            LCDOUT $FE,$C0, "=>NEM : ",dec USTNEM ," %      "
            IF YUKARI=1 then
                USTNEM=USTNEM+1
                ENDIF
              IF USTNEM=100 THEN USTNEM=0
              PAUSE 100
           IF ASAGI=1 then
                USTNEM=USTNEM-1
                ENDIF
              IF USTNEM=255 THEN USTNEM=1
              PAUSE 100
         IF MENU=1 THEN
         WRITE 2, USTNEM:PAUSE 2
         GOTO konum
         ENDIF
GOTO SET3       

DORT:   
GOSUB TEMIZLE:read 3, ALTNEM
SET4:       
            LCDOUT $FE,$80,    " ALT NEM AYARI  "
            LCDOUT $FE,$C0,    "=>NEM : ",dec ALTNEM ," %      "
            IF YUKARI=1 then
                ALTNEM=ALTNEM+1
                ENDIF
              IF ALTNEM=90 THEN ALTNEM=1
              PAUSE 100
           IF ASAGI=1 then
                ALTNEM=ALTNEM-1
                ENDIF
              IF ALTNEM=255 THEN ALTNEM=1
              PAUSE 100
         IF MENU=1 THEN
         WRITE 3, ALTNEM:PAUSE 2
         GOTO konum
         ENDIF
GOTO SET4

dokuz:return

goto ana
'********************************* SENSÖR OKUMA *******************************

SENSOROKU:
;---- check_DHT22 ----
;-== send StartSignal ==-
TRISa.0 = 0                      'Data port is output
high dht_port
pauseus 10                       'send 10uS high pulse
low dht_port                     
pause 1                          'send 1mS high pulse
high dht_port

;-== wait response from Sensor ==-
TRISa.0 = 1                      'Data port is input
while dht_port=1:wend            'wait for low from DHT
while dht_port=0:wend            'wait for high FROM DHT
;-== Grab 40bits data from DHT22 ==-
pulsin DHT_port,1,pulse(1)        'Humidity HighBit data
pulsin DHT_port,1,pulse(2)
pulsin DHT_port,1,pulse(3)
pulsin DHT_port,1,pulse(4)
pulsin DHT_port,1,pulse(5)
pulsin DHT_port,1,pulse(6)
pulsin DHT_port,1,pulse(7)
pulsin DHT_port,1,pulse(8)
pulsin DHT_port,1,pulse(9)
pulsin DHT_port,1,pulse(10)
pulsin DHT_port,1,pulse(11)
pulsin DHT_port,1,pulse(12)
pulsin DHT_port,1,pulse(13)
pulsin DHT_port,1,pulse(14)
pulsin DHT_port,1,pulse(15)
pulsin DHT_port,1,pulse(16)      'Humidity LowBit data
pulsin DHT_port,1,pulse(17)      'Temperature HighBit data (1 means below 0 degree!)
pulsin DHT_port,1,pulse(18)
pulsin DHT_port,1,pulse(19)
pulsin DHT_port,1,pulse(20)
pulsin DHT_port,1,pulse(21)
pulsin DHT_port,1,pulse(22)
pulsin DHT_port,1,pulse(23)
pulsin DHT_port,1,pulse(24)
pulsin DHT_port,1,pulse(25)
pulsin DHT_port,1,pulse(26)
pulsin DHT_port,1,pulse(27)
pulsin DHT_port,1,pulse(28)
pulsin DHT_port,1,pulse(29)
pulsin DHT_port,1,pulse(30)
pulsin DHT_port,1,pulse(31)
pulsin DHT_port,1,pulse(32) 'Temperature LowBit data
;-== convert to '0' & '1' ==-
for x=1 to 33
if pulse(x)>=2 and pulse(x)<=4 then p(x)=0 'if pulsewidth between 20 and 40uS then read as '0'
if pulse(x)>=6 and pulse(x)<=8 then p(x)=1 'if pulsewidth between 60 and 80uS then read as '1'
next x
;-== convert bin to dec ==-
nem=32768*p(1)+16384*p(2)+8192*p(3)+4096*p(4)+2048*p(5)+1024*p(6)+512*p(7)+256*p(8)+128*p(9)+64*p(10)+32*p(11)+16*p(12)+8*p(13)+4*p(14)+2*p(15)+1*p(16)
isi=16384*p(18)+8192*p(19)+4096*p(20)+2048*p(21)+1024*p(22)+512*p(23)+256*p(24)+128*p(25)+64*p(26)+32*p(27)+16*p(28)+8*p(29)+4*p(30)+2*p(31)+1*p(32)

nemim=nem/11:nemim1=nem//11
isim=isi/10:isim1=isi//10

return

END

ete

Program kilitlenmesinin ana sebebi Stack Taşmasıdır. Bilmeyenler olabilir diye stack taşması nedir onu anlatayım önce.
Stack denilen şey işlemci içinde yer alan bir ara hafızadır. Normal şartlarda bu hafızaya biz ulaşamıyoruz. Bu hafızaya genellikle GOSUB ile bir etikete gidileceği zaman işlemci ayrıldığı adresi hemen alıp Stack'a atar. Atar diyorum şuraya yaz demez içine atar. Stack da temel kaide şudur en son gelen ilk çıkar. Bu şu demektir. Stack' a atılan adresin öncelikle oradan alınıp stack'in bir nevi boşaltılması gerekir. Doyayısıyla program GOSUB dan sonra mutlaka bir RETURN görmelidir ki Hemen gidip stack'a atılan adresi geri alıp geldiği yere geri döner. Stack işlemcinin tipine göre 15-35 hafıza adresinden oluşur. Bu nedenle programlarda çok fazla iç içe GOSUB kullanılmamalıdır. Bir etikete gosub ile gittin. Oradan bir başka yere gittin (stack'e 2 adres atılmış oldu) oradan bir başka yere gosub ile gittim stack'e 3 adres atılmış oldu. Bu atılan adreslerin sayısı 5-6 yı geçtiği zaman şayet stack da adres atılacak hafıza kalmamış ise program ne yapacağını şaşırır ve kilitlenir.
Diğer bir kilitlenme sebebi ise çok fazla yapılan bir hata olduğu için söylüyorum, bir etikete gosub ile gidip oradan Goto ile dönmek olur. Bu işi program bir kaç defa tekrarladımı bir stack taşması meydana gelir ve program nereye gideceğini bulamadığı için kilitlenir.
Şimdi senin programa bir bakalım. Kilitlenmeden bahsedince hemen Gosub komutlarına baktım. En başta Gosub Sensoroku yer alıyor. Orada sorun yok bir yere dallanmadan alt programın altında yer alan RETURN komutunu görüp program geri dönüyor.
Ardından gelen Gosub Goster kısmına baktım. Göster etiketinde de sorun yok oraya gidiyor ve Return görerek geri dönüyor.
Gosub SINIRBAK da da sorun gözükmüyor. Ama altta yer alan IF Menu=1 then Goto Konum kısmında sorun var.
Menü tuşuna basınca program Goto ile Konum etiketine geliyor.  Buradan GOSUB ile DURUM isimli etikete gidiyor. BU etiketten mutlaka RETURN ile dönmeli. Ama dönemiyor. Burada menu tuluna basmış isem Goto BIR komutu ile BIR isimli etikete gidiyor. Konum etiketinden Durum etiketine Gosub ile gitmiş olduğu için bir adet RETURN alacağı var stack in. Tekrar KONUM isimli etikete dönebilmesi için. Şimdi BIR etiketine geldik. Bakalım ne oluyor orada, Hala Menü tuşuna basıyor isem , Ustısı ve a değerlerini eproma kayıt ettikten sonra, GOTO KONUM ile KONUM etiketine geliyor. Halbuki oradan GOSUB Durum isimli etikete gitmiş idik.  Bu stack taşması oluşturacak bir hatadır.
Aynı sorun GOTO IKI ile IKI isimli etikete ve oradan dönüşte karşılaşılan GOTO KONUM komut satırı içinde geçerlidir.
Sonuç olarak programda stack taşması sorunu var. Menü sisteminde ipin ucunu kaçırmış gözüküyorsun. Bence Menü kısmını yeniden tasarlamanda yarar var.

Ete

sinasos

Ete hocam alakanıza çok teşekkür ederim. çok naziksiniz ! Stabil çalışan sorun yaratmayan bir menü algoritması oluşturmak benim için biraz sıkıntı olacak sebebine gelince DHT 22 sensörü okumayı yabancı bir kaynaktan buldum  o da önce 16f628a içerisine sığmadığından sistemi 16f88'e göre yeniden yapmak zorunda kaldım. hazırladığım proğram bile 16f88'e ucu ucuna sığdı. hareket alanı da dolayısıyla çok kısıtlandı. şu anki durumda ucu ucuna sığıyor. kısa bir şekilde olabilecek örnek bir menü proğramı ve DHT 22 sensörü kullanımı konusunda daha kısa bir kod dizisi biliyorsanız yardımcı olabilirmisiniz rica etsem.
teşekkürler.

ete

DHT22 okuma kısmıda pek hoşuma gitmedi. Bu sitede DHT22 ile ilgili çalışma yapmış idik.
Aratırsan bulabilirsin.
Aslını denemediğim ama isisde sorunsuz çalışan program ve devreyi aşağıda veriyorum. Deneyebilirsin.
Sorun olursa aşağıdaki linktekileride okursan bir sonuca ulaşabilirsin belki.

http://etepic.com/index.php/topic,3451.msg32694.html#msg32694

ete

sinasos

teşekkürler hocam okuma yapıyor, ancak ekrana sensör hatası yazıyor. hata kısmını kapatınca nem ve ısı yı gösteriyor. ancak sensörün takılı olup olmadığını anlamıyor.
birde önereceğiniz menü algoritması varmı sorunsuz çalışan ?
teşekkürler.

Powered by EzPortal