Elektronik / Elektronik Kaynakları/

PICBasic Dersleri PIC Basic Pro ile PIC Programlama 6

Sponsorlu Bağlantılar

KESME (INTERRUPT) KULLANIMI: Tüm bilgisayarlar ve mikroislemci sistemlerinde kullanılan bir özelliktir. Basitçe açıklamak gerekirse, bir mikroislemciye kesme anında neler yapması gerektigi bir program bölümü seklinde verilir. Açıkçası mikro islemci kesme oluştugu anda yaptıgı isi tamamen bırakarak kesme bölümüne gider ve orada gösterilen isleri yapar. Kesme bölümünün sonunda tekrar geriye dön komutunu alır ve önceden yaptıgı ise kaldıgı yerden devam etmek üzere döner.

Bu olayı günlük hayatımızda yasadıgımız bir örnekle açıklayalım isterseniz. Diyelim ki bir evde yasıyorsunuz ve bir gün tüm aileyi topladınız. Amacınız aileye bir yangın olması durumunda ne yapılması gerektigini ögreteceksiniz. Burada yangının meydana gelmesi bir kesme olayı olacaktır. Normal yasama düzeninde hiç yangın olmaz ise kesme oluşmayacak demektir. Ama oluşma ihtimali her zaman olacaktır. Simdi bir aksam yemegi esnasında yangın çıktıgını varsayalım. Kesme oluşacak ve herkes önceden ögretildigi gibi görevinin basına kosacak. Yangın söndürülecek ve her kes yemege geri dönecektir. iste tipik bir kesme olayına

örnek. Kesme olayını kısaca açıkladıktan sonra Pic islemcilerinde hangi olayların kesme yaratabilecegine bir göz atalım.

RB0/INT KESMESİ:
En çok kullanılanlardan birisi PortB.0 pininde meydana gelen lojik seviye degisikliginin oluşturacagı kesme dir. Option Yazmaçının 6. biti önceden ayarlanarak kesmenin sıfırdan – bir konumuna geçiste mi yoksa bir konumundan – sıfır konumuna geçiste mi oluşturulacagı belirlenir.

OPTION_REG.6=0 olur ise RB0 da düsen kenarda kesme oluşur.
OPTION_REG.6=1 olur ise RB0 da yükselen kenarda kesme oluşur.

Düsen veya yükselen kenar terimi bir clock palsının kenar sekli olarak anlasılmalıdır. Kesme isleminin aktif edilebilmesi için INTCON (interrupt control registeri) yazmaçı kullanılır.

Örnegin RB0 kesmesinin aktif hale getirilebilmesi için;
INTCON.4=1 yapılmalı ve daha sonra ;
INTCON.7=1 degeri 7 nolu bite verilerek tüm kesmeler açılmalıdır.
Bu iki deger tek bir komutlada verilebilir. Söyle,
INTCON=%10010000

Bu kesme aktif hale getirildikten sonra sayet bir kesme oluşur ise INTCON yazmaçı nın 1 nolu biti 0 konumundan 1 konumuna geçer. Bu bit sayet tekrar 0 konumuna program içinde getirilmez ise yeniden bir kesme oluşmaz. Bu nedenle programın KESME bölümünde bu bit sıfırlanmalıdır. RB0/INT Kesme kullanımını toparlamak gerekir ise;

RB0/INT kesmesini kullanmak için yapılması gerekenler sırası ile;
– Programın bas kısmına ON INTERRUPT GOTO KESME komutu verilerek kesme oluştugunda programın gidecegi yer (KESME) belirlenir.

RB0 pini giris olarak ayarlanacak
– Gerekir ise Option Yazmaçının 7. biti 1 veya 0 yapılarak pullup dirençleri istege göre ayarlanacak.

– Option Yazmaçının 6 biti 1 veya 0 olarak ayarlanarak kesmenin düsen kenar veya yükselen kenardamı olacağına karar verilecek.

– Intcon yazmaçına INTCON=%10010000 degeri verilerek kesme aktif hale getirilecek.

– Kesme bölümüne baslarken DISABLE komutu verilerek kesme anında yeniden kesme oluşumuna imkan verilmeyecek.

– Kesme bölümünde INTCON.1=0 komutu verilerek kesmeden dolayı 1 olan bayrak tekrar sıfırlanır ve sonradan yeni kesme oluşmasına imkan tanınır.

– Kesme bölümünün sonunda RESUME komutu verilerek programın kesme oluşmasından önceki yerine dönmesi saglanır.

– En sona ENABLE komutu yazılarak kesmeden dönüldükten sonra tüm kesmeler aktif hale getirilir.

Simdi de ögrendiklerimizi bir örnek vererek açıklayalım. Örnek Programımız RB0 bacagına baglı bir tus yardımı ile RA.0 bacagına baglı olan bir led’i yakıp söndürsün. Program içinde tusa basıldı mı? seklinde bir komut vermeden direkt kesme özelliginden yararlanacagız.

Yani RB0 bacagını sürekli 1 konumunda tutacağız (pullu up ile). Dolayısıyla bu bacagı tusa basarak sıfıra çekersek kesme oluşacak ve kesme bölümünde de led’i toggle komutu ile yanıksa söndürecegiz, sönük ise yakacagız. Tabiiki seçim olarak RB0/INT bacagı düsen kenar da kesme oluşacak sekilde ayarlanacaktır. Önce semamızı verelim;

kesme-devre-semasini-verelim

iste Programımız;


‘****************************************************************
‘* Name : KESME-RB0.BAS *
‘* Author : [Erol Tahir Erdal] *
‘* Notice : Copyright (c) 2005 [ETE] *
‘* : All Rights Reserved *
‘* Date : 23.04.2005 *
‘* Version : 1.0 *
‘* Notes : *
‘* : *
‘****************************************************************
PORTA=0
TrisA=%00000000
TrisB=%00000000
‘—————————————————————–
@ DEVICE pic16F628 ‘islemci  16F628
@ DEVICE pic16F628, WDT_on  ‘Watch Dog timer açık
@ DEVICE pic16F628, PWRT_ON  ‘Power on timer açık
@ DEVICE pic16F628, PROTECT_OFF ‘Kod Koruma kapalı
@ DEVICE pic16F628, MCLR_OFF  ‘MCLR pini kullanılmıyor.
@ DEVICE pic16F628,  INTRC_OSC_NOCLKOUT ‘Dahili osilatör kullanılacak
‘—————————————————————–
ON INTERRUPT GoTo KESME ‘kesme oluşursa KESME adlı etikete git.
OPTION_REG=%0000000 ‘dahili  Pull up dirençleri aktif edildi ayrıca pullup direncine gerek yok
INTCON=%10010000 ‘Tüm  Kesmeler aktif ve RB0/INT kesmesi aktif
TRISB=%00000001 ‘PortB.0  giris digerleri çıkıs yapıldı.
TRISA=%00000000 ‘A portu  tamamı çıkıs yapıldı.
CMCON=7 ‘16F628 de  komparatör pinleri iptal hepsi giris çıkıs
‘—————————————————————–
SYMBOL TUS=PORTB.0
SYMBOL LED=PORTA.0
‘——————————————————————-
BASLA: ‘Ana program  bölümünde program bir sey yapmayacak
pauseus 100 ‘kesme  oluşmadıgı müddetçe program
goto basla ‘ bu satırlar  arasında dolasır
DISABLE ‘yeniden kesme  oluşması önleniyor
KESME: ‘program buraya  geldiginde kesme oluşmus demektir.
TOGGLE LED ‘LED konum  degistirdi
PAUSE 1
INTCON.1=0 ‘RB0/INT Bayragı (flag) silindi.
Resume ‘geldigin yere dön
Enable ‘kesmeler yeniden  aktif.
End
‘————————————————————————

