Programlanabilir Kontrol Devresi

Başlatan oguztkn, 07 Aralık 2018, 04:15:48

oguztkn

Öncelikle Merhaba,

Bir kontrol kartı tasarladım ve programlaması ile uğraşmaktayım. Menü kısmını tamamlayabilirsem ana program akışına döneceğim. Program şimdilik istediğim şekilde gidiyor en azından menü kısmı ama programda 16 adet programlanabilen alt programcık olacak. Yani ana döngü bu programların eproma yazdığı verilere göre arka arkaya çalışacak. 4x20 lcd de çalışıyorum menu de ekran içinde imleci hareket ettirebiliyorum ama sanki bunu çok zor yoldan yapıyorum gibi geldi. Daha kolay bir yöntemi mutlaka vardır ama ben göremiyorum şuanlık, kesmeleri bu kısımda kullanmak istemedim çünkü ana programda kesmelere ihtiyacım olacak ve girişten gelicek bilgileri kaçırmaması için o kısmı olabildiğince sade tutmaya çalışacağım. Program ve şemayı ekliyorum menuyu nasıl yapmak daha mantıklı olur fikir verebilirmisiniz acaba ?

Şimdiden Teşekkür Ederim....

DEFINE LCD_DREG		PORTD
DEFINE LCD_DBIT 4
DEFINE LCD_EREG PORTD
DEFINE LCD_EBIT 0
DEFINE LCD_RWREG    PORTD
DEFINE LCD_RWBIT        1
DEFINE LCD_RSREG PORTD
DEFINE LCD_RSBIT     2
DEFINE LCD_BITS 4
DEFINE LCD_LINES     4
DEFINE OSC 8
;*******************GİRİŞ ÇIKIŞ KESME AYARLARI**********************************
TRISA=0:TRISB=%11111111:TRISC=0:TRISD=0:TRISE=0:PORTA=0:PORTC=0: PORTD=0:PORTE=0
OSCCON=%01110000:ADCON1=7:CMCON=7:lcdout $FE,$40,4,0,4,4,4,4,4,0
LOW PORTD.1:lcdout $FE,1:pause 300
;**********************DEĞİŞKENLER**********************************************
i var byte:y var byte:x var byte:sayi var byte:sayi2 var byte:page var byte
MENU vAR PORTB.1:yuka var byte:saso var byte:psay var byte:onoff var byte
YUKARI VAR PORTB.3:ASAGI VAR PORTB.7:enter var PORTB.6:SAG var PORTB.5
SOL var PORTB.4:kayit var byte:kayit2 var byte:SYMBOL BUZER=PORTA.6
AYR VAR BIT:AYAR VAR BYTE:SEC VAR BYTE:SAYAC VAR BYTE:adet var byte

;**********************AÇILIŞ EKRANI********************************************
lcdout $FE,$C0,"  ** CNRTL  ** " :pause 300
for i=0 to 18
lcdout $FE,$C0+i," ** CNTRL  ** ":lcdout $FE,$D4,"                     "
pause 145:next i:
yuka=0:saso=0:onoff=0:lcdout $FE,1:pause 200
'************************BASLA**************************************************
BASLA:
GOSUB EKRAN1
    IF MENU=1 THEN GOTO AYAR_MENUSU
goto BASLA       
'***********************EKRAN1**************************************************
EKRAN1:       
lcdout $FE,$80,"AKT",0,"F PROGRAMLAR":lcdout $FE,$C0,"                "
lcdout $FE,$94,"                    ":LCDOUT $FE,$D4,"ADET:",DEC4 Adet
return
'***********************AYAR_MENUSU*********************************************
AYAR_MENUSU:
GOSUB BIP:WHILE menu=1:WEND:GOSUB TEMIZLE:SEC=0:goto DURUM
AYARLAR:
gosub BUTON_KONTROL:goto DURUM:GOTO AYARLAR
;*******************************************************************************
DURUM:
SELECT CASE SEC
CASE 0             
    lcdout $FE,$80,"***** ANA MENU *****":lcdout $FE,$C0," -> ROGRAM AYARI <- "
    lcdout $FE,$94,"     ISTIFLEME      ":LCDOUT $FE,$D4,"       CIKIS        "
        IF ENTER=1 then
            WHILE ENTER=1:WEND
                GOSUB BIP:gosub Temizle:yuka=1:saso=1:gOTO Menu_Page1:ENDIF
