Frekans Sayici- 16F628a (Yardım)
-
İyi geceler,
PIC 16f628a ile bir frekans sayiciyapmaya çalışıyorum.
1 saniye içerisinde RB6/INT pinine gelen pulsları sayacağım.
1 saniye tutmak için TMR1 timer'ını 32.768kHZ harici osilatör ile kullanıyorum.
Proteus 8.5 ile devreyi kurdum. RB6'ya 10000Hz'lik sinyale kadar doğru gösteriyor fakat daha yüksek frekanslarda eksik sayıyor.
Forumlarda RB6 pininin üst limitinin 50MHz civarında olduğunu yazmışlar. (datasheet'te öyle yazıyormuş ben kendim bakmadım.)
benim sayaç daha 20kHz'te doğru okuyamıyor.
Acaba bu simülasyon olduğu için mi böyle?
Kodları mikroC for PIC 6.6.2'de yazıp derliyorum.
Bir ekran görüntüsü ve kodlar aşağıdaki gibidir;
// Lcd pinout settings sbit LCD_RS at RA1_bit; sbit LCD_EN at RA0_bit; sbit LCD_D4 at RB5_bit; sbit LCD_D5 at RB4_bit; sbit LCD_D6 at RB3_bit; sbit LCD_D7 at RB2_bit; // Pin direction sbit LCD_RS_Direction at TRISA1_bit; sbit LCD_EN_Direction at TRISA0_bit; sbit LCD_D4_Direction at TRISB5_bit; sbit LCD_D5_Direction at TRISB4_bit; sbit LCD_D6_Direction at TRISB3_bit; sbit LCD_D7_Direction at TRISB2_bit; unsigned long frekans = 0; void interrupt() { INTF_bit = 0; frekans++; } void ayarlar() { CMCON = 0b00000111; //karsilastirici kapatildi INTE_bit = 1; //TRISA0_bit = 0; //CIKIS LCD E pinine gider //TRISA1_bit = 0; //CIKIS LCD RS pinine gider TRISA2_bit = 1; //GIRIS: S11 TRISA3_bit = 1; //GIRIS: S12 TRISA4_bit = 1; //GIRIS: S13 TRISA5_bit = 1; //GIRIS: reset butonu girisi (MCLR) TRISA6_bit = 0; //CIKIS: bosta TRISA7_bit = 0; //CIKIS: bosta //TRISB = 0b10000001; // LCD Pinlerini kendi ayarliyor TRISB0_bit = 1; //GIRIS: Sayilacak sinyal girisi TRISB1_bit = 0; //CIKIS: bosta //TRISB2_bit = 0; //CIKIS: LCD D7 pinine gider //TRISB3_bit = 0; //CIKIS: LCD D6 pinine gider //TRISB4_bit = 0; //CIKIS: LCD D5 pinine gider //TRISB5_bit = 0; //CIKIS: LCD D4 pinine gider //T1CON register'inda harici osilator secilince bu ikisine bakilmiyormus //TRISB6_bit = 1; //GIRIS: 32.768 kHZ kristal girisi //TRISB7_bit = 0; //CIKIS: 32.768 kHZ kristal cikisi //TMR1 ayarlari T1CON = 0b00001110; T1CKPS1_bit = 0; //TMR1 prescaler 1/1 ayarlandi T1CKPS0_bit = 0; T1OSCEN_bit = 1; //asenkron T1CON.F2 = 1; TMR1CS_bit = 1; //RB6'dan gelen sinyalleri sayacak TMR1ON_bit = 0; } void frekans_goster(unsigned long f) { char i, n, k, dijit[10]; n = 0; // dijitleri ayirarak diziye yaz do { dijit[n] = '0' + f % 10; f /= 10; n++; } while (f > 0 && n < 10); k = 13; // gosterilecek sembol sayisi: 10 basamaklı sayı + 3 virgul for(i = 0; i < 11; i++) { if (k == 2 || k == 6 || k == 10) { if (i < n) Lcd_Chr(1,k+3,','); // her uc basamaktan sonra virgul koy else Lcd_Chr(1,k+3,' '); // sayi kisa ise virgul yerine bosluk koy k--; } if (i < n || i == 0) { Lcd_Chr(1,k+3,dijit[i]); // haneyi yaz } else { Lcd_Chr(1,k+3,' '); // sayi kisa ise virgul yerine bosluk koy } k--; } } void Lcd_baslat() { Lcd_Init(); Lcd_Cmd(_LCD_CLEAR); Lcd_Cmd(_LCD_CURSOR_OFF); Lcd_Out(1, 1, "Frekans Sayici"); delay_ms(500); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1, 1, "F="); } void main() { ayarlar(); Lcd_baslat(); while(1) { GIE_bit = 0; //Genel kesmeler pasif TMR1ON_bit = 0; //TMR1 kapali frekans = 0; //frekans sayaci sifirlandi TMR1L = 0b00000000; //TMR1 degerleri yuklendi TMR1H = 0b10000000; TMR1IF_bit = 0; //TMR1 kesme bayragi indirildi INTF_bit = 0; //RB0/INT kesme bayragi indirildi TMR1ON_bit = 1; //TMR1 basladi GIE_bit = 1; //Genel kesmeler aktif while (!TMR1IF_bit) {} //1 sn tutuluyor GIE_bit = 0; TMR1ON_bit = 0; frekans_goster(frekans); } }
-
Hocam merhabalar,
Koda çok ayrıntılı bakamadım ancak dikkatimi çeken bir nokta var. Puls değerini arttıran fonksiyonu tanımlamışsınız. Ancak kesme vektörü şeklinde değilde interrupt() şeklinde isim vermişsiniz. PIC mimarisine hakim değilim ancak interrupt fonksiyon_adı() şeklinde yada __ISR() şeklinde ilgili vektör tanımlaması yapmanız gerekmiyor mu?
Edit: Şimdi inceledim sizin yazdığınız gibiymiş.
Ek olarak iki adet intteruptınız var. Timer ve external interrupt. Global interrupt fonksiyonunuz içerisinde sadece RB6 dan gelen interrupt'ı denetleyip frekans değerini arttırmayı deneyebilirsiniz
aercys tarafından 14/Kas/16 01:23 tarihinde düzenlenmiştir -
pic ile haşır neşirim ama hiç frekans sayıcı yapmadım. Öncelikle TMR1 timer'ını 32.768kHZ harici osilatör ile kullanıyorum demişsin ve RB6'ya 10000Hz'lik sinyale kadar doğru gösteriyor demişsin. TMR1 harici osc kullanıyorsan RB6 ve RB7 pinlerine 32.768 kristal bağlamış olman gerekiyor, peki buradan nasıl frekans ölçtün, ben mi yanlış anladım?
Yanılmıyorsam en yüksek frekans ölçümü için sanırım işlemci en son saat hızında(harici XT ile 20MHz), en yüksek sayan timer, en yüksek bölme oranında capture-compare şeklinde çalıştırılması gerekiyor. Yanılıyor da olabilirim fakat nette picli çok frekansmetre örneği var.
-
Haklısınız RB6 pininde 32.768kHz kristal var. Sayacağım sinyali RB0/INT pininden(6 nolu bacak) giriyorum. Yanlış yazmışım.
Yalnız benim comparator kapalı. RB0 da yüksek kenar interruptlarını sayıyorum. 1 saniyede oluşan interrupt sayısının frekansa eşit olması gerektiği mantığıyla.