B portunda dahili pullup dirençleri vardır ve OPTION Yazmaçının 7. biti bunların aktif olup olmamasını kontrol eder. Sayet bu bit 0 ise dirençler aktif, 1 ise dirençler devrede degildir. Sanırım örnek her seyi açıkça anlatıyor. Burada özellikle dikkat edilecek yer ana program bölümünde pauseus 100 komutundan baska bir komut olmadıgıdır. Normal olarak program kesme oluşuncaya kadar sürekli Basla etiketi ile Goto basla komutu arasında dönüp duracaktır. Buraya kadar açıklananlar yalnızca RB0/INT kesmesinin kullanımına örnektir.

PORTB (RB4-RB7) DEGİSİKLİK KESMESİ :

Bu kesme tipinde RB4-RB7 bacaklarının mevcut konumlarında oluşacak bir degisiklik sonucunda da kesme oluşturulmaktadır. Bu kesme PORTB nin RB4-RB7 arası bacaklarının tamamının giris yapılması halinde geçerlidir. Bacaklardan birisi çıkıs yapılır ise kesme iptal olur.

Kesme bir kere aktif hale getirilir ise bu 4 adet bacak degeri sürekli pic tarafından okunur. Okunan deger bir önceki ile karsılastırılır. Sayet fark var ise kesme oluşur. Kesme de oluşan RBIF bayragının silinmesi için PortB nin bir kere programcı tarafından mutlaka okutulması gerekir. Aksi taktirde bayrak silinemez ve sürekli kesme oluşur.

Tabiiki yalnızca PortB nin okunması bayragı silmeye yetmeyecektir. Ayrıca RBIF bayragının
kesme bölümünde silinmesi de gerekir. RB PORT (Rb4-Rb7) Degisiklik Kesmesinin oluşması İçin Gerekenler :

Programın bas kısmına ON INTERRUPT GOTO KESME komutu verilerek kesme oluştugunda programın gidecegi yer (KESME) belirlenir.

RB4-RB7 pinleri mutlaka giris olarak ayarlanacak

– Intcon yazmaçının 3 biti bu kesme için ayrılmıstır. Bu bit 1 yapılarak kesme aktif edilir. INTCON=%10001000 degeri verilerek kesme aktif hale getirilecek.

– Kesme bölümüne baslarken DISABLE komutu verilerek kesme anında yeniden kesme oluşumuna imkan verilmeyecek.

– Kesme Bölümünde DURUM=PORTB seklinde port degeri okunacak

– Kesme bölümünde INTCON.0=0 komutu verilerek kesmeden dolayı 1 olan bayrak tekrar sıfırlanır ve sonradan yeni kesme oluşmasına imkan tanınır.

– Kesme bölümünün sonunda RESUME komutu verilerek programın kesme oluşmasından önceki yerine dönmesi saglanır.

En sona ENABLE komutu yazılarak kesmeden dönüldükten sonra tüm kesmeler aktif hale getirilir

Bu kesmeyi bir örnekle açıklayalım. Bu defa yine PortA.0 pinine bir LED baglı olsun. PortB.7 pinine bir Tus baglayalım ve bu sefer tus, pulldown yani GND ye çekili olsun. Tusa basılınca PortB.7 pinine High
uygulayalım.

İste baglantı semamız;

kesme-baglanti-semasi

Program RB (4-7) Degisiklik Kesmesi:

 ‘****************************************************************
‘* Name : KESME-RBCH.BAS *
‘* Author : [Erol Tahir Erdal] *
‘* Notice : Copyright (c) 2005 [ETE] *
‘* : All Rights Reserved *
‘* Date : 23.04.2005 *
‘* Version : 1.0 *
‘* Notes : *
‘* : *
‘****************************************************************
PORTA=0:portb=0
TRISB=%11110000 ‘PortB tamamı giris yapıldı.
TRISA=%00000000 ‘A portu  tamamı çıkıs yapıldı.
‘—————————————————————–
@ DEVICE pic16F628 ‘islemci  16F628
@ DEVICE pic16F628, WDT_on  ‘Watch Dog timer açık
@ DEVICE pic16F628, PWRT_ON  ‘Power on timer açık
@ DEVICE pic16F628, PROTECT_OFF ‘Kod Koruma kapalı
@ DEVICE pic16F628, MCLR_off  ‘MCLR pini kullanılmıyor.
@ DEVICE pic16F628,  INTRC_OSC_NOCLKOUT ‘Dahili osilatör kullanılacak
‘—————————————————————–
ON INTERRUPT GoTo KESME  ‘kesme oluşursa KESME adlı etikete git.
OPTION_REG=%10000000 ‘dahili  Pull up dirençleri iptal edildi
INTCON=%10001000 ‘Kesmeler  aktif ve RB CHANGE kesmesi aktif
CMCON=7 ‘16F628 de  komparatör pinleri iptal hepsi giris çıkıs
‘—————————————————————–
DURUM VAR BYTE
SYMBOL TUS=PORTB.0
SYMBOL LED=PORTA.0
SYMBOL RBIF=INTCON.0
‘——————————————————————-
BASLA: ‘Ana program bölümü
DURUM=PORTB
PAUSEUS 100
GOTO BASLA
DISABLE ‘yeniden kesme  oluşması önleniyor
KESME: ‘ burada kesme oluştu  demektir.
TOGGLE LED ‘LED konum  degistirdi
PAUSE 300
DURUM=PORTB ‘PortB degeri okundu
RBIF=0 ‘INTCON.0=0 yapıldı  yani RB CHANGE Bayragı (flag) silindi.
RESUME ‘geldigin yere dön.
ENABLE ‘kesmeler yeniden  aktif.
End

TMR0 KESMESİ : Ram bellegin 01 adresinde bulunan özel bir yazmaçdır. Genellikle adı üstünde zamanlayıcı olarak kullanılır. 8 bitlik bir sayıcıdır. Yazılabilir okunabilir. Programlanabilen bir özel bölücüsü (prescaler) vardır. Harici veya dahili clock palsları ile sayım yapabilir.

