Hi-Tech Eğitim Bölüm8 (TMR0 int. ile 4 dijit display sür

Başlatan arslan74, 05 Şubat 2008, 06:38:38

arslan74

Merhaba,

Bölüm7 de TMR0 kesme işlemi nasıl yapılırına dair örnek kodlar ve acıklama yapmıştım. TMR0 ile otomatik sayac yapmıştık. Ancak bu sayac tek dijit olduğu için yanlız 0-9 arasında sayma işlemini yapabiliyordu. Şimdi yapmak istediğimiz olay, 8bit değişten (unsigned char) değerini 4 dijit ekranda göstermek. Bu işlem biraz karışık olduğu için önce mantığını anlatmak istiyorum sonra şemada ve devrede örneklerini acıklarım.

Önce ekranı tarama frekansı belirleyeceğiz. Bunu timer0 ayarlarıla yapacağız.TMR0 ön bölücüsünü 1/4 veya 1/8 secersek taram hızı bizim için fazlasıyla yeterli olur. Şimdi oluşan her TMR0 kesmesin de sırasıyla tek bir dijit göstreceğiz. tarama frekansı 50Hz üzerinde olduğunda hepsi yaniyormuş gibi gözükecektir.

ISIS de basit bir devre şemasını cizdim.



Sütün taraması için araya inverter koydum. Ama siz gercek devreniz de transistör kullanın.

Şimdi yapmamız gereken programı yazmak. oluşan her kesme işlemide hangi hande kaldığı görstermesi için bir tane hane değişkeni kullanacağım.

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

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



#define S1	RA0
#define S2	RA1
#define S3	RA2
#define S4	RA3


							 //   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
							  };							  

volatile 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 = 0b00000001;	// PullUp dirençleri devreye sokar.  Ön bölücü 1/4 secildi.
	
	TMR0 = 0;	// TMR0 sayacını sıfırla.
	T0IF = 0;	// interrupt flagini sıfırla
	T0IE = 1;	// RB0 interuprunu devreye sok.
	GIE  = 1;	// Acık olan bütün interupları devreye sok.

	
	while (1){ // program döngüsü	
					
		sayac++;	// Sayacı bir artır.		
					
		DelayMs(250);	// 250 ms bekle.
		
	}
}

static void interrupt
isr(void)			// Here be interrupt function - the name is
				// unimportant.
{
	
	if(T0IF) {			// timer interrupt
		
		unsigned char gosterge; // Ekrana gösterilecek bilgiyi tutar.
		static unsigned char hane = 1; // Gösterilecek haneyi tutar.
		
		PORTA =	0; // Önce ekranı kapat.
		
						
		if (hane == 1){		// 1 ler hanesi
			hane++;		// bir sonraki haneye gec.
			
			gosterge = sayac%10; // mod operatörüdür. Anlamı 10 bölümünden kalan demektir.
			
			PORTB = dijit[gosterge];	// BU DEĞERİ DİJİTE CEVİR VE EKRANA İLET.

			S1 = 1; // birinci sütünü yak.
		}
		else if (hane == 2) {		// 10 ler hanesi
			hane++;		// bir sonraki haneye gec.

			gosterge = (sayac/10)%10;	// 10 HANESİNİN DEĞERİNİ AL.
			
			PORTB = dijit[gosterge];	// BU DEĞERİ DİJİTE CEVİR VE EKRANA İLET.
			
			S2 = 1; // 2.ci sütünü yak.
		}
		else if (hane == 3) { 		// 100 ler hanesi
			hane++;		// bir sonraki haneye gec.
			
			gosterge = sayac/100; // 100 ler hanesi. 255 fazla olamıyacağı için fazladan modunu almadım.
			
			PORTB = dijit[gosterge];	// BU DEĞERİ DİJİTE CEVİR VE EKRANA İLET.

			S3 = 1; // 3.cü sütünü yak.
		}
		else {		// 1000 ler hanesi
			hane = 1;		// ilk haneye gec.
			
			PORTB = 0;	// char değişkenler en fazla 255 sayısı gösterdiği için bu haneyi kullanmiyorum.
			S4 = 1; // 4.cü sütünü yak.
		}

		T0IF = 0;		// clear the interrupt flag
	}
	
	
	if(INTF) {			// did we see a button press?
				

		INTF = 0;			// clear the interrupt
	}
}


şimdi simulyasonunu çalıştırdığımızda göstergenin gayet düzgün çalıştığını görüyoruz.




Ana program sadece belli sürede sayac değerini artırıyor. Başka hiç bir işle ilgilenmiyor. Ama alt programda ise TMR0 kresmesi ise sayac değerini ekrana yaziyor.

Şimdi main programda bir işlem yapmak isteyen birisi diyelimki bir değeri ekrana yazdırmak istiyor yapmasi geken tek işlem bu değeri sayac değişkenine atamaktır. Bilgi otomatik ekranda gözükecektir.

