G

Programla ilgili ufak bir yardım.

Başlatan gozkan, 03 Temmuz 2012, 22:43:16

gozkan

Merhaba arkadaşlar. Aşağıda vermiş olduğum ISIS dosyası ve Program dosyası simulasyon olarak güzel çalışıyo aslında %99 oranda istediğim gibi oldu. Ama kesme işlemini kullanamadım. Bir kaç deneme yaptım ama sonuç hüsran Erol bey kesmeyi anlattı ama ben gene anlamamışım :).Bende Stop butonunu en çok devrenin tekrar ettiği yere koymaya çalıştım ama genede kesme işlemi gibi olmaz. Kesme gerçekleşince programın sıfırdan başlamasını istiyorum ama yapamadım.  Programla ilgili yardımcı olabilecek arkadaslara şimdiden teşekkürler. Birde Unutmadan benim bu sigorta ayarlarıyla da aram pek iyi değil. Şayet Osilatör kullanmazsam bütün bacakları giriş çıkış olarak kullanabilirmiyim. Osilatör kullanırsan ayarlar nasıl olmalı. Benim yapmak istediğim devre bu fakat aynen bu şekilde kursam devreyi (transistörler falan bağladıktan sonra) bi sıkıntı çıkarmı. Hala bu A.4 ve A.5 portlarını düzgün şekilde kullanamıyorum pullup direncimi koyacam onlara düzgün çalışması için. Bana herbir durun için Sigortaları yazarsanız sigorta işinide kavrayabilirim.

ISIS Dosyası ve program ektedir.
  
    '*****GİRİŞ VE ÇIKIŞLAR*****
    TRISA=%00000001             
    TRISB=0               
    PORTA=0
    PORTB=0
    '—————————————————————
    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 2 'LCD RS  bacağı Hangi Bite bağlı ?
    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
    '——————————————————————
    CMCON=7 '16F628a de  komparatör pinleri iptal hepsi giriş çıkış
    OPTION_REG.7=1 'portB deki  dahili PULL-UP lar iptal edildi.
    '——————————————————————
@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _LVP_OFF & _CP_OFF
    '——————————————————————
    LCDOUT $FE,1
    PAUSE 300             
    SYMBOL DTA=PORTA.3             'Çıkış entegresi 74HC595 data ucu
    SYMBOL CLK=PORTB.0             'Çıkış entegresi 74HC595 clock ucu
    symbol SET=PORTB.1             'Çıkış entegresi 74HC595 aktarma ucu
    SYMBOL DTA_INPUT=PORTA.0       'Giriş entegresi 74165 data ucu
    SYMBOL CLK_INPUT=PORTA.1       'Giriş entegresi 74165 clock ucu   
    SYMBOL SET_INPUT=PORTA.2       'Giriş entegresi 74165 aktarım  ucu             
    POSITION1 var word          : POSITION1=20             'Yatak başlangıç konumu
    POSITION2 var word          : POSITION2=50             'Yatak duruş konumu
    POSITION var word           : POSITION=POSITION2-POSITION1    'Yatak haraket mesafesi
    SPEED var byte              : SPEED=0                 'Hız değişkeni
    INPUT_DATA VAR byte         : INPUT_DATA=0           'Giriş (Buton) Bilgisi
    OUTPUT_DATA VAR byte        : OUTPUT_DATA=0           'Çıkış (Step Motor) Bilgisi
    k var word                                             'Konum için sayaç
    i var word                                             'Hız için Sayaç
    j var bit                   : J=1                       'Yön değiştirme değişkeni
    symbol UP_BUTTON=INPUT_DATA.0    'Bu bölümdekiler Butonlara karşılık gelen input değerleridir.
    symbol DOWN_BUTTON=INPUT_DATA.1
    symbol MENU_BUTTON=INPUT_DATA.2
    symbol START_BUTTON=INPUT_DATA.3
    symbol STOP_BUTTON=INPUT_DATA.4
    symbol SWITCH=INPUT_DATA.5
    symbol MOTOR_UP=INPUT_DATA.6
    symbol MOTOR_DOWN=INPUT_DATA.7
    '——————————————————————
    'PORGRAM BAŞLANGIÇ
    '——————————————————————
    pause 200                            'Program başlamadan 200ms bekle