Sayma yönü daima artan yöndedir. Bu sayıcı veya zamanlayıcı 255 degerini astıgı zaman degeri tekrar sıfır olur ve bu anda bir kesme oluşturulabilir. Bu sayıcının diger önemli bir özelligi ise arka planda yani ana programdan bagımsız çalısmasıdır. Ana program çalısırken veya kesme oluştugu andan
itibaren saymasına devam eder.

OPTION Yazmacının ilk üç biti frekans bölme (prescaler) ayarlaması için kullanılır. Bu üç bitin aldıgı degerlere göre bölücünün aldıgı degerler asagıda gösterilmistir. Bu bölücü aynı zamanda WDT içinde kullanıldıgından tabloda WDT için bölücü degerleride gösterilmistir.

tmr0-kesmesi-ram-picbasic

Tablodan da anlasılacagı üzere sinyal kaynagından gelen palsların TM0 sayıcısını 1/1 yani direkt saydıracagı bir konum mevcut degildir. Özellikle dısarıdan bir sinyal kaynagından gelen palsların sayılmasında lazım olacak olan bu husus için OPTION yazmacının 3. biti 1 (bir) yapılarak frekans bölme islemi WDT için yapılır.

Bu bir nevi aldatmadır. Bölme WDT için yapılınca Frekans bölücü TM0 için Bay-Pass edilmis yani atlanmıs olur. Dolayısıyla gelen sinyaller 1/1 olarak Timer0 tarafından sayılır. Bunu yapacagımız örnekte görecegiz. TM0 sayısının kullanılması için bazı parametrelerin önceden ayarlanması gerekiyor. Bunlar sırası ile;

1. Sayıcının sayabilmesi için gerekli olan clock sinyalinin kaynagı ne olacaktır?. Bu kaynak dahili osilatör olabilecegi gibi standart olarak PortA.4 /TOCKI bacagı kullanılarak dısarıdan bir sinyal kaynagı ile beslenebilir. Bu seçim OPTION yazmacının 5. biti olan TOCS biti ile yapılır.

TOCS biti = 0 ise sinyal kaynagı dahili osilatör dür. TOCS biti = 1 ise sinyal kaynagı PortA.4 pinin den giren harici sinyal kaynagıdır.

2. Harici sinyal kaynagı seçilir ise, sayacın düsen kenarda mı yoksa yükselen kenarda mı sayma isini yapacagı OPTION yazmacının 4. biti olan TOSE biti ile ayarlanır.

TOSE Biti = 0 ise düsen kenarda sayma
TOSE Biti = 1 ise Yükselen kenarda sayma yapılır.

3. Frekans bölme islemi TMR0 için mi yoksa WDT için mi geçerli olacaktır? Bunu seçmek için OPTION yazmacının 3. biti olan PSA biti kullanılır.

PSA Biti = 0 ise Frekans Bölme TMR0 için geçerli,
PSA Biti = 1 ise Frekans Bölme WDT için geçerli olur.

4. Son olarak da Frekans bölme kullanılacak ise degeri ayarlanır. Bunun içinde OPTION yazmacının ilk 3 bitinin kullanıldıgını söylemistik. Tabloda verdigimiz degerlerden biri seçilerek OPTION yazmacına yazılır.

5. Programın bas kısmına ON INTERRUPT GOTO KESME komutu verilerek kesme oluştugunda programın gidecegi yer (KESME) belirlenir.

6. INTCON yazmacının 5. biti bu kesme için ayrılmıstır. Bu bit 1 yapılarak kesme aktif edilir.

7. Kesme bölümüne baslarken DISABLE komutu verilerek kesme anında yeniden kesme oluşumuna imkan verilmeyecek.

8. Kesme bölümünde INTCON.2=0 komutu verilerek kesmeden dolayı 1 olan bayrak tekrar sıfırlanır ve sonradan yeni kesme oluşmasına imkan tanınır.

9. Kesme bölümünün sonunda RESUME komutu verilerek programın kesme oluşmasından önceki yerine dönmesi saglanır.

10. En sona ENABLE komutu yazılarak kesmeden dönüldükten sonra tüm kesmeler aktif hale getirilir. Burada bir konuyu açıklamakta fayda görüyorum. Dahili veya harici osilatör kullanılması durumunda, frekans degerinin Pic’e baglı kristal degerinin dörtte biri olacağını bilmeniz gerekiyor. Diyelimki Pic 4 MHz lik bir kristal ile çalısıyor. O halde TMR0 için kullanılacak sinyal kaynagı 1 MHz frekansa sahip olacaktır.

Dahili osilatör ve Frekans bölücü pek çok uygulamalarda kullanılır. Özellikle hassas zamanlama islerinde önemli bir kullanım alanı vardır. Bunların basında Pic’in bir saat olarak kullanılması gelir. Dahili veya harici ösilatör ve frekans bölücü kullanılarak pic’in her bir saniyede bir kesme oluşturmasını saglayabiliriz. Sayet bu zamanı hassas bir sekilde ayarlayabilir isek dogru çalısan bir saat yapabiliriz. Simdi bunu bir örnek ile açıklayalım.

Yapacagımız örnek de 4 MHz de çalısan bir PIC16F628 kullanacagız. Dahili sinyal kaynagını kullanarak gelen sinyali 64’e bölecegiz. Bu durumda pic, TMR0’ ile 0 dan baslayıp 255’e kadar sayıp kesme oluşturabilmesi için ;

1 us x 64 x 256 = 16384 us süre kullanacaktır. 1 sn = 1000 ms ve oda 1000.000 us ye esit oldugundan sayet 1.000.000 us degerini 16384’e bölersek 61 degerini buluruz. O halde her kesme oluştugunda bir baska degiskeni saydırır ve bunun degeri 61 den 62 ye geçtigi anda degerini sıfırlayıp saniye degerini bir artırırsak bir saniyelik saat palslarını yakalamıs oluruz. Bunu bir programda kullanarak da saat yapabiliriz.

Bu örnek için bir semamız asagıdadır.

tmr0-ornek-devre-semasi-picbasic

Programa geçmeden önce gerekli parametrelerimizi tespit edelim; Tespitlerimizin etki alanı OPTION Yazmacı olacağından tüm tespitleri Binary olarak bu yazmaca isleyecegiz.

1. Sinyal kaynagımız dahili osilatör olacaktır. O halde TOCS (5.bit) 0 olacaktır.
OPTION_REG=%00000000

2. Frekans Bölme islemi TMR0 için olacak olup 3. bit 0 olacaktır.
OPTION_REG=%00000000

3. Frekans bölme (prescaler) degeri 64 olacak olup bunun TMR0 için bit karsılıgı 101 dir.

OPTION_REG=%00000101