CASE 1
    lcdout $FE,$80,"***** ANA MENU *****":lcdout $FE,$C0,"    ROGRAM AYARI    "
    lcdout $FE,$94,"  -> ISTIFLEME  <-  ":LCDOUT $FE,$D4,"       CIKIS        "
        ;IF ENTER=0 then
            ;WHILE ENTER=0:WEND
                ;GOSUB BIP :goto ayarlar :endif;SIMDILIK BOS BU KISIM:ENDIF
CASE 2
    lcdout $FE,$80,"***** ANA MENU *****":lcdout $FE,$C0,"    ROGRAM AYARI    "
    lcdout $FE,$94,"     ISTIFLEME      ":lCDOUT $FE,$D4,"   ->  CIKIS   <-    "
        IF ENTER=1 then
        WHILE ENTER=1:WEND:gosub Temizle:GOSUB BIP:goto BASLA:endif
END SELECT:goto ayarlar
;*******************************************************************************
;********************AYARLAR SAYFASI********************************************
Menu_Page1:
gosub BUTON_KONTROL:gosub Secim
if yuka=>17 then
lcdout $FE,$80,"KAYIT Ve CIKIS"
else
lcdout $FE,$84,"AYAR":lcdout $FE,$C4,"AYAR":lcdout $FE,$98,"AYAR":lcdout $FE,$D8,"AYAR"
lcdout $FE,$8A,"ON":lcdout $FE,$CA,"ON":lcdout $FE,$9E,"ON":lcdout $FE,$DE,"ON"
lcdout $FE,$8F,"OFF":lcdout $FE,$CF,"OFF":lcdout $FE,$A3,"OFF":lcdout $FE,$E3,"OFF":
ENDif
if yuka=>1 and yuka<=4 then
lcdout $FE,$80,"P1"::lcdout $FE,$C0,"P2":lcdout $FE,$94,"P3":lcdout $FE,$D4,"P4":endif
if yuka>4 and yuka=<8 then
lcdout $FE,$80,"P5":lcdout $FE,$C0,"P6":lcdout $FE,$94,"P7":lcdout $FE,$D4,"P8":endif
if yuka>8 and yuka=<12 then
lcdout $FE,$80,"P9":lcdout $FE,$C0,"P10":lcdout $FE,$94,"P11":lcdout $FE,$D4,"P12":endif
if yuka>12 and yuka=<16 then
lcdout $FE,$80,"P13":lcdout $FE,$C0,"P14":lcdout $FE,$94,"P15":lcdout $FE,$D4,"P16":endif
goto Menu_Page1
;*******************************************************************************
Secim:
psay=yuka
if (yuka=1 or yuka=5 or yuka=9 or yuka=13)then
        if saso=1 then Lcdout $FE,$83,"<"
            if saso=2 then
            Lcdout $FE,$88,"<"
                 if enter=1 then
                    goto PROGRAMAYARSEC
                        endif
            endif       
        if saso=3 then Lcdout $FE,$8D,"<"
        if saso=4 then Lcdout $FE,$93,"<"
endif
if (yuka=2 or yuka=6 or yuka=10 or yuka=14)then
        if saso=1 then Lcdout $FE,$C3,"<"
        if saso=2 then
            Lcdout $FE,$C8,"<"
              if enter=1 then
                    goto PROGRAMAYARSEC
                        endif
             endif
        IF saso=3 then Lcdout $FE,$CD,"<"
        if saso=4 then Lcdout $FE,$D3,"<"
endif

if yuka=3 or yuka=7 or yuka=11 or yuka=15 then
        if saso=1 then Lcdout $FE,$97,"<"
        if saso=2 then
            Lcdout $FE,$9C,"<"     
              if enter=1 then
                    goto PROGRAMAYARSEC
                       endif
              endif
        if saso=3 then Lcdout $FE,$A1,"<"
        if saso=4 then Lcdout $FE,$A7,"<"
endif

if yuka=4 or yuka=8 or yuka=12 or yuka=16 then
        if saso=1 then Lcdout $FE,$D7,"<"
        if saso=2 then
            Lcdout $FE,$DC,"<"
              if enter=1 then
                    goto PROGRAMAYARSEC
                       endif
              endif 
        if saso=3 then Lcdout $FE,$E1,"<"
        if saso=4 then Lcdout $FE,$E7,"<"
