avatar_ete

PIC Basic Ders-06 (Kesme (INTERRUPT) Kullanımı)

Başlatan ete, 28 Ağustos 2011, 16:13:09

ete

Bu konu tam olarak nerede yer alıyor?  Programin tamamına bakmam lazım.
Ete

0nur

PORTA=0:portb=0
TRISB=%00001111   'PortB tamamı giriş yapıldı.
TRISA=%00000000   'A portu tamamı çıkış yapıldı.
'-----------------------------------------------------------------
@ DEVICE pic16F628                      'işlemci 16F628                               
@ DEVICE pic16F628, WDT_OFF              'Watch Dog timer açık
@ DEVICE pic16F628, PWRT_ON             'Power on timer açık
@ DEVICE pic16F628, PROTECT_OFF         'Kod Protek kapalı
@ DEVICE pic16F628, MCLR_off            'MCLR pini kullanılıyor.
@ DEVICE pic16F628, INTRC_OSC_NOCLKOUT  'Dahili osilatör kullanılacak
'-----------------------------------------------------------------
DEFINE LCD_DREG PORTA 'LCD data bacakları hangi porta bağlı?
DEFINE LCD_DBIT 0 'LCD data bacakları hangi bitten başlıyor?
DEFINE LCD_EREG PORTA 'LCD Enable Bacağı Hangi Porta bağlı?
DEFINE LCD_EBIT 7 'LCD Enable Bacağı Hangi bite bağlı ?
DEFINE LCD_RSREG PORTA 'LCD RS Bacağı Hangi Porta bağlı ?
DEFINE LCD_RSBIT 6 'LCD RS 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
'-------------------------------------------------------------------------
ON INTERRUPT GoTo KESME   'kesme oluşursa KESME adlı etikete git.
OPTION_REG=%10000101   'Pull up dirençleri İPTAL- Bölme oranı 1/64.
INTCON=%10100000  'Kesmeler aktif ve TMR0 kesmesi aktif
TMR0=0
CMCON=7    '16F628 de komparatör pinleri iptal hepsi giriş çıkış
'----------------------------------------------------------------------------
SAYAC   VAR   BYTE
SN      VAR   BYTE[5]
DAK     VAR   BYTE[5]
SAAT    VAR   BYTE[5]
GUN     VAR   BYTE
DURUM   var   byte
I       VAR   WORD
ESKI    VAR   BYTE
ROLE    VAR   BYTE
'-----------------------------------------------------------------------------
CLEAR  'tüm değişkenler sıfırlandı
PAUSE 200
LCDOUT $FE,1

'-----------------------------------------------------------------------------

BASLA:
      LCDOUT $FE,$84,DEC2 SAAT[0],":",DEC2 DAK[0],":",DEC2 SN[0]
      DURUM=PORTB & %1111
      IF DURUM>0 THEN PORTB=DURUM
      ESKI=PORTB | DURUM*16
      ROLE=NCD ESKI  'NCD KOMUTU SAYIDAKİ EN YÜKSEK HİGH OLAN BİTİ VERİR
      ROLE=((ROLE>0)&%1)*(ROLE-4) 'BİR ÇOK İŞİ GÖREN TEK BİR KOMUT
      LCDOUT $FE,$C0,"ROLE=",#ROLE,"  ",DEC2 SAAT[ROLE],":",DEC2 DAK[ROLE],":",DEC2 SN[ROLE]
     
      PORTB=ESKI
      FOR I=0 TO 2000
        PAUSEUS 10
      NEXT I 
      GOTO BASLA

DISABLE
KESME:
      SAYAC=SAYAC+1  'kesme sayacı  1 sn= 61(sayac) x 256 (Tmr0) x 64 (bölme)
      IF SAYAC=61 then  '61 adet kesme olunca 1 sn. süre geçiyor.(999424 us)
         SAYAC=0        'sayaç sıfırlanıyor
         SN[0]=SN[0]+1
         IF ROLE=0 then ATLA
         SN[ROLE]=SN[ROLE]+1        'saniye değeri bir artırılıyor