4. TMR0 kesmesini kullanacagımızdan INCON yazmacının 5. biti high olacaktır. Tüm Kesmeleri açmak için INTCON 7. biti high olacağından bu iki durumu tek komutta toparlarsak, INTCON=%10100000 seklinde bir komut yazmamız gerekir. Bu asamadan sonra programımızı verelim.

‘****************************************************************
‘* Name : KESMETMR0.BAS *
‘* Author : [Erol Tahir Erdal] *
‘* Notice : Copyright (c) 2005 [ETE] *
‘* : All Rights Reserved *
‘* Date : 23.04.2005 *
‘* Version : 1.0 *
‘* Notes : *
‘* : *
‘****************************************************************
PORTA=0:portb=0
TRISB=%00000000 ‘PortB tamamı çıkıs yapıldı.
TRISA=%00000000 ‘A portu  tamamı çıkıs yapıldı.
‘—————————————————————–
@ DEVICE pic16F628 ‘islemci  16F628
@ DEVICE pic16F628, WDT_OFF  ‘Watch Dog timer kapalı
@ DEVICE pic16F628, PWRT_ON  ‘Power on timer açık
@ DEVICE pic16F628, PROTECT_OFF ‘Kod Koruma kapalı
@ DEVICE pic16F628, MCLR_off  ‘MCLR pini kullanılıyor.
@ DEVICE pic16F628,  INTRC_OSC_NOCLKOUT ‘Dahili osilatör kullanılacak
‘—————————————————————–
DEFINE LCD_DREG PORTB ‘LCD  data bacakları hangi porta baglı?
DEFINE LCD_DBIT 4 ‘LCD data  bacakları hangi bitten baslıyor?
DEFINE LCD_EREG PORTB ‘LCD  Enable Bacagı Hangi Porta baglı?
DEFINE LCD_EBIT 3 ‘LCD  Enable Bacagı Hangi bite baglı ?
define LCD RWREG PORTB ‘LCD  R/W Bacagı Hangi Porta baglı?
define LCD_RWBIT 2 ‘LCD R/W  Bacagı Hangi bite baglı ?
DEFINE LCD_RSREG PORTB ‘LCD  RS Bacagı Hangi Porta baglı ?
DEFINE LCD_RSBIT 1 ‘LCD RS  bacagı Hangi Bite baglı ?
DEFINE LCD_BITS 4 ‘LCD 4 bit  mi yoksa 8 bit olarak baglı?
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 giris çıkıs
‘—————————————————————————-
SAYAC VAR BYTE
SN VAR BYTE
DAK VAR BYTE
SAAT VAR BYTE
GUN VAR BYTE
‘—————————————————————————–
CLEAR ‘tüm degiskenler  sıfırlandı
PAUSE 200
LCDOUT $FE,1
LOW PORTB.2 ‘LCD -R/W bacagı LOW’a çekildi.
‘—————————————————————————–
BASLA:
LCDOUT $FE,$84,DEC2 SAAT,”:”,DEC2  DAK,”:”,DEC2 SN
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=SN+1 ’saniye degeri bir  artırılıyor
IF SN=60 THEN ’saniye 60  olmus ise 1 dakika süre geçti o halde
SN=0 ‘ saniye sıfırlanıyor
DAK=DAK+1 ‘ dakika degeri  bir artırılıyor
IF DAK=60 THEN ‘dakika 60  olmus ise 1 saat süre geçti
DAK=0 ‘ dakika sıfırlanıyor
SAAT=SAAT+1 ‘ saat degeri  bir artırılıyor
IF SAAT=24 THEN ’saat 24  olmus ise 1 gün geçti
SAAT=0 ’saat sıfırlanıyor
GUN=GUN+1 ‘gün degeri bir  artırılıyor
IF GUN=365 THEN GUN=0 ‘gün  365 olmus ise
ENDIF ‘gün sıfırlanıyor 1  yıl geçti
ENDIF
ENDIF
ENDIF
INTCON.2=0 ‘TMR0 Kesme bayragı sıfırlanıyor
RESUME
ENABLE
END
‘———————————————————————————–

Her ne kadar hesap sonucunda kesmenin oluşturacagı gecikme yaklasık 1 sn hesaplanmıs isede pratikte program komutlarınında bir gecikmeye sebep olacağı unutulmamalıdır. Yukarıdaki programda KESME bölümünde bir çok komut bulunmaktadır. Makine dilinde her bir komut yaklasık (4MHz de) 1 us süre almaktadır. Bu nedenle hesaplama dogru olsa da saat ileri gidebilir veya geri kalabilir. Bunun için SAYAC degeri her 61 kesme yerine 60 – 59 -58 kesmede bir saniye artırımı yaptırılabilir. En iyisi programın yazılması tamamlanınca bir dogru çalısan bir saat yardımı ile süre karsılastırması yapılmalı ve gerekirse SAYAC degeri ile oynanarak hassas bir ayarlama yapılmalıdır.

Burada ikinci bir örnek daha verecegiz ve saat’in baska ilerde nasıl kullanılacagına bakacagız. Diyelim ki 4 adet tus ile kontrol edilen 4 adet rölemiz var ve bunlar bir takım sistemleri çalıstırıyorlar. Her bir röle ayrı bir sistemi çalıstırıyor ve biz hangi sistemin ne kadar çalıstıgını bilmek istiyoruz. İste yazacagımız program 4 adet tus yardımı ile 4 adet röleyi çalıstıracak ve arka planda ise TMR0 kesmesi yardımı ile saatimiz çalısacak.

Bu programda ayrıca yeni bir degisken tipi ile tanısacagız. Dizi degiskeni. Dizi degiskenleri aynı isimle açılırlar ancak her bir degiskenin bir indeks denilen parametresi vardır. Indeks ayrı bir degisken altında saklanabilir ve degeri degistirilerek istenilen dizi degiskenine kolaylıkla ulasılabilir. Kullanımı degisken tanımlarında söyle yapılmaktadır.

DEGER var Byte [4] burada deger adlı degiskenin 4 ayrı indeksli çesidi vardır. Bunlar ;

DEGER[0] – DEGER [1] – DEGER [2] ve DEGER [3] dür.

Önce programla ilgili semamızı verelim;

kesme-role-lcd-picbasic

Dikkat edilirse semada röle yerine logic prop baglanmıstır. Bunların yerine asıl devrede birer role baglanacaktır. Ancak asıl amacımız programın islevini göstermek oldugundan detaya girilmemistir.

İste programımız;


