PIC16F877 ile Frekansmetre

Başlatan anti1990, 26 Eylül 2011, 01:42:55

anti1990

Merhaba arkadaslar
PIC16f877 ile 16 bit veya 24 bit frekansmetre yapmak istiyorum. CCS ile programlıcam, frekansmetre yaparken CCP modlarından hangisini(capture/PWM) kullanmam gerekir? Algoritmayı nasıl yapmam gerekir?

tacettin

bir zamanlar bir yerden bulmuştum,ama yazanı bilmiyorum. umarım işine yarar...

#include "16F876.h"

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES LVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD




#use delay (clock=4000000)
#include "flcd.c"
//------------------------------------------------------------------------------
int   durum=0;
int16 value_timer1=0x3CAF;
int   sayac_tmr1=0;
int   sayac0=0;
int   sayac1=0;
int   sayac2=0;
int   sayac3=0;
int   sayac4=0;
char  sayac0_lcd;
char  sayac1_lcd;
char  sayac2_lcd;
char  sayac3_lcd;
char  sayac4_lcd;
//------------------------------------------------------------------------------
int   kesme_tmr1(void);
int   kesme_ext(void);
int   duzenle(int);
//------------------------------------------------------------------------------
// 1 sn lik timer1 kesmesi
//------------------------------------------------------------------------------
#INT_TIMER1
int   kesme_tmr1()
{
   sayac_tmr1++;
   if(sayac_tmr1==20)
   {
      sayac_tmr1=0;
      lcd_gotoxy(9,1);

      sayac0_lcd=duzenle(sayac0);
      sayac1_lcd=duzenle(sayac1);
      sayac2_lcd=duzenle(sayac2);
      sayac3_lcd=duzenle(sayac3);
      sayac4_lcd=duzenle(sayac4);
      
      lcd_putc(sayac4_lcd);      
      lcd_putc(sayac3_lcd);      
      lcd_putc(sayac2_lcd);      
      lcd_putc(sayac1_lcd);      
      lcd_putc(sayac0_lcd);
      lcd_putc("Hz");


      sayac0=0;     
      sayac1=0;     
      sayac2=0;     
      sayac3=0;     
      sayac4=0;     
   } 
   set_timer1(value_timer1);
}
//------------------------------------------------------------------------------
#INT_EXT
int   kesme_ext()
{
   sayac0++;
   if(sayac0==10)
   {
      sayac0=0;
      sayac1++;
      if(sayac1==10)
      {
         sayac1=0;
         sayac2++;
         if(sayac2==10)
         {
            sayac2=0;
            sayac3++;
            if(sayac3==10)
            {
               sayac3=0;
               sayac4++;
               if(sayac4==10)
               {
                  sayac4=0;
               }
            }
         }
      }
   }
}
//------------------------------------------------------------------------------
int   duzenle(int a)
{
   if(a==0)
   {
      return   '0';
   }
   if(a==1)
   {
      return   '1';
   }
   if(a==2)
   {
      return   '2';
   }
   if(a==3)
   {
      return   '3';
   }
   if(a==4)
   {
      return   '4';
   }
   if(a==5)
   {
      return   '5';
   }
   if(a==6)
   {
      return   '6';
   }
   if(a==7)
   {
      return   '7';
   }
   if(a==8)
   {
      return   '8';
   }
   if(a==9)
   {
      return   '9';
   }
}      
//------------------------------------------------------------------------------
int main()
{
//      SET_TRIS_b(0xFF);
//      output_b(0x00);
      setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 ); 
      set_timer1(value_timer1);
         
      lcd_init();
      lcd_putc("Frekans=");
       lcd_putc("\nKORFEZ EML 12BTL");

      enable_interrupts(INT_EXT);
      enable_interrupts(INT_TIMER1);
      enable_interrupts(GLOBAL);

      while(TRUE);
}