ATLA:    IF SN[0]=60 THEN  'saniye 60 olmuş ise 1 dakika süre geçti ohalde
               SN[0]=0
               SN[ROLE]=0        ' saniye sıfırlanıyor
               DAK[0]=DAK[0]+1
               DAK[ROLE]=DAK[ROLE]+1   ' dakika değeri bir artırılıyor
                  IF DAK[0]=60 then   'dakika 60 olmuş ise 1 saat süre geçti
                     DAK[0]=0
                     DAK[ROLE]=0         ' dakika sıfırlanıyor
                     SAAT[0]=SAAT[0]+1
                     SAAT[ROLE]=SAAT[ROLE]+1   ' saat değeri bir artırılıyor
                        IF SAAT[0]=24 THEN  'saat 24 olmuş ise 1 gün geçti
                           SAAT[0]=0
                           SAAT[ROLE]=0        'saat sıfırlanıyor
                           GUN=GUN+1     'gün değeri bir artırılıyor
                              IF GUN=365 THEN GUN=0  'gün 365 olmuş ise
                        endif                    'gün sıfırlanıyor 1 yıl geçti
                  ENDIF
            ENDIF
         ENDIF
         INTCON.2=0        'TMR0 Kesme bayrağı sıfırlanıyor
         RESUME
         ENABLE
         
END
'NOT
'sayac=50 SATIRINDA 50 SAYISI 1 SN LİK SÜREYİ AYARLAMAKTADIR. ASIL DEĞERİ 61
'OLUP PROGRAM KOMUTLARINDAKİ GECİKMELER NEDENİ İLE 50 ALINMIŞTIR DAHA HASSAS
'BİR AYARLAMA GEREKEBİLİR. BİR SAATLE BİRLİKTE KONTROL EDİLEREK PIC SAATİ
'GERİ KALIYORSA 50 DEĞERİ AZALTILMALIDIR. İLERİ GİDİYOR İSE ARTIRILMALIDIR.
       
   

ete

Bu bir öğretmek amacı ile yazılmış bir örnek program. Açıklamasında rölenin aktif olduğu süreyi tuttuğu yazıyor ve tuttuğu zamanı saniye bazında tuttuğu belirtilmedigine göre zaman dakika ve saat cinsinden tutuluyor demektir. Bu durumda sorun anlamını yitiriyor değilmi?.
Ete

0nur

#33
Ben durumu anlatamadım sanırım..

Şimdi demek istediğim şu tam olarak. Mesela sistemin saati 00:00:25 iken ben röle 1 i aktif ettim. Sistemin saati 00:01:00 olduğunda röle 1 in saatinin 00:00:35 olması gerekiyor.Fakat rölenin saati de 00:01:00 oluyor.Dolayısıyla sistem saatinin saniye sayacı sıfırlandığında röle saatinin saniye sayacıda sıfırlanıyor ve sistem saatinin her 1 dakikalık peryodundan sonra röle saati sistem saatine ayak uyduruyor.

yukarıdaki örnekle devam edecek olursak;

sistem saati 00:01:00 olduğunda
röle saati de 00:01:00 oluyor halbuki 1 dk olması için 25 snlik bir zaman geçmesi gerekiyor.

bunu anlatmak istemiştim.

ete

Onur ,
Ya ben senin dediğini anlamıyorum yada sen gereksiz hassasiyet gösteriyorsun.
00:00:25 de set edilmiş bir rölede yalnızca set edildiği saniyede 25 sn lik eksikle röle saati 1 artırılır. sonrasında gelen saniyelerde ise normal artırım yapılmış olur. Bu durumda bi,tin röle saatinde sistem 25 sn lik eksikle zaman tutmuş olmazmı?. Burada bir kabul var saniye hesabına bakmıyoruz bunu anla lütfen.
Yinde de anlamadı ise sen doğrusunu yap buraya koy belki bende anlarım