endif
if yuka=17 then lcdout $FE,$90,"<"
return
;*******************************************************************************
;************************PROGRAM AYAR KISMI*************************************
PROGRAMAYARSEC:
WHILE ENTER=1:WEND:GOSUB TEMIZLE:lcdout $FE,1:yuka=1:y=2
PRGAYAR_SEC:
    gosub PROG_SECENEK
    gosub BUTON_KONTROL
if (yuka=>1)and(yuka<=3) then
    lcdout $FE,$80,"*",#PSAY,".PROGRAM AYARLARI":lcdout $FE,$C0,"1.BICAK GIRIS"
    lcdout $FE,$94,"2.BICAK GIRIS":lcdout $FE,$D4,"1.VAKUM GIRIS"
        gosub PROG_SECENEK:endif   
if (yuka>3)and(yuka<=7) then
    lcdout $FE,$80,"2.VAKUM GIRIS":lcdout $FE,$C0,"1.VAKUM CIKIS"
    lcdout $FE,$94,"2.VAKUM CIKIS":lcdout $FE,$D4,"ISTIFLEME    "
        gosub PROG_SECENEK:endif
if (yuka>7)and(yuka<=11) then
    lcdout $FE,$80,"BICAK GIRIS OFFSET":lcdout $FE,$C0,"BICAK CIKIS OFFSET"
    lcdout $FE,$94,"VAKUM GIRIS OFFSET":lcdout $FE,$D4,"VAKUM CIKIS OFFSET"
        gosub PROG_SECENEK:endif
if (yuka>11)and(yuka<=15) then
    lcdout $FE,$80,"BICAK ZAMAN":lcdout $FE,$C0,"VAKUM ZAMAN"
    lcdout $FE,$94,"DIKIS KONTROL":lcdout $FE,$D4,"ISFTIFLEME"
        gosub PROG_SECENEK:endif
if (yuka>15)then
    lcdout $FE,$80,"KAYIT    ":gosub PROG_SECENEK:endif
goto PRGAYAR_SEC
;*******************************************************************************
PROG_SECENEK:
    if y=2 or y=6 or y=10 or y=14 then
    lcdout $FE,$D2,"<-"
           if (y=2)and(enter=1) then
                 while enter=1:wend
                 onoff[0]=1-onoff[0]
                 if onoff[0]=0 then lcdout $FE,$CF," ON"
                 if onoff[0]=1 then lcdout $FE,$CF,"OFF"
                 endif   
    ENDIF ;2
    if y=0 or y=3 or Y=7 or y=11 or y=15 then         
    lcdout $FE,$D2,"  ":lcdout $FE,$A6,"<-":endif      ;3
    if y=1 or y=4 or y=8 or y=12 or y=16 then
    lcdout $FE,$E6,"<-":lcdout $FE,$A6,"  ":endif      ;4
    if y=5 or Y=9 or y=13 or y=17 then
    lcdout $FE,$92,"<-":lcdout $FE,$E6 ,"  ":endif     ;1
return
;*******************************************************************************
;*******************************************************************************
BUTON_KONTROL:
    IF asagi=1 THEN
        GOSUB BIP:WHILE asagi=1:WEND:yuka=yuka+1:y=y+1:SEC=SEC+1:lcdout $FE,1
            iF yuka=>17 THEN :yuka=1
            if y>17 then y=2
            IF SEC>2 THEN SEC=0
    endif
    IF yukari=1 THEN
        GOSUB BIP:wHILE yukari=1:WEND:yuka=yuka-1:y=y-1:SEC=SEC-1:lcdout $FE,1
            iF yuka<1 THEN:yuka=16
            if y<2 then y=17
            iF SEC=255 THEN SEC=2
    endif
    if SAG=1 then
        GOSUB BIP:wHILE sag=1:WEND:saso=saso+1:lcdout $FE,1
            iF saso>=5 THEN
                saso=1:endif:endif         
    if SOL=1 then
        GOSUB BIP:wHILE sol=1:WEND:saso=saso-1:lcdout $FE,1
            iF saso<1 THEN         
                saso=4:endif:endif