Görduğunuz gibi bir değeri ekrana yazmak gayet basit işlem haline geldi.

Program yazmadan önce nasıl yapılacağının mantığını bilmek önemli. Kafada bir mantık oluştuktan sonra onu koda dökmek o kadar zor değil, tabi programa dilini bilmesi kaydiyle.


En başta bazı tanımlamalar yaptım.

#define S1   RA0 
#define S2   RA1 
#define S3   RA2 
#define S4   RA3


böyle yaparsanız kodunuzun anlaşıması daha kolay olur hemde bacaklarda bir değişiklik yaptığınızda sadece bu tanımdada değişiklik yaparak halledebilirsiniz. Kodunuzun içinde hiçbir müdahele yapmanız gerekmez.

Projenin kaynak kodları ve simulsayonu:

http://www.4shared.com/file/36896517/f9396965/Blm8.html?dirPwdVerified=5a7b6e3a

Çalışmalarızda başarılar.

Logan

Merhaba @arslan74, derslerini ilgiyle takip ediyorum son derece açıklayıcı yazıyorsun. Ben yaklaşık7 aydır C kullanıyorum, henüz yeniyim ve öğrenmeye çalışıyorum. Aşağıdaki programda sayac değişkenini tanımlarken "volatile" kullanmışsın ve interrupt alt programını "static" olarak tanımlamışsın. Bunların sebebini açıklar mısın? Çalışmalarında başarılar.
İmza.

arslan74

Alıntı yapılan: "Logan"Merhaba @arslan74, derslerini ilgiyle takip ediyorum son derece açıklayıcı yazıyorsun. Ben yaklaşık7 aydır C kullanıyorum, henüz yeniyim ve öğrenmeye çalışıyorum. Aşağıdaki programda sayac değişkenini tanımlarken "volatile" kullanmışsın ve interrupt alt programını "static" olarak tanımlamışsın. Bunların sebebini açıklar mısın? Çalışmalarında başarılar.

Bundan önce yazdığım eski ders notlarını hepsini iyice okuyun. Cunkü konuları birbiryle ilişkili olarak acıklıyoum. Sorduğunuz bu soruları bundan önceki bölümlerde acıkladım.

Selamlar

hackorsan

Hocam dersleriniz çok güzel ellerinize sağlık
benim bir iki sorum olacak bu 4 display sürme ile ilgili
bir kaç aydır fırsat buldukça c ye çalışıyorum normalde basic kullanıyorum

daha önce yaptığığım display sürmelerde her dijit arasında 3 ms bekleme yaptırdığımda güzel çalışıyordu
fakat sizin programınızda bu beklemeyi göremedim

soru 1= her kesme oluştuğunda kesme içinde 4 adet displayde sıra ile sürülüyor anladığım kadarı ile fakat aralarında bir gecikme yok 1/4 prescaler kullanmışsınız. bildiğim kadarı ile bu kesme süresinin yaklaşık 4 mikrosaniye yapması lazım doğrumu ?

soru 2 = ana programda 250 milisaniyelik bir gecikme var normalde kesme bu bekleme komutuna rast geldiğinde 250 milisaniye orada takılması lazım ki basic de kesinlikle takılıyor.Bu takılma sonunda da displaylerde bir düzensiz çalışma hali olması lazım.  İşin ilginç tarafı eklediğiniz dökümanlardaki isis dosyasını çalıştırdım gayet güzel çalışıyor
Programın çalışma mantığını kavramak adına genel çalışma mantığını açıklarsanız sevinirim
Teşekkkür eder iyi çalışmalar dilerim
bla

arslan74

Alıntı yapılan: "hackorsan"Hocam dersleriniz çok güzel ellerinize sağlık
benim bir iki sorum olacak bu 4 display sürme ile ilgili
bir kaç aydır fırsat buldukça c ye çalışıyorum normalde basic kullanıyorum

daha önce yaptığığım display sürmelerde her dijit arasında 3 ms bekleme yaptırdığımda güzel çalışıyordu
fakat sizin programınızda bu beklemeyi göremedim

soru 1= her kesme oluştuğunda kesme içinde 4 adet displayde sıra ile sürülüyor anladığım kadarı ile fakat aralarında bir gecikme yok 1/4 prescaler kullanmışsınız. bildiğim kadarı ile bu kesme süresinin yaklaşık 4 mikrosaniye yapması lazım doğrumu ?

soru 2 = ana programda 250 milisaniyelik bir gecikme var normalde kesme bu bekleme komutuna rast geldiğinde 250 milisaniye orada takılması lazım ki basic de kesinlikle takılıyor.Bu takılma sonunda da displaylerde bir düzensiz çalışma hali olması lazım.  İşin ilginç tarafı eklediğiniz dökümanlardaki isis dosyasını çalıştırdım gayet güzel çalışıyor
Programın çalışma mantığını kavramak adına genel çalışma mantığını açıklarsanız sevinirim
Teşekkkür eder iyi çalışmalar dilerim

