Hi-Tech PICC Eğitim Dökümanı Bölüm6

Başlatan arslan74, 03 Şubat 2008, 06:48:53

arslan74

Merhaba,

Şimdi konumuzu ilerletelim. Interrupt işlemlerini nasıl kullandığını anlatalım. En basit interrupt işlemi olan RB0 external interruptundan başlamak istiyorum.

Eski örnekler de RB0 bacağı kullanıldığı için önce o bacağı boşa cıkartiyorum. Şemayi aşağıdaki gibi değiştirdin. Buton olarak da RB0 bacağına sadece bir buton ekledim. ekranı sürecek olan bacaklarının hepsini kaydırdım. Buton basıldıkca sayac bir artacak.




Ekran süren bacaklarını değiştirdiğim için sadece kodda dijit bilgilerini tutan dizinin içindeki bilgileri değişirmen ve RB0 bacağınıda giriş olarak ayarlamam gerek.

Yeni proje yapmak yerine eski bölüm5 projesini farklı bir dizinie farklı bir isim olarak kayıt ediyorum.



yeni bir isim verelim ve kayıt edelim.



Şimdi MPLAB ekran göntüsü böyle oldu.



Ancak buraya dikkat etmeniz geren önemli bir konu var. "MPLAB IDE editor" içinde acık olan dosyalar eski dosyalardır, yani bölüm5 ait dosyalardır. O yüzden bu dosya üzerinde işlem yaparsanız bizim projemize ait dosyayı değiştirmemiş oluruz. O yüzden bu IDE yi kapatıp solda ki projede ki dosya yı cıft tıkladığımızda bu sefere IDE yeniden projemize ait dosya ile acılacaktır.

Şimdi dijit dizisini doğru göstermesi için yeniden düzenleme yapiyorum.
Tek yapman sadece bir bit sola kaydırmak aslında düzelme yapmama bile gerek yok. dijit dizisinden aldığım bilgiyi PortB iletmeden önce bir kez sola kaydırmış olursak doğru çalışacak. Ama öyle yapmayıb dijit değerlerini değişiteceğim sonra incelediğmizde yanlış anlama olmaması için.

Tuş okuma fonksiyonunu projeden kaldırıyorum. Onun yerine ana ana programa sadece bir tane "interrupt" fonksiyonu ekliyoruz. Hi-Tech'in örnek klasöründe 2 tane örnek kodlar var. Oradan olduğu gibi alıb yapıştırıyorum.

Alıntı YapC:\HT-PIC\samples\intrpt\

interrupt fonksiyonunun dosyanın en sonuna ekliyorum.

Son görünümü bölye oldu.



Şimdi yapmaız gereken PIC'in interrupt donanımını ayarlamak. PORTB de PULLUP direncleri aktif olduğu için tuşa basmada sıfıra düşektir, dolaysıyla interuptu düşen kenar olarak ayarlıyoruz ve aktif hale getiriyoruz.

Bu işlemi nasıl yapacağız? Öncelikle Hi-Tech C, ASM diline yakın olduğu için ASM nasıl yapiyorsak Burada öyle yapacağız. Bunun için bizim en iyi klavuzumuz kullandığımız PIC'in datasheetleridir. Orada Hangi bitlerin ne işe yaradığını tek tek anlatılıyor. Ezberim de olmadığı için bende şimdi PIC16F628A'nın datasheeti "DS40044A.pdf" dosyasını acıp inceliyorum.

Bizim için iki tane register önemli biri daha önce kullandığımız "OPTION REGISTER" diğeride "INTCON REGISTER" dir. sayfa 25 ve 26 da iki registerle ilgili acıklama var.

Sayfa 25deki OPTION regsiterin de bizi sadece bit7 (RBPU: PORTB Pull-up Enable bit) ve bit6 (INTEDG: Interrupt Edge Select bit) ilgilendiriyor. Acılışta

OPTION = 0b00000000;	// PullUp dirençleri devreye sokar.


yazdığımız için bu registerin ayarlarını yapmış oluyoruz.



Sayfa 26 da;



Interrupt ayarlarını yapıldığı ana registerdir. O yüzden buraya cok dikkat etmemiz gerekiyor. Burada bizi ilgilendiren şimdilik 3 tane register var.

1- bit7  GIE (Global Interrupt Enable bit): Ana interupt biti bu bit ile interrupt işlemi devreye sokub cıkartiyoruz.

2- bit4 INTE (RB0/INT External Interrupt Enable bit): Harici yani RB0 interruptunu devreye sokar.

3- bit1 INTF (RB0/INT External Interrupt Flag bit): Bu bir eğer RB0 interuptu oluşmuş ise aktif olur.

İlk acıkışta önce INTF sıfırlıyoruz sonra INTE'yi yani RB0 interuptunu devreye sokuyoruz, en son olarakta Genel interuptu acıyoruz.