return
;*******************************************************************************
TEMIZLE:
lcdout $FE,1:RETURN
BIP:
hIGH buzer:pause 50:LOW buzer:RETURN

END

ete

Sözüme program yazma mantığını değiştirmeni önererek başlayayım.
Bu şekilde devam edersen bir müddet sonra neyi nerede yaptığını hiç bir şekilde bulamayacak ve anlayamayacaksın. Bunları benmi yazmışım da diyeceksin üstelik. Benzer şekilde program yazan ama sonrada bu konuda şiddeli rahatsızlık duyan birisiyim. Bu nedenle yol yakın iken her satıra tek komut yaz ve ":" kullanmadan program yazmaya özen göster.
Böylece hem hata takibin kolaylaşır hemde yazdıklarından bir anlam çıkartırsın.

Bir diğer önemli konu da LCD komutlarının en fazla işlemci hafızası tüketen komutlar olduğudur. Bu şekilde devam edersen bu program hiç bir işlemciye sığmayacaktır.
Aslında daha detaylı incelemk isterdim ama yazma şeklin buna engel oluyor ve bu inceleme işi çok sıkıcı hale geliyor.
Ama gördüğüm kadarı ile benzer LCD satırlarını birden fazla kullanmışsın. Bunları bile teke düşürsen epeyce hafıza kazancın olacaktır.
Şu satırlara bir bak istersen ;
CASE 0             
    lcdout $FE,$80,"***** ANA MENU *****":lcdout $FE,$C0," -> ROGRAM AYARI <- "
    lcdout $FE,$94,"     ISTIFLEME      ":LCDOUT $FE,$D4,"       CIKIS        "
        IF ENTER=1 then
            WHILE ENTER=1:WEND
                GOSUB BIP:gosub Temizle:yuka=1:saso=1:gOTO Menu_Page1:ENDIF
CASE 1
    lcdout $FE,$80,"***** ANA MENU *****":lcdout $FE,$C0,"    ROGRAM AYARI    "
    lcdout $FE,$94,"  -> ISTIFLEME  <-  ":LCDOUT $FE,$D4,"       CIKIS        "
        ;IF ENTER=0 then
            ;WHILE ENTER=0:WEND
                ;GOSUB BIP :goto ayarlar :endif;SIMDILIK BOS BU KISIM:ENDIF
CASE 2
    lcdout $FE,$80,"***** ANA MENU *****":lcdout $FE,$C0,"    ROGRAM AYARI    "
    lcdout $FE,$94,"     ISTIFLEME      ":lCDOUT $FE,$D4,"   ->  CIKIS   <-    "

bu bölümü ben şöyle yazarım;
DURUM:
    lcdout $FE,$80,"***** ANA MENU *****":lcdout $FE,$C0,"    ROGRAM AYARI    "
    lcdout $FE,$94,"     ISTIFLEME      ":LCDOUT $FE,$D4,"       CIKIS        "
    SELECT CASE SEC
     CASE 0
     LCDOUT $fe,$c1,"->":Lcdout $fe,$D1,"<-"
     IF ENTER=1 then
       WHILE ENTER=1:WEND
       GOSUB BIP
       gosub Temizle
       yuka=1:saso=1
       gOTO Menu_Page1
      ENDIF   
     
      Case 1   
      LCDOUT $fe,$96,"->":Lcdout $fe,$AA,"<-"

    Case 2
    LCDOUT $fe,$D7,"->":Lcdout $fe,$E3,"<-"
        IF ENTER=1 then
          WHILE ENTER=1:WEND
          gosub Temizle
          GOSUB BIP
          goto BASLA
       endif
      END SELECT
      goto ayarlar

Epeyce incelenecek yer var ama umarım anlatmaya çalıştığım mantığı anlamışsındır.
Ete




oguztkn

#2
Hocam öncelikle cevabınız için teşekkür ederim.

Kodları sizin gösterdiğiniz ışık ile sadeleştirmeye çalışıyorum. Şimdi  şöyle bir sorunum var pc8574 entegresini kullanıyorum. 8 adet buton okumak için. Bu entegrenin şemadaki gibi data ucu PORTC.2 ye clk ucu PORTC.1 ' e bağlı tabiki pull uplar ile. int ucu ise portb.0 a bağlı.