‘****************************************************************
‘* Name : KESME-R0LE.BAS *
‘* Author : [E.Erdal] *
‘* Notice : Copyright (c) 2005 [ETE] *
‘* : All Rights Reserved *
‘* Date : 23.04.2005 *
‘* Version : 1.0 *
‘* Notes : *
‘* : *
‘****************************************************************
PORTA=0:portb=0
TRISB=%00001111 ‘PortB (RB4-RB7) çıkıs digerleri giris yapıldı.
TRISA=%00000000 ‘A portu  tamamı çıkıs yapıldı.
‘—————————————————————–
@ DEVICE pic16F628 ‘islemci  16F628
@ DEVICE pic16F628, WDT_OFF ‘Watch Dog timer kapalı
@ DEVICE pic16F628, PWRT_ON ‘Power on timer açık
@ DEVICE pic16F628, PROTECT_OFF  ‘Kod koruma 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 baglı?
DEFINE LCD_DBIT 0 ‘LCD data  bacakları hangi bitten baslıyor?
DEFINE LCD_EREG PORTA ‘LCD  Enable Bacagı Hangi Porta baglı?
DEFINE LCD_EBIT 7 ‘LCD  Enable Bacagı Hangi bite baglı ?
DEFINE LCD_RSREG PORTA ‘LCD  RS Bacagı Hangi Porta baglı ?
DEFINE LCD_RSBIT 6 ‘LCD RS  bacagı Hangi Bite baglı ?
DEFINE LCD_BITS 4 ‘LCD 4 bit  mi yoksa 8 bit olarak baglı?
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 giris çıkıs
‘—————————————————————————-
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 degiskenler  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 İSİ 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 degeri bir artırılıyor
ATLA: IF SN[0]=60 THEN  ’saniye 60 olmus 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 degeri bir artırılıyor
IF DAK[0]=60 then ‘dakika 60  olmus 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 degeri bir artırılıyor
IF SAAT[0]=24 THEN ’saat 24  olmus ise 1 gün geçti
SAAT[0]=0
SAAT[ROLE]=0 ’saat sıfırlanıyor
GUN=GUN+1 ‘gün degeri bir  artırılıyor
IF GUN=365 THEN GUN=0 ‘gün  365 olmus ise
endif ‘gün sıfırlanıyor 1  yıl geçti
ENDIF
ENDIF
ENDIF
INTCON.2=0 ‘TMR0 Kesme bayragı sıfırlanıyor
RESUME
ENABLE
END
‘—————————————————————————–

Sayac=61 satırında 61 sayısı 1 sn lik süreyi ayarlamaktadır. Program komutlarındaki gecikmeler nedeni daha hassas bir ayarlama gerekebilir. Bir saatle birlikte kontrol edilerek pic saati geri kalıyorsa degeri azaltılmalıdır. İleri gidiyor ise artırılmalıdır. Programla iligli genel açıklamalar; Bu programda ileri programlama teknikleri kullanılmıstır. Program satırlarını esas alarak açıklamaya çalısalım.
‘——————————————————————————————————–
LCDOUT $FE,$84,DEC2 SAAT[0],”:”,DEC2 DAK[0],”:”,DEC2 SN[0]
‘——————————————————————————————————–
Programda saat için 5 adet indeks li degisken kullanılmıs idi. Bunun amacı her bir röle için ayrı bir zaman tutmak ve sıfır ile çalısan indeks degerini de ana saat için kullanmaktır. Yani saat(0) sistemin ana saati olacak Saat(1-4) arası ise her bir röleye ait olacaktır. Yukarıdaki komutta görüldügü gibi [0] indeksi kullanılmıs ve dolayısıyla sistem ana saati LCD üst satırında ekrana verilmistir.
‘——————————————————————————————————–
DURUM=PORTB & %1111
‘——————————————————————————————————–
Bu komutta Tusların hangisine basıldıgını kontrol etmek için tek bir komut kullanılmıstır. PORTB degeri okunarak 15 (%1111) sayısı ile AND islemi uygulanmıstır. Dolayısıyla PortB nin ilk 4 biti filtre edilerek ayrılmıs olacak ve bu bitlerden hangisi 1 ise (tusa basılmıs ise) belirlenecektir.

‘——————————————————————————————————–
IF DURUM>0 THEN PORTB=DURUM
‘——————————————————————————————————–
Burada herhangi bir tusa basılmıs ise eski basılmıs olanı iptal etmek ve yenisini devreye sokmak için bu komut kullanılmıstır.
‘——————————————————————————————————–
AKTIF=PORTB | DURUM*16
‘——————————————————————————————————–
Burada basılan tusa paralel olarak hangi rolelin aktif hale getirilecegi hesaplanmaktadır. Bir yerde basılan tuşun bit degeri 4 bit sola kaydırılarak PortaB ye verilmektedir. Hangi rölenin aktif oldugunu ise asagıdaki komut hesaplamaktadır.
‘——————————————————————————————————–
ROLE=NCD AKTIF ‘NCD KOMUTU SAYIDAKİ EN YÜKSEK HİGH OLAN BİTİ VERİR
‘——————————————————————————————————–
NCD komutu bir sayı içindeki en yüksek degerlikli high olan bitin konumunu verir. Örnek vermek gerekir ise SAYI=%00010000 ise NCD SAYI komutu bize 5 sayısını verecektir. En yüksek high 5. sıradaki 1 dir. Bu komut yardımı ile basılan tusa göre hangi rolenin aktif oldugunu belirliyoruz. Ancak bu belirleme bize PORTB deki sırayı verecektir.

Yani 4-8 arası bir deger. Halbuki biz 1. Role – 2. Role … 4.Role demek isteriz. Dolayısıyla bu degeri 1-4 arası degere indirgememiz gerekir. Burada islem aslında basit Hesaplanan degerden 4 çıkartır isek bize 1-4 arası degeri verir. Ancak ya deger 0 (sıfır) ise. Bu durumda 0-4 bize 65531 gibi bir deger verirki buda sistemin hata yapmasına sebep olur. Bu durumda sayet Role degeri sıfır ise bu hesabı yapmadan atlamamız gerekir. Akıllıca bir programlama mantıgı ile bu isi tek komutla halledebiliriz.
‘——————————————————————————————————–
ROLE=((ROLE>0) & %1)*(ROLE – 4) ‘BİR ÇOK İSİ GÖREN TEK BİR KOMUT
‘——————————————————————————————————–
Bu komut bizi birkaç defa if kullanmaktan kurtarır. Bu komut asagıdaki program satırlarının görevini yapmaktadır;
‘——————————————————————————————————–
IF ROLE=0 THEN Hesap yapma ve Ekrana bir sey yazma
IF ROLE>0 then ROLE= Role-4 hesabını yap
‘——————————————————————————————————–
Simdi komut nasıl çalısıyor bir bakalım;
(ROLE>0) & %1 komutunda (ROLE>0) ifadesi bir logik operatör kullanan bir aritmetik ifadesidir. Role>0 ise degeri 255, Role=0 ise degeri 0 dır. Dolayısıyla bunu %1 ile AND islemine tabi tutar isek Role 0 dan büyük olunca degeri 1, sıfıra esit olunca ise degeri 0 olarak gelir. Bu ifadeyi (ROLE-4) ile çarpar isek istedigimizi elde etmis oluruz.