TOP:
    gosub BUTTON_READ                     'Buton verileri okunur
    LCDOUT $FE,2,"MENU TUSUNA YADA "
    lCDOUT $FE,$C0, "START TUSUNA BASIN"
    pause 500
    while START_BUTTON=0  and MENU_BUTTON=0       
       gosub BUTTON_READ
       if MOTOR_UP=1 then
          gosub MOTOR_YUKARI
          pause 100 
       endif
       if MOTOR_DOWN=1 then
          gosub MOTOR_ASAGI
          pause 100
       endif     
    wend
    OUTPUT_DATA=0 
    LCDOUT $FE,1
    '——————————————————————
    if START_BUTTON=1 then
       OUTPUT_DATA=8
START:
       LCDOUT $FE,2,"  HAZIRLANIYOR "
       LCDOUT $FE,$C0, "LUTFEN BEKLEYIN..."
       pause 100
RESET:   
       gosub BUTTON_READ   
       if SWITCH=1 then
          LCDOUT $FE,1   
          LCDOUT $FE,2,"BASLANGIC KONUMU "
          LCDOUT $FE,$C0, "   AYARLANIYOR"     
          for i=0 to POSITION1
             gosub FORWARD
             pause 100
          next
          pause 1000
          LCDOUT $FE,1
          goto RUN 
       else
          gosub BACKWARD
          pause 100
          goto RESET
       endif       
    endif
    '——————————————————————
    if MENU_BUTTON=1 then
    'MENU BAŞLANGIÇ NOKTASI AYARI
    '——————————————————————
       LCDOUT $FE,2,"HARAKET MESAFESINI"
       LCDOUT $FE,$C0, "   AYARLAYINIZ"
       pause 1000   
       LCDOUT $FE,1
START_POSITION: 
       gosub BUTTON_READ
       LCDOUT $FE,2," BASLANGIC NOKTASI"
       LCDOUT $FE,$C0,"      ",#POSITION1, " mm    "
       while MENU_BUTTON=0 and UP_BUTTON=0 and DOWN_BUTTON=0   
          gosub BUTTON_READ
       wend
       while MENU_BUTTON=0 
          gosub BUTTON_READ
          if UP_BUTTON=1 then POSITION1=POSITION1+5
          if DOWN_BUTTON=1 then POSITION1=POSITION1-5
          if POSITION1< 0 or POSITION1>POSITION2 then POSITION1=0
          if POSITION1=POSITION2 then POSITION1=POSITION2-5
          while UP_BUTTON=1 
             gosub BUTTON_READ
          wend
          while DOWN_BUTTON=1 
             gosub BUTTON_READ
          wend
          goto START_POSITION
       wend   
       while MENU_BUTTON=1 
          gosub BUTTON_READ
       wend
       LCDOUT $FE,1
    'BİTİŞ NOKTASI AYARI
    '——————————————————————
STOP_POSITION: 
       gosub BUTTON_READ
       LCDOUT $FE,2,"  BITIS NOKTASI"
       LCDOUT $FE,$C0,"      ",#POSITION2, " mm    "
       while MENU_BUTTON=0 and UP_BUTTON=0 and DOWN_BUTTON=0   
          gosub BUTTON_READ
       wend
       while MENU_BUTTON=0 
          gosub BUTTON_READ
          if UP_BUTTON=1 then POSITION2=POSITION2+5
          if DOWN_BUTTON=1 then POSITION2=POSITION2-5
          if POSITION2<=POSITION1 then POSITION2=POSITION1+5 
          if POSITION2> 200 then POSITION2=200
          while UP_BUTTON=1 
             gosub BUTTON_READ
          wend
          while DOWN_BUTTON=1   
             gosub BUTTON_READ
          wend
          goto STOP_POSITION
       wend 
    endif
   
    LCDOUT $FE,1
    LCDOUT $FE,2,"  BASLAMAK ICIN "
    LCDOUT $FE,$C0, " STARTA BASINIZ"
    '——————————————————————
    WHILE START_BUTTON=0 
       gosub BUTTON_READ
    wend
    goto START 
    '——————————————————————
    'MOTOR ÇALIŞMA BÖLÜMÜ
RUN: 
    gosub BUTTON_READ
    for k=1 to POSITION2-POSITION1 
       gosub BUTTON_READ
       if j=0 then   
          gosub BACKWARD
          POSITION=POSITION2-k
       else     
          gosub FORWARD     
          POSITION=POSITION1+k
       endif
    '——————————————————————
    'Tuşlar
       if  DOWN_BUTTON=1 then SPEED=SPEED+1
       if  UP_BUTTON=1 then SPEED=SPEED-1
       if SPEED<5 then SPEED=5
       if SPEED>50 then SPEED=50
       if STOP_BUTTON=1 then              'Bu komudu kesme ile yapmak istedim ama beceremedim
          goto TOP                        'Erol bey bu konuda yardımcı olursanız sevinirim.
       endif                              '
       LCDOUT $FE,2,"   HIZ   = ",DEC3 50-SPEED
       LCDOUT $FE,$C0, " KONUM= ",dec POSITION1,"-",dec POSITION2," ",dec2 POSITION," ",dec1 OUTPUT_DATA
    '——————————————————————
       for i=1 to SPEED         
          pause 20
       next
    next 
    toggle j                                     
    GOTO RUN
   
    'İleri Yönde Çalıştır.
    '——————————————————————