Şimdi ben kodların başında
INTCON.7=1
INTCON.4=1
on interrupt goto kesme tanımlıyorum

disable
kesme:
      ı2cread PORTC.2,PORTC.1,$49,[temp]
INTCON.1=0
resume
enable

şeklinde tanımlıyorum ve programın basla kısmını
basla:
lcdout $FE,$80,bin8 temp
goto basla

şeklinde tanımlıyorum. Amacım her butonun düzgün çalıştığını test etmek. Ama hiçbir hareket yok. Nerede hata yapıyorum.

Pcf8574'te a0 vcc a1 ve a2 gnd ye bağlı buradan da datasheetinde okumak için $49 yazmak için $48 adreslerini kullanmam gerektiğini buldum. Ama nereyi atlıyorum bulamadım ? Sanırım normal döngü içerisinde yani kesme dönüşü pcf nin içerisine birşeyler yazmalıyım ama bulamadım. Sonsuz döngüye girdim dönüyorum sürekli. :)

ete

Bana kalırsa hatan I2C device adresi. $49 kullanmışsın. Data sheet şöyle diyor;
Device adress =%0100A2-A1-A0-R/W
Şimdi Ax bitleri birden fazla 8574 bağlı ise onları buradan adreslemek için kullanılıyor. Öncelikle tek kullandığını varsayarak doğru kodu bulmaya çalışalım. Basic yazma ve okuma bitlerini otomatik ayarlamaktadır.
Data sheet adres referans tablosunda,
A2-A1-A0=0 ise kullanılacak adres $40 olacak diyor. (Basic okuma konumunda bunu otomatik $41 yapacaktır.) Sen hep aynı değeri kullan. Yada 40-41 kullansanda bir şey değişmeyecek bu şekilde de kullanabilirsin.
Sen ise adres olarak $49 kullanmışsın bunun binary karşılığı %01001001 buradan şu çıkıyor. Sen 4+1=5 adet PCF8574 okumaya çalışıyorsun ve okuduğun adres de beşinciye ait. Yani devrendeki PCF yi okuyamıyorsun demektir bu.
Referans tablosunda 1-8 adet pcf kullanımına göre adres değerini göstererek vermiş adam zaten. Buna göre;
A2-A1-A0 bitleri;
%000 ise devrede 1 adet PCF var demektir.
%001 ise devrede 2 adet PCF var demektir (1+1)
%010 ise devrede 3 adet PCF var demektir.
%011 ise devrede 4 adet PCF var demektir.
%100 ise devrede 5 adet PCF var demektir.
%101 ise devrede 6 adet PCF var demektir.
%110 ise devrede 7 adet PCF var demektir.
%111 se devrede 8 adet PCF var demektir.

Ete

oguztkn

#4
Hocam dediğiniz gibi adreslerde hata yapıyormuşum. Adresi düzeltince pcf den bilgi alabiliyorum. Ama çok ilginç bir durumla uğraşıyorum.

i2cread PORTC.2,PORTC.1,$41,[temp]

komutunu ana döngüde kullanırsam sorun yok her biti tek tek okuyabiliyorum. Ama pcf'nin int bacağını portb.0 pinine bağlayıp. kesme ayarlarını yapıp kesmede okumak istediğimde çalışmıyor. Acaba kesme oluşmuyor mu diye düşünerek bir adet deneme sayacı koydum kesmeye her kesmeye girdiğinde bir arttırıp lcd de yazması için sayac çalışıyor her basışta ama pcfden değerler gelmiyor. Bunun nedeni ne olabilir ?

Programın başında DEFINE I2C_SLOW 1 komutu bulunmakta 20mhz ile çalışıyorum.

kesme programım ise :
DISABLE
Kesme:
     lcdout $fe,$c0,"deneme:",#p1
    i2cread PORTC.2,PORTC.1,$41,[temp]
    p1=p1+1
    INTCON.1=0
resume
enable

okuma komutundan sonra 10ms gecikme koymayı da denedim birşey değişmedi. 

ete

Adresi $41 değilde 40 ver bakalım sonuç değişecekmi.
Bakanilmem için varsa aimulsyon devresi ve programınıda buraya koy belki tamamında bir sorun bulanilirim. Pek mantıklı değil bu kusur.
P değeri arttığına göre ona bakıp kesmeye girip girmediğini görebilirsin giriyormudur?
Ete