Datasheetlerinde yazılan bitlerin aynısı birebir yaziyorum.

Örnek kod:

INTF = 0;	// interrupt flagini sıfırla
	INTE = 1;	// RB0 interuptrunu devreye sok.
	GIE  = 1;	// Acık olan bütün interupları devreye sok.


Bu işlemden sonra RB0 interrupt devreye girmiştir.

Şimdi sayac artıma işlemini ana programda mi yoksa interrupt altına yapcağız ona ona karar vermemiz gerekiyor. İlk olarak interrupt altında yapalım.

<#include	<pic.h>
#include	"delay.h"

// Sigorta ayarlarının yapıldığı yer
__CONFIG(PROTECT & CPD & INTIO & MCLRDIS & WDTDIS & LVPDIS & PWRTEN & BOREN );

							 //   GFEDCBAx
const unsigned char dijit[] = {	0b01111110, // 0
								0b00001100, // 1
								0b10110110, // 2
								0b10011110, // 3
								0b11001100, // 4
								0b11011010, // 5
								0b11111010, // 6
								0b00001110, // 7
								0b11111110, // 8
								0b11011110, // 9
							  };							  

unsigned char sayac = 0;
	
void main(void){ // Ana program
	
	TRISA = 0b00000000;	
	TRISB = 0b00000001;// RB0 giriş olarak ayarlandı.
	
	PORTA = 0b00000000;
	PORTB = 0b00000000;
	
	CMCON = 0x07;	// PORTA  analog pinlerini kapatır. Dijital prota dönüştür.

	OPTION = 0b00000000;	// PullUp dirençleri devreye sokar. 
	
	INTF = 0;	// interrupt flagini sıfırla
	INTE = 1;	// RB0 interuprunu devreye sok.
	GIE  = 1;	// Acık olan bütün interupları devreye sok.
	

	PORTB = dijit[sayac];

	while (1){ // program döngüsü	
	}
}

static void interrupt
isr(void)			// Here be interrupt function - the name is
				// unimportant.
{
	if(INTF) {				// did we see a button press?
					
		sayac++;	// Sayacı bir artır.
		if (sayac > 9 ) // Eğer sayac 9 dan byüyk ise sayacı sıfırlar
			sayac = 0;
		
		PORTB = dijit[sayac];	// sayac değerini ekrana yaz.
		NOP();

		INTF = 0;			// clear the interrupt
	}
}


Buton basmada ki parazitleri önlemek için interrupt altında bir tane bekleme döngüsü koyabiliriz. Ama daha sonra ekliyeceğiz timer interruptlarını etkileceği için bunu pek tavsiye etmiyorum. En basidi daha öncede belirtiğim gibi butonların girişlerine birer 100nF kondansatör eklemekle olur.

Kodu derleyib çalıştırdığımızda kodun gayet düzgün çalıştığını görüyoruz.

main programında ise sanki hiç bir işlem yapılmiyormuş gibi görünsede buton her basmada sayac değeri bir artıyor ve ekrana yaziyor.

-------------------------------------------------------------------------------

Şimdi başka bir varyasyon düşünelim: Biz ana prograın içinde RB0 interruptu oluştuğunu öğrenmek istiyoruz ona göre ana programda bu sayac değerini bir artırip ekrana yazacağız.

Bunu en basit çözümü bir tane global register tanımlamaktir. Ben burda hızlı işlem yapması adına global bir bit tanımlıyacağım. interupt da bu biti set edeceğim. Ana programda ise bu bitin durumuna bakacağım eğer bu bit set edilmiş ise o zaman RB0 int. oluşmuş demektir.

Kodu değiştiridiğimde söyle bir görüntü ortaya cıkıyor.

#include	<pic.h>
#include	"delay.h"

// Sigorta ayarlarının yapıldığı yer
__CONFIG(PROTECT & CPD & INTIO & MCLRDIS & WDTDIS & LVPDIS & PWRTEN & BOREN );

							 //   GFEDCBAx
const unsigned char dijit[] = {	0b01111110, // 0
								0b00001100, // 1
								0b10110110, // 2
								0b10011110, // 3
								0b11001100, // 4
								0b11011010, // 5
								0b11111010, // 6
								0b00001110, // 7
								0b11111110, // 8
								0b11011110, // 9
							  };							  

unsigned char sayac = 0;