bu da flcd.c
struct lcd_pin_map {                 // This structure is overlayed
            BOOLEAN unused;           // low order up.  ENABLE will
            BOOLEAN rs;               // access to the LCD pins.
           BOOLEAN rw;               // The bits are allocated from
           BOOLEAN enable;           // on to an I/O port to gain
           int     data : 4;         // be pin B0.
        } lcd;


#byte lcd = 0x07
#define set_tris_lcd(x) set_tris_c(x)
#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40    // LCD RAM address for the second line


BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
                             // These bytes need to be sent to the LCD
                             // to start it up.


                             // The following are used for setting
                             // the I/O port direction register.

struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in



BYTE lcd_read_byte() {
      BYTE low,high;
      set_tris_lcd(LCD_READ);
      lcd.rw = 1;
      delay_cycles(1);
      lcd.enable = 1;
      delay_cycles(1);
      high = lcd.data;
      lcd.enable = 0;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(1);
      low = lcd.data;
      lcd.enable = 0;
      set_tris_lcd(LCD_WRITE);
      return( (high<<4) | low);
}


void lcd_send_nibble( BYTE n ) {
      lcd.data = n;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(2);
      lcd.enable = 0;
}


void lcd_send_byte( BYTE address, BYTE n ) {

      lcd.rs = 0;
      while ( bit_test(lcd_read_byte(),7) ) ;
      lcd.rs = address;
      delay_cycles(1);
      lcd.rw = 0;
      delay_cycles(1);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}


void lcd_init() {
    BYTE i;
    set_tris_lcd(LCD_WRITE);
    lcd.rs = 0;
    lcd.rw = 0;
    lcd.enable = 0;
    delay_ms(15);
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(5);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
       lcd_send_byte(0,LCD_INIT_STRING[i]);
}


void lcd_gotoxy( BYTE x, BYTE y) {
   BYTE address;

   if(y!=1)
     address=lcd_line_two;
   else
     address=0;
   address+=x-1;
   lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy(1,2);        break;
     case '\b'   : lcd_send_byte(0,0x10);  break;
     default     : lcd_send_byte(1,c);     break;
   }
}

char lcd_getc( BYTE x, BYTE y) {
   char value;

    lcd_gotoxy(x,y);
    while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
    lcd.rs=1;
    value = lcd_read_byte();
    lcd.rs=0;
    return(value);
}

-Hasan-

#2
Alıntı yapılan: anti1990CCP modlarından hangisini(capture/PWM) kullanmam gerekir? Algoritmayı nasıl yapmam gerekir?

Arkadaşım CCP kullanırsan Capture ile pals genişliklerini ölçerek yaparsın ama benim sana tavsiyem; CCP kullanmadan, 1 saniyede gelen palsleri sayarak bu işi yapman. Genellikle bu yöntem kullanılır zaten. CCP ile yaparsan, yüksek frekanslarda pek verimli olmaz.

Bunu yaparken 2 tane Timer kullanılacak; birisi 1 saniyelik zamanı tutmak için, diğeri de gelen palsleri saymak için. Gelen palsleri sayan Timer ' in 16 bit olması daha iyi olur, bu yüzden Timer0 ' ı zamanlayıcı olarak, Timer1 ' i sayıcı olarak kullanabilirsin. Bu durumda:

Timer0 ' ı 1 saniyede kesme üretecek şekilde ayarla.
Timer1 ' i de harici clock pininden (T1CLK) gelen palsleri sayacak şekilde ayarla ve Timer1 kesmesini de aç.
Her Timer1 kesmesi gelişinde bir registeri arttır. (Ölçeceğin frekansın yüksekliğine göre, istediğin uzunlukta olabilir.(16 bit 24 bit)) (Timer1 (TMR1L TMR1H) de sayıcı registere dahildir.)
Her Timer0 kesmesi geldiğinde de sayıcı registerleri LCD ' ye yazdır ve sonraki ölçüm için sayıcı registerleri (Timer1 ile birlikte) sıfırla.

Ayrıca Picproje E-Dergi 2 de böyle bir konu vardı, oradan da faydalanabilirsin.

Kolay gelsin. :)