oguztkn

#6
Bayrak sıfırlamalar ile ilgili eksiğimi farkettim hocam hallettim,

ama şunu sorabilirim write 0,deneme ile eproma yazıyoruz mesele bu adres sayısı kaça kadar ilerleyebiliyor.

Mesela 18f4520 kullanıyorum datasheet'inde 256 byte eeprom olduğu söyleniyor. Yani 256 adet byte türünden değişken yazılabilir anlamına geliyor bu sanırım. Peki adres olarak nasıl belirleniyor yani 0,1,2,3 şeklinde mi ilerleyecek bu komut ?

ete

256 byte eprom sana 0-255 arasında adres kullanarak kayıt yapma imkanı verir.
Ete

oguztkn

Merhaba,

Sağlık sorunu nedeniyle bir süreliğine ara vermiştim tekrar başladım şuan için tüm menü işlemleri bitti. yaklaşık 15 adet gibi bir sayıda byte tipi değişkeni usart ile kontrol kartına göndermeye çalışıyorum. Usart ayarlarını ayarlayabildim. Deneme olarak bir adet byte tipi değişkeni gönderip diğer alabiliyorum. Sorunum bu 15 adedi nasıl ayırt edebilirim. Forumda bir yazınızda HSERIN [STR DiziVar\5\254] komutunu gördüm. Bunun üzerine uğraşıyorum ama veriler genede karışıyor.

bicakgiris var byte[5]
alıcıda de şu kodu deniyorum
basla:
HSERIN [STR bicakgiris\5\254]
lcdout $FE,$80,"0:",dec bicakgiris[0],"     ","1:",dec bicakgiris[1]
lcdout $FE,$C0,"2:",dec bicakgiris[2],"     ","3:",dec bicakgiris[3]
lcdout $FE,$94,"4:",dec bicakgiris[4],"     ","5:",dec bicakgiris[5]
goto basla

göndericide ise
Basla:
bicakgiris[0]=12
bicakgiris[1]=2
bicakgiris[2]=0
bicakgiris[3]=13
bicakgiris[4]=189
bicakgiris[5]=254
HSERout [str bicakgiris\5]
goto basla

gönderdiğim sırada yerleşmiyor nedense , ben bu verileri nasıl ayıklayabilirim ? Kesme kullanmayı düşündüm ama gönderme ve alma esnasında ne gönderici nede alıcı başka işlemler yapmıyor o yüzden vazgeçtim. Birde diğer kartla haberleşmenin durumunu da izlemek istiyorum bunun için bir timer kurup belirli bir sürede bir karakter yollayıp cevap almam gerekiyor diye çözüm ürettim ama bu kadar verinin arasında kaldım ,nereden başlasam bilemedim beceremedim bir ışık yakabilir misiniz hocam ?

Amacım lcd'nin olduğu kartta değişkenlere değerler giriyorum(şimdilik byte tipinde sonra word'e döndürebilirim) bunları eproma yazıyorum diğer karta da bu verileri aktarıp orada da eproma yazıp işlemleri ona göre yapmaya çalışıyorum. Diğer kartta işlemci ve çıkışlar için 2 adet uln bulunmakta bu çıkışları lcd den girdiği değerleri göre açık kapalı durumları üzerinde uğraşıyorum. (İki kartta 18f4520 bulunmakta kristaller ise biri 8(dahili) biri 20 mhz)

Şimdiden Teşekkür ederim....

ete

Dizi değişkenlerini kullanırken dikkat edilmesi gereken en önemli nokta dizi sayısıdır.
bicakgiris var byte[5] şeklinde tanımlanmış dizide dizi elemanı sayısı 5 tir. Bunun elaman bazında ayırımı ise ;
bicakgiris[0]
bicakgiris[1]
bicakgiris[2]
bicakgiris[3]
bicakgiris[4]
şeklindedir.  Senise diziye bicakgiris[5] elamınınıda ekleyerek eleman sayısını 6 ya çıkartmış oluyorsun. 5 ide kullanacaksan tanımlamaya 5 değil 6 yazman gerekir.
Elemanlara değerler gönderme sırasında yerleşir. Aynı sırada da alınır.
Bu dediklerimi dikkate alarak yeniden deneme yap düzelecektir sorunun.
Ete

Powered by EzPortal