Yani:
1 x (Role-4) burada Role 0 dan büyük oldugundan role degeri 1-4 arası çıkacaktır.
0 x (Role-4) ki burada Role 0 oldugundan sonuç 0 olacaktır.
‘——————————————————————————————————–
LCDOUT $FE,$C0,”ROLE=”,#ROLE,” “,DEC2 SAAT[ROLE],”:”,DEC2 D
DAK[ROLE],”:”,DEC2 SN[ROLE]

‘——————————————————————————————————–
Komutu ile aktif olan role ile o röleye ait saat degeri ekrana getirilmektedir.
‘——————————————————————————————————–
PORTB=AKTIF
‘——————————————————————————————————–
Aktif olan role ekrana verilmektedir. Kesme oluşmasında kolaylık saglamak üzere 20 ms lik gecikme us cinsinden döngü kullanılarak verilmektedir.
‘——————————————————————————————————–
FOR I=0 TO 2000
PAUSEUS 10
NEXT I

‘——————————————————————————————————–
GOTO BASLA
‘——————————————————————————————————–
Goto basla ile program tekrar basa yönlendirilmektedir. Programın Kesme kısmında ise 1 sn lik süre Sayac=61 sayısı ile kontrol edilmekte ve bu süre sonunda Sn=Sn+1 komutu ile degeri bir artırılmaktadır. Sn degerinin 60’ı geçmesi halinde dakika ve paralel olarak saat ve gün degerleri artırılmaktadır.

Buradaki diger önemli nokta ise o andaki ROLE degeri ki burada indeks olarak kullanılmakta esas alınarak o roleye ait saat degeri ise ayrıca saydırılmaktadır. Tabiiki hiçbir role aktif degil ise role degeri 0 olacağından sistem ana saati saydırılmaktadır.

Hazırlayan: Erol Tahir Erdal (ETE) PICBasic Dersleri PIC Basic Pro ile PIC Programlama 6 Kod ve simülasyon dosyaları: PICBasic Dersleri PIC Basic Pro ile PIC Programlama 6

Proje Dosyaları: link-10139.zip şifre-pass: 320volt.com