Ete

s.atak

ete hocam merhaba

müsaitseniz ekteki rb chace kesmesi ile ilgili deneme çalışmama bir baksanız??
16f876 ile bir türlü çalıştıramadım. 16f628 de denemeler çalışyor. 16f876 nın altladığım bir yermi var acaba??
cevabınız için teşekkür ederim.
s.atak

ete

Birinci hata led bağlantın yanlış. Ledin Katod bacağı GND ye bağlı olması gerekirken +5V ta bağlamışsın. Onu düzelt bir kere.
İkincisi 16F6876 da A portu Analog dur. Bunu bir komut ile digital yapman gerekir. Aksi halde port beklediğin gibi çalışmaz.
Programın başına ADCON1=7 komutunu ilave et.

Kesme kullanılan programlarda Pause komutu hele pause 100 şeklinde komut kullanmak hatalıdır.
Zira kesme oluşsa bile program pause 100 komutunuicra etmeden kesme etiketine gidemez.
Bu nedenle pause 100 komutunu oradan kaldır. Gerekirse kesme kısmında önlem al yada döngü şeklinde gecikme yarat.
For I= 0 to 5000:next  şeklind eki bir komut işini görecektir.

Hepsi bu kadar
Ete

s.atak

hocam cevap için teşekkür ederim.

isis şemada nasıl böyle bir hata yapmışım anlamadım. kaç gündür bunula uğraşıyorum. kafa allak bullak olmuş.
ben programı denerken sizin rb chance kesme dersini aynen kullandım. 16f628 de pause 100 komutu varken de çalışıyordu.
peki şöyle başka bir soru sorayım.
aslında geçenlede de sormuştum adc hakkında idi ve cevabı da başka bir sitede vermiştiniz bende oradan deneme yaparak adc çevrimi ile zaman sınırlaması yapmayı başardım, fakat motorun çalışma zaman sınırlaması malesef pause sure*1000 şeklinde, bu durumda herhangi bir sensörden kesme gelse dahi ana programda pause komutu bitmeden kesmeye atlayamacak demektir.(yanlışım varsa lütfen düzeltin).
peki pause yerine adc den okudumuz ve zaman olarak tanımladığımız değişkeni (sure) motor hareketine nasıl aktarmam lazım ki motor o zaman aralığında çalışsın??
örnek kod:

BASLA:
INTCON.0=0
PORTB=255
DURUM=PORTB
ADCIN 0,RAW
SURE=((RAW+1)*/15)*1000

SERIN2 PORTA.2,396,[WAIT("SUAT"),ALICI]     
    IF ALICI=10 THEN SOL
    IF ALICI=20 THEN SAG
       
GOTO BASLA

SOL: 

MGERI=1:LEDG=1:UYARI=1 
pause SURE
MGERI=0:LEDG=0:UYARI=0
GOTO BASLA
                         ' burda motor çalışması pausedeki sure değişkenin durumuna göre çalışıyor.
bu komut icra ederken (pause) sensörden rb chance kesme ile bilgi geldiğinde kesmeye pause komutu bittikten sonra gidecek (doğru anladıysam)
pause nin yerine başka ne yada nasıl bir komut kullanmam lazım ??
yyazdığınız gibi for : next mi ??
bu komutu kullansam komut satırları icra edilirken kesme oluştuğunda kesmeye gidebilirmiyim ??
teşekkürler
s.atak
 

ete

En dogrusu adc den elde ettigin degeri for next dongusunde kullanarak gerekli sureyi saglamaktır.
Toplam suren maksimum 60000 ms olacagına gore dongu icine pauseus ler yerlestirmen gerekebilir.
Bunları bir yada birden fazla pauseus 5  Seklinde verirsen kesmeyi etkilememis olursun.
Ete