Merhaba,

Sorularınız cevaplamadan önce size C nin genel yapısı hakkında basid bir acıklama yapmak istiyorum. C orta sevide bir dil olması nedeniyle kullanımı ve öğrenimi Basic gibi ust seviye dilleri gib basit ve hızlı olmuyor. Ama Domanıma doğrudan müdahele etme olanağınız cok daha fazla olduğu için size cok daha iyi bir avantaj sağlıyor.

Programı anlatmadan önce işin mantığını anlatayım, aslında yazımda da bunları acıkladım. Ama anlamayan arkadaşlar için yeniden anlatmaya çalışayım.

En başta proteus simulasyonunda kendinizde ayrıntılı inceleme yapabilirsiniz. Örneğin TMR0 int. olduğu yere bir tane breakpoint koyarak iki breakpoint arasındaki gecen süreyi bulabilirsiniz. Ben şimdi test ettim ortama 1ms gözüküyor. Bu durumda tarama frekansi 1000hz gibi cok yüksek bir frekans göküyüor.

Anladığım kadarıyla siz interrupt olayını hiç kullanmamışsınız. Ekran taramasını bir alt fonksiyon altında yapmaya çalışıyorsunuz. Öyle durumlarda mecburen bekleme eklemeniz gerekiyor yoksa çalışmaz ve bütün taramaların hepsini yapiyorsunuz. bu durumda 3ms*4=12ms ortama bir sürede yapiyor. Basid programlarda bu böyle olabilir, fazla sorunla karşılaşmassınız. Ama gelişmiş bir programda bu olay büyük sorun olarak durur. Ekran fonksiyonun gelene kadar gecen süre her kod eklemenizde değişir. Program belli bir ebattı gectikten sonra ekranda titrelemeriniz artacaktır.

Ama benim yazdığım kodda ise ekran sürme işlemi ana programdan bağımsız olarak olarak çalışıyor. Ana program istediğiniz kadar kod ekleyin ekran taramasında en ufak bir değişiliğe neden olmayacak, tabi kesemeleri kapatmadığınız sürece.

Kesme alt programınız her oluşmasında sadece bir dijiti yakar. biz 3 dijit yaptığımız için. 3 kesme sonucunta ekran taraması tamamlanır oda ortama 3ms gibi bir süre eder.

kesme alt programı sadece "sayac" değişkenini ekrana yazar. "sayac" değişkeninde ne varsa onu ekran görebilirsiniz. Başka bir iş yapmiyor.

Ana programda ise ortama 250ms(burada 290ms cıktı) de bir sayac değerini artırıyoruz. Bekleme fonksiyonun değişirerek sayma süresini değişirebiliriz.

Asıl sorunuz olan "DelayMs(250);" işlemi içinde neden kilitleme olsunki. "DelayMs(250)" mainde herkangi bir alt fonksiyondur. 16 serisi piclerde en fazla 8 tane alt fonksiyon derinliğine kadar inebilirsiniz. hiç bir sorunlar olmaz.

Siz PIC in donanımın öğrenme olayını, öğrendiğin PicBasic dilinde göre anlamaya çalışıyorsunuz, ona göre şekillendiriyorsunuz. Bu şahsen benim görüşüme göre cok yanlış ve hatadır. Bazı donumsal olayları kullandığınız dillerde yazamasınız, o durumda ASM bile gecmeniz gerekebilir. PIC de program yazmadan önce PIC'in donanım yapısını cok iyi bilmeniz gerekiyor. Yoksa fazla ilerleyemesiniz.

Çakışma daha cok bir fonksiyon hem kesme alt programında hemde ana programda kullanılmış ise ortaya cıkar. Ama Hi-Tech derleyicisi bu kontrolü yapiyor ve bu durum için size müsade etmiyor. dolaysıyla öyle bir şey söz konusu olmuyor. maindeki bekleme fonksiyonunu ayrıca kesme alt programında çalırmaya çalıştığınızda hata mesajı verir.

Sizin kullandığınız Basic programınında bekleme fonksiyonu nasıl yazdığınına bakmamız gerek. Yoksa kafan çakışma olur demek cok yanlış ve büyük bir yanlış anlama.

Selamlar

Seferi


a.zorba

Bilenler bilir . Biz maraşlilar için şehir olarak şubat ay' i bayram ,kurtuluş ,yaz in gelmesiydi. Şimdi karalar in yas in ayı oldu.

refik1

kardeş şu topladıklarını başka biryere göndersen

a.zorba

Bilenler bilir . Biz maraşlilar için şehir olarak şubat ay' i bayram ,kurtuluş ,yaz in gelmesiydi. Şimdi karalar in yas in ayı oldu.