PICBasic Dersleri PIC Basic Pro ile PIC Programlama-7 Ders-7 Devam

  • hüseyin

    Merhaba Hocam
    adc ile kesme ile ilgili örnek verebilirmisiniz.Örneğin 3 volt olduğunda kesme kullanarak 10 dak. sayıp ledi(vs) yakması

  • Ferdi Gurtekin

    LCDOUT $FE,$84,DEC2 SAAT[0],”:”,DEC2 DAK[0],”:”,DEC2 SN[0]
    hocam buradaki $fe,$84 lcd de ne işe yarıor birde dec2 ne işe yarıyor anlıyamadım ?

  • ete

    LCDOUT $FE,$84 komutu kursorü ilk satırda 5. haneye getiriyor.
    Satırın en başı $80 adresine sahiptir. $84 olunca 5.ci haneye gelmiş oluyor.

    DEC komutu Decimal’in kısaltılmış halidir ve sayı formatı olarak kullanılır. DEC2 şeklinde kullanıldığı zaman bu komutu takip eden sayının yalnızca 2 hanesini ekrana yazdırır.
    Örnekle açıklarsak;
    A=321 olsun DC2 A dediğiniz zaman ekrana 21 sayısı yazılır.
    A=2 olsun DEC2 A dediğiniz zaman ekrana 02 yazdırılır. Olmayan haneler yerine sıfır getirilir otomatikman.

    Ete

  • mehmet ali

    1 BASLA: ‘Ana program bölümünde program bir sey yapmayacak
    2 pauseus 100 ‘kesme oluşmadıgı müddetçe program
    3 goto basla ‘ bu satırlar arasında dolasır

    4 DISABLE ‘yeniden kesme oluşması önleniyor

    5 KESME: ‘program buraya geldiginde kesme oluşmus demektir.
    6 TOGGLE LED ‘LED konum degistirdi
    7 PAUSE 1
    8 INTCON.1=0 ‘RB0/INT Bayragı (flag) silindi.
    9 Resume ‘geldigin yere dön

    10 Enable ‘kesmeler yeniden aktif.

    11 End

    hocam benim aklıma bişi takıldı şimdi biz programı çalıştırdık pic sürekli 1 ile 3. satırlar arasında işlem yapıyo herhangi bi kesme oluncaya kadar ama biz kesme uyguladığımızda 4. satırı atlıyarak 5. kesmenin olduğu satırdan devam ediyo ve 9. satırda tekrardan 3. satıra dönmüş oluyo yani bu arada 4. ve 10. satırlara hiç bi işlem yapmıyo

    bu şekilde olması gerekmezmi ?

    BASLA: ‘Ana program bölümünde program bir sey yapmayacak
    pauseus 100 ‘kesme oluşmadıgı müddetçe program
    goto basla ‘ bu satırlar arasında dolasır

    KESME: ‘program buraya geldiginde kesme oluşmus demektir.
    DISABLE ‘yeniden kesme oluşması önleniyor
    TOGGLE LED ‘LED konum degistirdi
    PAUSE 1
    INTCON.1=0 ‘RB0/INT Bayragı (flag) silindi.
    Enable ‘kesmeler yeniden aktif.
    Resume ‘geldigin yere dön

    End

    teşekkürler

  • ete

    Mehmet Ali,

    Disable komutu kesmeye giren program icra edilirken yeniden bir kesme oluşmasını önler.

    Enable komutu ise yeniden kesme oluşmasınını sağlayacak sistemi açar.
    Bu satırlar icra edilmiyor gibi görünselerde programın derlenmesi esnasında gereken tedbirler alınarak bu komutlar devreye sokulurlar.

  • hülya

    Merhaba hocam ;

    RB0 aktif hale gelebilmesi için intcon.4 ve intcon.7 bitini kullanmamız gerektiğini belirtmişsiniz.peki başka bir bit seçsek olur mu ya da sadece neden o bitleri seçiyoruz?
    teşekkürler

  • ete

    Başka hangi bit yada bitleri seçmek isterdiniz?
    Pic işlemcileri microchip firması tarafından üretilmiş.
    Üreticisi işlemcinin nasıl kullanılacağını göstermek ve özelliklerini açıklamak için Data Sheet denilen bir bilgi formu yayınlamış.
    Orada diyorki RB0 kesmesini açmak için INTCON registerinin 7 nolu biti olan Global Kesme bitini aktif edin. Böylece kesmeler genel olarak açılsın. Aynı registerin 4. bitini aktif ederek de RB0 kesmesini aktif hale gitirin.
    Durum bu. Üzgünüm ama kafanıza göre bit set edemiyorsunuz. Sonuçta data sheet ne diyorsa ona uyuyoruz . Hepsi bu.

    Ete

  • ferdi

    hocam durum diye tanımladığımız değişken ne işe yarıyor tam olarak ?

  • ete

    PortB değişiklik kesmesinde ;
    – Kesme Bölümünde DURUM=PORTB seklinde port degeri okunacak
    şeklindeki ifadede yer alan DURUM isimli değişkenden bahsediyor isen (hangi durum olduğunu belirtmemişsin)
    BU port değerini okuyup kayıt altına alan değişkendir. Tam olarak portB nin değerini kayıt ederki işlemci bu kayıt ile anlık olarak portB nin kendisini karşılaştırıp farklılık olursa kesmeyi yaratıyor. Yoksa PortB de değişiklik olduğunu anlayamıyor maalesef.
    Daha açık bir deyişle, Değişiklik nedir diye sorarsam bir şeyin bir iönceki haline olan farklılığıdır derim. PortB nin bir önceki halini ise Durum isimli değişken kayıt ediyor. Hepsi bu. Bu komut satırını kullanmazsanız kesme çalışmaz.

    Ete

  • ferdi gürtekin

    hocam bu durum değişkeni nerde kontrol ediyor biz portb yi durumu eşitlediğimiz için otomatik mi kontrol ediyor?

  • ete

    Kontrol işi işlemci tarafından geri planda yapılır bunu sizin görmeniz mümkün değil. Biliyorsunuz arka planda çalışan bir işlemci programı var.

    Bütün işler aslında o program tarafından yapılıyor ve sizin yazdığını zprogramı da o çalıştırıyor.

    Sizin anlamanız gereken şey , port değişiklik kesmesinin oluşması için ilgili pinlerde bir değişiklik olması gerektiği.

    Değişiklik ise bir şeye kıyasla anlaşılan bir husustur. Kıyas edilen şey ise o pinlerin değişiklikten önceki durumlarıdır. Bunu sağlayan ise DURUM=PORTB komutudur.

    Bu komut sayesinde PortB nin durumu kayıt altına alınıp işlemci tarafından her an otomatik olarak kontrol edilir. bir değişiklik oluncada kesme oluşturulur.

    Ete

  • Cenap

    Sayın Hocam, ben de başlayıcıyım, timer ve interrupt kullanımında süre uzunsa nasıl bir yol izlenmeli? Örnek bir proje olarak;
    Serum damla sayacı…… dakikada kaç damla damlıyor?

    _____I—–_______________________________I—–___________

    Sensordan gelen ve kare dalgaya çevrilmiş pulsların başlangıç aralarını (I-I arası) süre olarak ölçmek ve diyelim 2 damla arasını ms olarak ölçüp son 10 adedinin ortalamasını alıp, 60000 i bu sayıya bölersek dakikada kaç damla damladığını buluruz. Ama bu kadar uzun süre her 65535 sayım sonrası kaç kere başa dönerek flag oluştuğunu ve üzerine ne kadar da daha sayıldığını hesaplayarak bulmalıyız düşüncesindeyim. (örnek 23 adet 65535 + 256 adet clock sayılsa ve clock frekansına göre süre bulunsa…. bir soru: bölücü kullanılacak mı?) (örnek araların 1000 ms olması demek 60000/1000=60 damla/dk. ediyor display 60 yazacak) Tabii hesap mikrosaniye üzerinden yapılması gerekiyorsa 60000 değil 60.000.000 u ölçülen mikrosaniyeye bölmeliyiz.Tabii sonucu ayrıca 7 segmanlı display ile 2.5 digit (199 damla/dakikadan fazlası lazım olmaz) veya lcd displayde göstertmemiz gerekiyor.
    Nasıl bir devre ve program yapılabilir? saygılarımla.

  • ete

    Bana kalırsa en güzeli,
    TMR1 sayacını dışarıdan giriş yapacak şekilde kurmalı ve işlemi başlatırkende sayacı sıfırlamalısın. Sonra hassas bir şekilde 1 dak. zaman tutup bu süre sonunda TMR1 sayacının kaç saydığına bakmalısın.
    TMR1 sayacı 16 bitlik olduğu için 65536’ya kadar sayabilir. Sayı bu rakamdan büyük ise bölücü de kullanabilirsin. Bölme oranı 1/2 alınır ise sayac 65535 saya ama aslında bu 65535×2 adede eşdeğer olur.
    Aynı şekilde bölme oranı 1/4 veya 1/8 olarak da alınabilir.

    Ana programın başka işlerde yapacak ise zaman tutmak için TMR0 kesmesi kullanabilirsin. Böylece bir yandan zaman sayarken bir yandan da programı bloke etmemiş olursun. Bu şekilde damlaların hassas bir şekilde sayılabileceğini düşünüyorum.
    Ete

  • Cenap

    ETE hocam hızlı cevabınız için müteşekkirim. Diyelim ki dakikada 5 damla damlıyor yani her 12 saniye de bir. TMR1 dışardan her 12 saniyede bir uyarı alacak ve sayacak. Yani sayımı 65536 ya kadar normal clock sinyalinden registerların birine saydırmalıyım diye düşünüyorum. Aşım olduğunda kaç kere aşım olduğunu ve ilave sayımı kullanarak bir değer bulmalı mıyım hesap yaparken? teşekkürler

  • ete

    TMR1 sayacı dediğim gibi hem sistem clk’undan puls alarak sayar hemde harici giriş pininden puls alarak sayabilir. Harici pinden sayarsa 1/1 bölme oranını kullanarak 1 dak içinde 65535’e kadar puls saydırabilirsin. Şayet bunda aşabilirim dersen o zaman TMR1 kesmesinide açarsın aşma olduğunde kesme oluşur ve orada ikinci bir değişkeni bir artırırsın.

    Yani bir dakikada 65536 ‘yı aşacağını hiç sanmıyorum.

    Dediğim gibi yaparsan 1 dakikada 1 damla gelse 1 sayar 1000 damla gelse 1000 sayar 60000 damla gelse 60000 sayar. Onun dışındakiler sana sorun çıkartır bu benim fikrim. Israrla başka register kullanayım diyorsan kullan derim ne diyeyim.

    Ete

  • Cenap

    Sabrınız ve desteğiniz için çok teşekkür ederim.
    Sanıyorum pic le süre aralığı ölçümünün ve bunun dakikada kaça tekabül ettiğinin çeviriminin nasıl yapılabileceği konusunda kısa bir ders anlatabilirseniz çok daha iyi anlar ve müteşekkir kalırız.

    Benim anlayabildiğim ve kafamda oluşanları tekrar ifade etmeye çalışayım;

    aynı projeji bir turnikeden dakikada geçen kişi sayısının sayılması için de uygulayabiliriz

    şimdi damlaların veya kişilerin toplam sayısı bizim için önemli değil
    yani amacımız yukarı doğru sayan bir sayaç yapmak değil damlaların arasındaki süreyi ölçmek ve sayı/dk ya çevirmek. Bu yüzden TMR1 in sayım yapması değil olayın yani damlanın varlığının tespitini yapması bize yetiyor. Şimdi bu nedenle TMR1 dışardan uyarı alabiliyor bunu damlanın varlığını tespit eden sensora bağlayalım ve dakikada 3 damla damlasın (zaten 199 un üstü lazım değil, benzer şekilde turnikeden de dakikada belli kişi geçebilir registerın sınırında endişemiz yok)
    Sorum şu: TMR1; 20 saniyede bir uyarı alacak bu durumda pic gerçek zamanın farkına nasıl varacak? yani clock 4 MHz de sayacak diğer
    registerdan bu hızla bu örnekte (3 damla/dk) 20 saniyede kaça kadar sayılmış ve kaç aşım olmuş diye saymamız ve bunu kullanmamız gerekmiyor mu? Yani TMR1 in kaç tane uyarı aldığı değil iki uyarı arasında clock un kaça kadar saydığı bizi ilgilendirmiyor mu?
    Geçen sürenin nasıl ölçüleceğinin ve ne yolla sayılması , sonucun sayı/dakikaya çevrilmesi gerektiğinin mantığını anlamaya çalışıyorum.
    Saygılarımla

  • Cenap

    Sayın hocam aklıma sonradan gelenleri eklemek istedim;
    Damla aralığının süre olarak ölçümünün damla/dk ya çevrilmesnii her damladan sonra görüntüye vermek (veya son 10 damlanın ortalamasını alıyorsak 10. damladan sonra)ayrıce okuma için 1 dk gibi bir sürenin geçmesini beklemeden her damla sonrası anlık damla/dk sayısını görmemizi de sağlayacaktır.(1 dk 60 milyon mikrosaniye olduğuna göre 60.000.000/ölçülen süre aralığı mikrosaniye = damla/dk verir) aralar 1 milyon mikrosaniye ise 60 damla dakika gösterir.

  • ete

    Pic ile peryot ölçmenin bir kaç yolu mevcut.
    Birincisi PULSIN komutunu kullanmak . BU komut PULSIN Pin,KOnum,Değişken şeklinde belirlenen 3 parametre ile çalışır.
    Pin sinyalin girdiği pindir ve giriş olarak ayarlanmalıdır. Konum ölçülecek konum olup sıfır (LOW) yada 1 (High ) şeklinde bir parametre verilmelidir. Değişken ise ölçülen sürenin yerleştirildiği değişken adıdır. Ölçülen süre 10us lik katlar şeklinde hesaplanır ve değişkene aktarılır. 65535 ms lik bir süre 6553 olarak değişkende yer alacaktır.

    Diğer bir yöntem ise Kesme kullanmaktır. Kesme yöntemi hem TMR0 hemde TMR1’e uygulanabilir. Ama süre uzun olacak ise TMR1 kullanmak daha akıllıca olacaktır. Bu sşstemi yine bir başka kesme ile başlatmak gerekebilir. Örneğin damlanın düşütüğü anda bir HIGH palsi oluşacağına göre PORTB.0 kesmesi yükselen kenar için açılır. Kesme oluşunca TMR1 sıfırlanır ve aktif edilir. Böylece ilk damlada başlatılan zaman sayımı ikinci damlaya kadar sürecektir. Zamanın 65535 ms den uzun olabileceği dikkate alınarak aynı zamanda TMR1 değer aşım kesmeside aktif edilir. Şayet ikinci damla gelmeen TMR1 zaman aşımına uğrar ise kesme oluşacak ve siz bir başka zaman değişenini bir artıracaksınız (ZAMAN1). Bu arada ikinci damla gelirse bu sferde PORTB.0 kesmesi oluşacak ve siz hemen TMR1 değerini okuyup kendi değişkeninize (ZAMAN0) aktaracaksınız. Bu durumda iki damla arasındaki zaman, zaman1*65536 + zaman0 şeklinde hesaplanacaktır.

    Hesabı kolayca yapayım isterseniz 18F serisinden bir işlemci kullanarak LONG tipi değişken kulanmanızı öneririm. Böylece sayıları 32 bit formatında tutabilir ve ekranada yazdırabilirsiniz.
    Bu kadar uzun sürelerin 10 tanesini toplamak ve bunların ortalamasını almak bence neredeyse deveye hendek atlamk gibi bir şey olacaktır boşuna çabalama bence.

    TMR1 sayacının bölme oranını 1/8 alabilirsiniz. Böylece zamanı 8 kat artırmış olacaksınız. Ama bunu yaparsanız tmr1 her 8 pulsde bir sayacağı için işin hassasiyeti de kaybolacaktır. Bu nedenle mümkünse 1/1 bölme oranı ile bu işi yapmaya çalışın.

    Diğer bir yöntem iste Capture özelliği olan işlemciler kullanıp capture kesmesi ile bu süreyi elde etmektir. Bu yöntem ykarıda açıkladığım yöntemden çok farklı değil. Fark yalnızca ayrıca bir PortB.0 kesmesi kullanma ihtiyacınızın olmamasıdır. Bu yöntemi direk anlatmak biraz zor. Örnekle açıklamak daha uyun sanırım.

    – Önce TMR1 sıfırlanıyor. TMR1L = 0 :TMR1H = 0 (tek seferde TMR1=0 denilemiyor maalesef)
    – Sonra CCP1 kesmesi düşen kenarda kesme olması için açılıyor, CCP1CON = %00000100
    – Sonra CCP1 kesme biti sıfırlanıyor , PIE1.2 = 0
    – Sonra capture bayrağı sıfırlanıyor PIR1.2=0
    – Sonra CCp1 kesmesini açıyoruz , PIE1.2=1
    – Sonra capture oluuncaya kadar bekliyoruz. While PIR1.2=0:Wend
    – Kesme oluştu şimdi artık yükselen kenarda kesme bekleyebiliriz.
    – Önce kesme bayrağını sıfırlayalım , PIR1.2=0
    – TMR1L = 0 :TMR1H = 0
    – Kesmeyi yükselen kenarda açalım, CCP1CON = %00000101
    – Kesme oluşuncaya kadar bekleyelim While PIR1.2=0:Wend
    – Kesme oluştu. O halde zamanı alalım. Zaman.byte0=TMRL : Zaman.Byte1=TMR1H
    – CCP1CON=0

    Hepsi bu kadar.

    Senin sorunun iki damla arasındaki sürenin saniyeler seviyesinde mikro işlemci için çok uzunbir süre olmasıdır.
    Bu nedenle kesin olarak 18F serisinden bir işlemci kullanıp bu süreyi LONG tipi bir değişkende tutmak olacaktır.
    Capture metodu da sana pek uygun gelmeyecektir. Dolayısıyla ikinci tarif ettim metod en iyisi olacaktır.

    Kolay Gelsin
    Ete

  • fatih

    OPTION_REG=%00000000 sorununu çözemedi bi türlü , bu komutu kabul etmiyor …