ugurkantar

merhaba arkadaşlar. bu tmr0 kesmesi hesabıyla ilgili bir şey soracam. 16f877A picini  20 mhz kristalle çalıştıracam. şöyle bir hesap yapıyorum  .tmr0 kesmesinin başlangıç değerini 6 yapacam bölme oranı1/4 olacak.
1/5000000*4*250=0,00002 buda 200us yapıyor.
10 ms bir kesme için sayaç değerini 50 oluyor. bu hesabım doğrumu.
tmr0 kesmesini değerinin tekrar 6 eşitlemem gerkiyormu?
birde ete hocamın bu dersinde şöyle demiş
1.   Sayıcının sayabilmesi için gerekli olan clock sinyalinin kaynağı ne olacaktır?. Bu kaynak dahili osilatör olabileceği gibi standart olarak PortA.4 /TOCKI bacağı kullanılarak dışarıdan bir sinyal kaynağı ile beslenebilir. Bu seçim OPTION yazmacının 5. biti olan TOCS biti ile yapılır.
TOCS biti = 0 ise sinyal kaynağı dahili osilatör dür.
TOCS biti = 1 ise sinyal kaynağı PortA.4 pinin den giren harici sinyal kaynağıdır.

dışarıdan picin osc1 ve osc2 ye krisatl bağlanınca bu haricimi oluyor dahilimi anlamadımda


ete

#40
Hesabın aşağı yukarı  doğru. Yalnızca komut gecikmelerini eklemek gerektiğini belirtmem gerek. Genelde 7 sayısı kadar bir komut çevrimi süreye eklenmelidir. Yani sen ön yükleme değerini 6 verdiğin zaman sayacın 7 den başlayıp 256 ya kadar sayacaktır. Aslında 250us lik bir süre geçecek gibi gözüksede komut gecikmeleri nedeni aslında 257us lik bir süre geçer. Bu nedenle ön yükleme değerine komut gecikmelerini eklersen daha hassas bir zamanlama elde edersin.

TMR0 iki kaynaktan beslenebilir. Birincisi dahili osilatör yada pic e bağlanan kristaldir. Bu otomatikman pic in çalışmasını sağlayan her bir clk palsi TMR0 sayacınıda saydırır.
Diğeri ise PORTA.4 pininden girilen kare dalga dır. Buradan girilen sinyal yada pulslar TMR0 saydırabilir. Terim kargaşası yaratmamak için TMR0 dahili clk kaynağından sinyal alabilir diyelim. Dahili CLK kaynağı ise 16F628'i göz önüne alırsak Dahili Osilatörden çalıştırılabilir yada OSC bacaklarına Kristal bağlanarak çalıştırılabilir.
Bunların hiç birisi harici kaynak sayılmıyor. Çünki hepside sistem osilatörünü çalıştıran kaynaklardır.
Yalnızca PORTA.4 pininden yapılan giriş harici kaynak sayılmaktadır.
Bu arada her kesme sonunda tmr0 değerini yeniden 6 yapman gerekiyor elbette.

Ete


ugurkantar

Hocam verdiğiniz bilgiler için çok teşekkur ederim. Komut gecikmesi ile dediğinizi dikkate alacam hocam.

ugurkantar

Ete hocam benim yapmak istediğim şu. 16f877A 8 adet analog/dijital çevirme yapmak istiyorum. Okuma işlemini yaperken bana her 10 ms deki değeri lazım. bunun için tmr0 kesmesini kullanmaya çalıştım . ama yapamadım. Programın başında  değer okuyor Başkada okumuyor . Acaba hatayı nerde yapıyorum.

 DEFINE OSC 20
'****************************************************************
TRISA=%101111
TRISE=$FF
TRISC=%00000000
TRISB=%00000000
'****************************************************************
PORTA=0
PORTB=0
PORTC=0
PORTD=0
PORTE=0
'****************************************************************
ADCON1 = %10000000
CMCON=7
'****************************************************************

