Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H

Ana Menü

16f828 frekansmetre sorunu

Başlatan metaltrrocker, 14 Haziran 2013, 05:02:55

metaltrrocker

arkadaşlar merhaba.İnternette frekansmetre diye aratınca bu devreyi ve kodları buldum.Baktım ki hitech C için yazılmış, mikro C ye çevirmeye çalıştım.Kafama göre birşeyler yaptım.Devreyi proteus ta çizdim.Ancak devreyi çalıştıramadım.Kodlardamı sıkıntı var acaba bir bakabilirseniz sevinirim.

Kaynak:
http://www.biltek.tubitak.gov.tr/gelisim/elektronik/38.htm
proje ve proteus dosyaları
link:
https://www.dropbox.com/s/v41gif7utwglu53/16f828%20frekansmetre.rar

unsigned char kontrol;

//---------------------------------------------
//	     CCP1 kesme alt programı
//---------------------------------------------
void interrupt(void){
TMR1H=0; TMR1L=0; // TMR1 içeriğini sıfırla
INTCON.GIE  = 0;     // enable Global interrupts // yeni kesme gelmesini engelle

kontrol=1;

pie1.CCP1IF=0; // yeni kesmeler için bayrağı sıfırla
INTCON.GIE  = 1;     // enable Global interrupts; // bütün kesmelere izin ver
}