FORWARD: 
    gosub BUTTON_READ
    if OUTPUT_DATA< 1 or OUTPUT_DATA>8 then OUTPUT_DATA=1
    sHIFTOUT DTA,CLK,1,[OUTPUT_DATA]
    HIGH SET:PAUSEus 2:LOW SET 'BILGI ÇIKIŞA AKTARILDI
    OUTPUT_DATA=OUTPUT_DATA*2
    return   
    'Geri Yönde Çalıştır.
    '——————————————————————
BACKWARD:   
    gosub BUTTON_READ
    if OUTPUT_DATA< 1 or OUTPUT_DATA>8 then OUTPUT_DATA=8
    SHIFTOUT DTA,CLK,1,[OUTPUT_DATA]
    HIGH SET:PAUSEus 2:LOW SET       'DATA ÇIKIŞA AKTARILDI
    OUTPUT_DATA=OUTPUT_DATA/2
    return
   
MOTOR_YUKARI:   
    if OUTPUT_DATA< 16 or OUTPUT_DATA>128 then OUTPUT_DATA=16
    sHIFTOUT DTA,CLK,1,[OUTPUT_DATA]
    HIGH SET:PAUSEus 2:LOW SET 'BILGI ÇIKIŞA AKTARILDI
    OUTPUT_DATA=OUTPUT_DATA*2
    return   
   
MOTOR_ASAGI:
    if OUTPUT_DATA< 16 or OUTPUT_DATA>128 then OUTPUT_DATA=128
    SHIFTOUT DTA,CLK,1,[OUTPUT_DATA]
    HIGH SET:PAUSEus 2:LOW SET       'DATA ÇIKIŞA AKTARILDI   
    OUTPUT_DATA=OUTPUT_DATA/2
    return
   
BUTTON_READ:
    LOW SET_INPUT: PAUSEUS 2: HIGH SET_INPUT      'Girişler registere yazıldı
    SHIFTIN DTA_INPUT,CLK_INPUT,0,[INPUT_DATA]
    return
    end




greatgonzo

#1
Kullandığım sigorta ayarları. 628A için böyle

@ DEVICE pic16F628A                                         'işlemci 16F628 
@ DEVICE pic16F628A, BOD_ON                          'Bunun tam ne olduğunu bilmiyorum ama brown on detect gibi bişi. Pic düşük     
@ DEVICE pic16F628A, WDT_OFF                        'Watch Dog timer kapalı                                                gerilimle çalışması için
@ DEVICE pic16F628A, PWRT_ON                       'Power on timer açık                                                        gerekli bir ayardı sanırım
@ DEVICE pic16F628A, PROTECT_OFF                 'Kod Koruma kapalı
@ DEVICE pic16F628A, MCLR_off                    'MCLR pini kullanılmıyor.
@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT  'Dahili osilatör kullanılacak

Tüm pinler giriş çıkış olurmu soruna genel yanıt genellikle olmaz. Resimdeki  okları takip edersen fark edeceksinki bazı pinler tek yönlüdür. Onlar sadece o yonde çalışırlar. Yanlız dikkat! isis similasyonu yanıltabilir. Aynı pin yapısına sahip 16F88 de başıma geldi; led animasyon için tümünü çıkış olarak kullandım ve yazdığım program problemsiz çalıştı ama gerçek devrede öyle olmadı. Zira  RA5/MCLR bacağına bakarsan ok sadece giriş şeklinde.Bunun anlamı,sigorta ayarlarındaki  @ DEVICE pic16F628A, MCLR_off                 'MCLR pini kullanılmıyor.
ifadesiyle MCLR özelliğini kapatsan bile sadece giriş pini olarak kullanılıyor.

Bu arada birde kesme probleminden bahsetmişsin ki anladığım kadarıyla tüm değişkenleri sıfırlayıp programı en başa döndürmek istiyorsun. Yazılımının içeriğine bakmadım ama tam olarak bunu istiyorsan senin çözümün MCLR pini.

  @ DEVICE pic16F628A, MCLR_ON