OPTION_REG=%10000001 'Pull up dirençleri PTAL- Bölme oranı 1/4.
INTCON=%10100000 'Kesmeler aktif ve TMR0 kesmesi aktif
TMR0=13
'****************************************************************
Define ADC_BITS     10  ' Set number of bits in result
Define ADC_CLOCK     3  ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50  ' Set sampling time in uS

'****************************************************************
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_EREG PORTB 'LCD Enable Bacağı Hangi Porta bağlı?
DEFINE LCD_EBIT     3 'LCD Enable Bacağı Hangi bite bağlı ?
define LCD_RWREG    PORTB  'LCD R/W Bacağı Hangi Porta bağlı?
define LCD_RWBIT    2       'LCD R/W Bacağı Hangi bite bağlı ?
DEFINE LCD_RSREG PORTB 'LCD RS Bacağı Hangi Porta bağlı ?
DEFINE LCD_RSBIT    1 'LCD RS bacağı Hangi Bite bağlı  ?
DEFINE LCD_BITS 4 'LCD 4 bit olarak bağlı
DEFINE LCD_LINES 2 'LCD 2 sıra yazabiliyor
DEFINE LCD_COMMANDUS 2000    'Komut geçikme süresi mikrosaniye cinsinden
DEFINE LCD_DATAUS 50
'****************************************************************
SAY VAR WORD
SEN0 VAR WORD
SEN1 VAR WORD
SEN2 VAR WORD
SEN3 VAR WORD
SEN4 VAR WORD
SEN5 VAR WORD
SEN6 VAR WORD
SEN7 VAR WORD
ON INTERRUPT GoTo KESME
BASLA:

lcdout $fe,$c0,#sen0
goto basla
DISABLE
KESME:
SAY=SAY+1
IF SAY=51 THEN
  ADCIN 0,SEN0
   ADCIN 1,SEN1
    ADCIN 2,SEN2
     ADCIN 3,SEN3
      ADCIN 4,SEN4
       ADCIN 5,SEN5
        ADCIN 6,SEN6
         ADCIN 7,SEN7
     
ENDIF
INTCON.2=0 'TMR0 Kesme bayragı sıfırlanıyor   
TMR0=13
RESUME
ENABLE



ugurkantar

Hatayı buldum nasıl gözden kaçırmışım anlamadım.Say değerini sıfırlamamışım..

Hattuşa

slm ete hocam;
bir noktada tıkandım, yardımlarınıza ihtiyacım var, sorunum kısaca şu şekilde;
elimde 18F4520 var ve ben bu işlemcinin RB0 girişine resimdeki gibi 100 hertzlik (10mS çevrimli) bir pulse girişim var, RB0 kesmesi ile bu pulsenin yükselen kenarını yakalıyorum. bu yükselen kenardan ortalama olarak 500uS sonra 1 ADC okutmam lazım, okutacağım ADC 50 adet ve bu 50 adet adc yi her bir yakalamada 1 kez yapıyorum, bu ADC okutma işlemi kesmenin içinde yapıldığı zaman işlemci hali ile sapıtıyor, bunu kesme dışında yapmam lazım ve 50 okuma işleminden sonra kesmeyi kapatıp ana programa dönüyorum, algoritmam şu şekilde (kaba bir tabirle)

GIE =0
ANA PROGRAM:
gosub hesap
gosub ekrana yaz
gosub buton işlemleri
goto alt program

Altprogram:
GIE =1
alt:
işte bu noktada RB0 kesmesinden pulseyi yakalayıp
adc değerlerini okumak ve kesmeyi kapatarak ana programa tekrar dönmek istiyorum

GIE =0
goto ANA PROGRAM



sizce nasıl yapabilirim. hocam INT0IF =1 bayrağını kontrol ederek ben beceremedim, mantıken olması lazımdı sanırım, ama olmadı

Powered by EzPortal