volatile bit RB0_INT;

	
void main(void){ // Ana program
	
	TRISA = 0b00000000;	
	TRISB = 0b00000001;// RB0 giriş olarak ayarlandı.
	
	PORTA = 0b00000000;
	PORTB = 0b00000000;
	
	CMCON = 0x07;	// PORTA  analog pinlerini kapatır. Dijital prota dönüştür.

	OPTION = 0b00000000;	// PullUp dirençleri devreye sokar. 
	
	INTF = 0;	// interrupt flagini sıfırla
	INTE = 1;	// RB0 interuprunu devreye sok.
	GIE  = 1;	// Acık olan bütün interupları devreye sok.
	

	PORTB = dijit[sayac];

	while (1){ // program döngüsü	
		
		if (RB0_INT){
			RB0_INT = 0;
			
			sayac++;	// Sayacı bir artır.
			if (sayac > 9 ) // Eğer sayac 9 dan byüyk ise sayacı sıfırlar
				sayac = 0;
			
			PORTB = dijit[sayac];	// sayac değerini ekrana yaz.
			NOP();
			
		}
	}
}

static void interrupt
isr(void)			// Here be interrupt function - the name is
				// unimportant.
{
	if(INTF) {				// did we see a button press?
				
		RB0_INT = 1;	

		INTF = 0;			// clear the interrupt
	}
}


Global bit in basındaki " volatile " anahtarı o kadar önemli değil kullanmasanızda çalışır. Anlamı ise bu bit başka kaynaklarında kullandığını ifade ediyor. Bit o kadar öenmli değil ama int, float gibi işlemlerde kullanmamız cok önem taşır. Yoksa hatalı işlemlere sebep olabilir.

program kaynak kodları:

http://www.4shared.com/file/36718369/74b42030/Blm6.html?dirPwdVerified=5a7b6e3a

Çalışmalarınzda başarılar

Mod Notu: Bu güzel dökümanlar arasına teşekkür veya lüzumsuz sorular ile girilmesin, aksi taktirde dökümanı korumak için silinecektir.

ErsinErce

Interrupt kısmı sabit kalacak, devamında yada öncesinde istediğimiz bir kesmenin oluşup oluşmadığını kontrol edeceğiz aşağıdaki örnekte Timer0 ve RB0 kesmelerinin bir arada kullanışı gösteriliyor.
static void interrupt
isr(void)         // Here be interrupt function - the name is unimportant.
{
   if(INTF) {            // Gelen kesme RB0 kesmesi mi ?
            
      RB0_INT = 1;   

      INTF = 0;         // clear the interrupt
   }

   if(T0IF) {            // Gelen kesme Timer0 kesmesi mi ?

     //yapılacak işlemler

      T0IF = 0;        // clear the interrupt
   }
}

ahmet2004

Hi-tech C de bir sorun yok bence işinde çok iyi.

sürekli kesmede olduğunu nerden çıkardın.Kesmeden çıkıyor.

Her butona basıldıktan sonra A portundan darbeleri üretip kesmeden çıkıp

bekliyor benim denemelerimde çalışıyor kodun.

ahmet2004

Daha önceki senelerde bu konu anlatılmıştı diye hatırlıyorum.

#include <pic.h> 
#include "delay.h" 

void main(void) 
{ 
   TRISA=0x00; 
   TRISB=0xFf; 
    
   PORTA=0; 
   PORTB=0x00; 
    
   RBIE=1; 
   INTE=1; 
   RBIF=0; 
   INTF=0; 
   GIE=1; 
    
   for(;;); 
} 

static void interrupt 
isim(void) 
{ 
   int i; 
   if(RBIF==1) 
   { 
	  RBIF=0; 
      PORTA=0;
      PORTB=PORTB;
   } 

   if(INTF==1) 
   { 
      INTF=0; 
      for(i=0;i<8;i++) 
      { 
         PORTA=i; 
         DelayMs(200); 
      } 
   } 
}


işlemin etkili olabilmesi için (yani kesmeden çıkmak için)B portunu 1 kere okuman gerekiyor.

ORC

Alıntı yapılan: "FxDev"
İlginçmiş, baya bakmıştım forumda sormadan önce ama bulamamıştım.
Yeri gelmişken sormak isterim, .h ile .c arasında hitech'te ne gibi bir farklılık var, bazen .h'ı okurken bazen ise hata verip duruyor (h-tide kullanıyorum). Bu konuda şöyle yap yeterli diyebileceğiniz bir şey var mı?
Cevabın için teşekkürler ;)

.h de derleyiciye .c de kullanacagımız değişken veya fonksiyonlar ile ilgili bi ön bildirim işlemi yapıyoruz.. .h yi okuyan derleyici biliyor ki .c dosyasında bu  ön bildirimi yapılan metod veya değişkenler in govdelerini bulacagını biliyor..

Dikkat edilmesi gereken nokta .h de nasıl ön bildirim yapılmıssa .c de aynı format kullanılmalı yani alınan parametre ve geri donus degeri aynı olmalı

Benim bildiğim bu kadar  :roll:

Kolay Gelsin  ;)

Seferi

Hocam link çalışmıyor. Yenileyebilir misin?