sigorta ayarını bu şekilde tanımlayacaksın ve bu pini 5v a çekeceksin.Tabi direnç ile pull up yapacaksın ve tercihen minik bir kondansatörde topraklama arasında yer alabilir usulen. MCLR (Master CLeaR) bacağını bir butonla sıfıra çekersen o zaman istediğin istediğin reseti alırsın. Herhangi bir kesme rutunine ihtiyacın yok. İlgili resimlerde aşağıda:-)

İyi çalışmalar

gozkan

Yardım için çok teşekkür ederim. Yapmak istediğim reset aynen dediğiniz gibi o yüzden dediğiniz çok mantıklı geldi sizin dediğiniz gibi yapmak en iyi şu anda . Ama sigorta işinde şöyle bir problemim ar benim işletim sistemi win7 64 bit olduğundan sizin yazıdğınız gibi yazınca hep hata alıyorum. Erol beyin anlattığı 64 bit işletim sistemleri için sigorta ayarını yaptım ama ne kadar düzgün çalışıyor bilmiyorum çünkü . Sigorta işini henüz kavrayabilmiş değilim. Tekrar teşekkür ederim.

ete

Sigorta ayarları ile işe başlayalım.
@ DEVICE pic16F628A           ' bu satır ile çalıştığın işlemcinin 16F628 olduğunu derleyiciye bildirmiş oluyorsun.

@ DEVICE pic16F628A, BOD_ON      'İşlemciye ilk voltaj verildiğinde voltaj seviyesi anlık olarak çekilen akımlar nedeni ile düşer. İşte bu sgorta ayarını ON yaparsanız işlemci beslemesi istenilen seviyeye gelinceye kadar işlemciyi reset konumunda tutar. Bazen faydalı bazen ise zararlıdır. Örneğin devrede röle veya akım çeken bir eleman kullanıyor ve besleme kaynağınız yeterince güçlü değil ise röle çekerçekmez besleme voltajı anlık olarak düşer. BOD bunu anlık olarak yakalar ve işlemciye reset attırır. Bu ise her zaman istenen bir durum değildir. Dolayısıyla gerektiğinde OFF yapılmalıdır.


@ DEVICE pic16F628A, WDT_OFF       'bekçi köpeği diye adlandırılıyor. Amacı işlemciyi kilitlenmeden kurtarmaktır. Programlarda yanlışlıkla (programlama hatası) sistemi sonsuz döngüye sokarsanız WDT_ON ise bir müddet sonra işlemciyi sonsuz döngüden kurtarır. Bazende gereksiz yere sürekli reset atttırır. Bu nedenle genelde kapalı tutulmalı ve bazı özel durumlarda programdan emin değilseniz açık tutulmalıdır.

@ DEVICE pic16F628A, PWRT_ON          İşlemciye ilk voltaj verildiğinde besleme kaynağının stabil olması için yaklaşık 70 ms lik bir gecikme uygular. Faydalıdır sürekli açık olması gerekir.

@ DEVICE pic16F628A, PROTECT_OFF          Yazdığınız programların başkaları tarafından kopyalanmasını istemiyorsanız bu ayarı aktif (ON) yapmanızı öneririm. Böylece işlemci üzerindeki program okunamaz hale gelir. (bütün bitler 1 olarak gözükür)

@ DEVICE pic16F628A, MCLR_off           MCLR işlemcinin reset bacağıdır. Bu bacak HIGH da tutulduğu müddetçe işlemci aktif yani çalışır konumdadır. MCLR bacağı anlık olarak LOW  yapılır ise işlemci resetlenir ve içindeki program baştan başlar. Ancak bazı değişken değerleri değişmeyebilir. Her işlemcide olmasada bazı işlemcilerde bu bacağın Reset özelliği iptal edilerek normal giriş bacağı haline getirilebilir. Unutmayın MCLR bacağı yalnızca giriş olabilir çıkış olamaz. Oda işlemcide bu iş için uygun donanım var ise. Örnek vermek gerekirse 16F628 - 16F88 12F675 gibi işlemcilerde MCLR iptal edilerek pin giriş pini yapılabilir. Ancak 16F84, 16F876 , 16F877 gibi işlemcilerde bu işlem mümkün değildir. Yeni nesil işlemcilerde genellikle bu özellik bulunmaktadır.