//---------------------------------------------
//		ANA PROGRAM
//---------------------------------------------
main(void)
{
unsigned const char rakam[10]={0x3F,0x06,0x5B,
  	    0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char secme[4]={1,2,4,8};
unsigned int sayac,deger,kalan1,kalan2;
float frekans;
unsigned char a,i,display[5],veri;

TRISA=0x00; // PORTA'nın hepsi çıkış
TRISB=0x08; // RB3/CCP1 ucu giriş
CMCON=0x07; // PORTA sayısal giriş

kontrol=0;
PORTA=0; PORTB=0; // başlangıç durumu ayarları

pie1.ccp1ie=1; // CCP1 kesmesine izin ver (PIE1,2)

// Her 4. yükselen kenarda yakalama modu
CCP1CON=0b00000110;

// TMR1 dahili saat fosc/4 ve ön bölücü 1:4
T1CON=0b00100001; // TMR1 çalışmaya başlar

PIE1.GIE  = 1;     // enable Global interrupts // bütün kesmelere izin ver
PIE1.PEIE = 1;   // çevresel kesmelere izin ver

for(;;){

// 16 bitlik CCPR1 değerini hesapla
sayac=256*CCPR1H+CCPR1L;

// Kesme oluşmadıysa kontrol=0'dır.
if(kontrol==1)frekans=100000000/sayac;
if(kontrol==0)frekans=0;

// 100Hz'in üzerini ölçme
if(sayac<10000)frekans=0;

kontrol=0;

// 300ms boyunca aynı değeri göster
for(a=0;a<25;a++){

	deger=(int)frekans;

	display[1]=deger/1000;
	kalan1=deger-display[1]*1000;

	display[2]=kalan1/100;
	kalan2=kalan1-display[2]*100;

	display[3]=kalan2/10;
	display[4]=kalan2-display[3]*10;

	// 3ms arayla display'leri tara
	for(i=0;i<4;i++){
		PORTB=0;
		PORTA=0;

		veri=rakam[display[i+1]];
		PORTB=veri&0x07;
		veri=veri<<1;
		PORTB=PORTB|(veri&0xF0);

		PORTA=secme[i];
		Delay_ms(3);

	}
}
} // Sonsuz döngü
} // Program sonu


Burada da orjinal hitech C kodları var.

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

__CONFIG(WDTDIS&PWRTEN&LVPDIS&XT);

unsigned char kontrol;

//---------------------------------------------
//	     CCP1 kesme alt programı
//---------------------------------------------
void interrupt kesme(void){
TMR1H=0; TMR1L=0; // TMR1 içeriğini sıfırla
GIE=0; // yeni kesme gelmesini engelle

kontrol=1; 

CCP1IF=0; // yeni kesmeler için bayrağı sıfırla
GIE=1; // bütün kesmelere izin ver
}

//---------------------------------------------
//		ANA PROGRAM
//---------------------------------------------
main(void)
{
unsigned const char rakam[10]={0x3F,0x06,0x5B,
  	    0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};	
unsigned char secme[4]={1,2,4,8};
unsigned int sayac,deger,kalan1,kalan2;
float frekans;
unsigned char a,i,display[5],veri;

TRISA=0x00; // PORTA'nın hepsi çıkış
TRISB=0x08; // RB3/CCP1 ucu giriş
CMCON=0x07; // PORTA sayısal giriş

kontrol=0;
PORTA=0; PORTB=0; // başlangıç durumu ayarları 

CCP1IE=1; // CCP1 kesmesine izin ver (PIE1,2)

// Her 4. yükselen kenarda yakalama modu 
CCP1CON=0b00000110; 

// TMR1 dahili saat fosc/4 ve ön bölücü 1:4
T1CON=0b00100001; // TMR1 çalışmaya başlar 
		  
GIE=1; // bütün kesmelere izin ver
PEIE=1; // çevresel kesmelere izin ver

for(;;){

// 16 bitlik CCPR1 değerini hesapla
sayac=256*CCPR1H+CCPR1L;

// Kesme oluşmadıysa kontrol=0'dır.
if(kontrol==1)frekans=100000000/sayac;
if(kontrol==0)frekans=0;

// 100Hz'in üzerini ölçme
if(sayac<10000)frekans=0; 

kontrol=0;

// 300ms boyunca aynı değeri göster
for(a=0;a<25;a++){ 

	deger=(int)frekans;

	display[1]=deger/1000;
	kalan1=deger-display[1]*1000;

	display[2]=kalan1/100;
	kalan2=kalan1-display[2]*100;

	display[3]=kalan2/10;
	display[4]=kalan2-display[3]*10;

	// 3ms arayla display'leri tara
	for(i=0;i<4;i++){
		PORTB=0;
		PORTA=0;

		veri=rakam[display[i+1]];
		PORTB=veri&0x07;
		veri=veri<<1;
		PORTB=PORTB|(veri&0xF0);

		PORTA=secme[i];
		DelayMs(3);
	}
} 
} // Sonsuz döngü
} // Program sonu

Kabil ATICI

bu dilden anladığımı söyleyemem ama mantık olarak;
// 16 bitlik CCPR1 değerini hesapla
sayac=256*CCPR1H+CCPR1L;
burada sayac değerini sabit bir değer verip ekrana düzgün çıkıyor mu bakabirsin.
Burada verdiğin değer ekrana düzgün çıkıyorsa en azından gösterge bölümün ile ilgili sonun olmadığı anlaşılır. kod olarak incelenmesi gereken bölüm sadece ölçüm olur...
umarım "sayac" 16 bit olarak tanımlanmış olsun...

Bu arada gerçi adı frekansmetrede bu alet orjin olarak periyotmetre olarak iş yapıp sonucu frekansı çeviriyor. O yüzden yüksek frekanslarda ölçüm yapılması hatalı olur.
ambar7

metaltrrocker

Kesme ve capture compare komutlarını MikroC ye uyarlarken hata yapmışım.Kodları düzelttim çalışıyor.Şimdi sormayı istediğim asıl soru geliyor.
Ben bu devreyi akord cihazına çevirmeyi düşünüyorum.Ne gibi eklemeler yapmam gerekiyor.Bir preamfili mikrofon ile sesi rb3 pinine vermek ve frekansı ölçmek içir ne tarz eklemeler yapmam gerekiyor?


[IMG]http://img822.imageshack.us/img822/2905/9vq.png[/img]


unsigned char kontrol;

//---------------------------------------------
//             CCP1 kesme alt programı
//---------------------------------------------
void interrupt(void){
TMR1H=0; TMR1L=0; // TMR1 içeriğini sıfırla
intcon.GIE  = 0;     // enable Global interrupts // yeni kesme gelmesini engelle

kontrol=1;

PIR1.CCP1IF=0; // yeni kesmeler için bayrağı sıfırla
intcon.GIE  = 1;     // enable Global interrupts; // bütün kesmelere izin ver
}

//---------------------------------------------
//                ANA PROGRAM
//---------------------------------------------
main(void)
{
unsigned const char rakam[10]={0x3F,0x06,0x5B,
              0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char secme[4]={1,2,4,8};
unsigned int sayac,deger,kalan1,kalan2;
float frekans;
unsigned char a,i,display[5],veri;

TRISA=0x00; // PORTA'nın hepsi çıkış
TRISB=0x08; // RB3/CCP1 ucu giriş
//CMCON=0x07; // PORTA sayısal giriş

kontrol=0;
PORTA=0; PORTB=0; // başlangıç durumu ayarları


PIE1.CCP1ie=1;      // CCP1 kesmesine izin ver (PIE1,2)
// Her 4. yükselen kenarda yakalama modu
CCP1CON=0b00000110;

// TMR1 dahili saat fosc/4 ve ön bölücü 1:4
T1CON=0b00100001; // TMR1 çalışmaya başlar

intcon.GIE  = 1;     // enable Global interrupts // bütün kesmelere izin ver
INTCON.PEIE = 1;   // çevresel kesmelere izin ver


for(;;){

// 16 bitlik CCPR1 değerini hesapla
sayac=256*CCPR1H+CCPR1L;
//sayac = 200000000;



// Kesme oluşmadıysa kontrol=0'dır.
if(kontrol==1)frekans=100000000/sayac;
if(kontrol==0)frekans=0;

// 100Hz'in üzerini ölçme
if(sayac<10000)frekans=0;

kontrol=0;

// 300ms boyunca aynı değeri göster
for(a=0;a<100;a++){

        deger=(int)frekans;

         /*
         display[1]=1;
         display[2]=2;
         display[3]=3;
         display[4]=4;
         */
         display[1]=deger/1000;
        kalan1=deger-display[1]*1000;

        display[2]=kalan1/100;
        kalan2=kalan1-display[2]*100;

        display[3]=kalan2/10;
        display[4]=kalan2-display[3]*10;
         
         
        // 3ms arayla display'leri tara
        for(i=0;i<4;i++)
        {
                PORTB=0;
                PORTA=0;

                veri=rakam[display[i+1]];
                PORTB=veri&0x07;
                veri=veri<<1;
                PORTB=PORTB|(veri&0xF0);

                PORTA=~secme[i];
                Delay_ms(3);

        }
}
} // Sonsuz döngü
} // Program sonu