@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT   Her işlemci bir CLK palsi eşliğinde çalışabilmektedir. Gerekli olan bu CLK palsi genelde haricen bağlanan bir kristal yada RC osilatörle sağlanabildiği gibi yine bazı işlemcilerin özelliği olarak işlemciler içinde fabrika tarafından kalibre edilmiş dahili osilatörleri de bulunmaktadır. İstenirse kristal istenirse dahili osilatörler kullanılabilir.
Bunu sağlayan ise bu sigorta ayarıdır.
@ DEVICE pic16F628A, XT_OSC  şeklinde kullanılır ise işlemciye 1-6 MHz arasında bir kristal bağlanabilir.
@ DEVICE pic16F628A, HS_OSC  şeklinde kullanılır ise işlemciye 6-20 Mhz arasında bir kristal bağlanabilir.
Bu iki alternatifte PORTA.6 ve PORTA.7 pinleri OSC pinleri olarak kullanılır başka işler için kullanılamaz.
@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT şeklinde kullanılır ise işlemcinin dahili osilatörü kullanılacak demektir. Bu konumda PortA.6 ve PortA.7 pinleri normal giriş çıkış pini olarak kullanılabilir.
Tabiiki INTRC_OSC her işlemcide bulunan bir özellik değildir. Yalnızca yeni nesil işlemcilerde bulunur. 12F675, 16F628, 16F88 16F886, 16F887 gibi işlemcilerde vardır. 16F84 , 16F876 ve 16F877 gibi işlemcilerde bulunmaz.

Kesme olayına gelince, tabiiki yalnızca stop butonunu PortB.0 pinine bağlayarak basıldığında kesme oluşturabilirsin.
Çok zor bir iş değil. Nasıl yapıldığını yeniden anlatmadan önce aynı pine bağlamış olduğun 74595 CLK pinini başka bir yere bağlaman gerekecek bunu unutma.
Kesme oluşturmak için Sırası ile yapman gerekenler şunlar.
Option registeri 7.biti sıfır yapılacak (pullup dirençlerini açmak için.  OPTION_REG.7=0
INTCON registeri 7 ve 4.cü bitlerini high yapacaksın.   INTCON=%10010000
ON INTERRUPT GoTo KESME  şeklinde bir komut satırı ilave ederek kesme oluştuğunda KESME isimli etikete gidilmesini sağlayacaksın.
Buraya kadar PORTB.0 kesmesi açılmış oldu. Şimdi kesme etiketinde ne yapılacak ona bakalım.
Önce DISABLE komutunu vereceksin bu yeniden kesme oluşmasını engelleyecek. Kesme içinde kesme oluşmaması gerekir.
Sonra KESME: etiket adını yazacaksın.
Ardından
DUR isimli bir bit değişkenin olacak ve bu değişkeni kesme içinde set deceksin.
DUR=1 şeklinde set ediliyor.
Sonra
INTCON.1=0 'kesme bayrağı sıfırlanacak.
RESUME
ENABLE
şeklinde işi tamamlayacaksın.
Şu anda program kesmeden çıktı ve ana programa geldiği yere döndü. Stop butonuna bastık ama hala programı TOP etiketine yönlendiremedik. Ama elimizde bir işaret var oda DUR=1 oldu. O halde programın belirli yerlerine ;
IF DUR=1 THEN
  DUR=0
  GOTO TOP
ENDIF
şeklinde komut dizisi eklersen program TOP etiketine atlayacaktır. Ancak hangi konumdan Kesme etiketine gidileceğini kestiremediğimiz için bunu programın çalışan kısımlarında en azından 3 ayrı konuma yerleştirmen gerekir.

ENABLE satırı ile işi bitirmiş olacağız.

Görüldüğü üzere bu programda stop butonunu kesme ye bağlamak çok akıllıca değil bence. Çünki stop butonu yalnızca programı TOP isimli başlangıç etiketine yollayacak. Kesme oluşturmak direk TOP etiketine yollamak için bir araç olamıyor maalesef. Aslında RESUME TOP şeklinde bir ikinci komut var ve programınistenilen etikete dönmesini sağlıyor ama çok iyi çalıştığını söyleyemem. Bu komutu yapmışlar ama onalarda ipin ucunu kaçırınca üzerinde çok fazla durmamaışlar anlaşılan.

Ete




gozkan

Erol bey size ve tekrardan greatgonzo beye teşekkür ederim. Gerçekten çoook yardımcı oldunuz sigortalar baya iyi açıklanmış tekrar teşekkür ederim.

Oceanicy

hocam bu sigortaları detaylı açıklamanız çok işime yaradı sağolun.

Powered by EzPortal