Haberler:

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

Ana Menü

KBD.C

Başlatan iruraz, 15 Aralık 2009, 22:43:21

iruraz

Herkese merhaba,

CCS içinde bulunan KBD.C nasıl kullanılır? 16f877 kullanarak bir şifreli kilit yapmak istiyorum da bir türlü "kbd_getc();" fonksiyonunu kullanarak tuş takımından değer alamıyorum. Aşağıda eksik halleriyle de olsa kodları yazdım. Bu konuda bilgisi olanlar yardımcı olabilirse sevinirim.
devrenin görünümü:
http://img504.imageshack.us/img504/5218/keypad2.png

#include <16F877.h> 
#fuses HS,NOWDT,NOPROTECT,NOLVP 
#use delay(clock=4000000) 
  
#define use_portd_lcd TRUE
#define use_portb_kbd TRUE

#include <kbd.c> 
#include <lcd.c> 



void main() { 
   char k; 

   lcd_init(); 
   kbd_init(); 

   lcd_putc("\fReady...\n"); 

   while (TRUE) 
   {
      lcd_gotoxy(2,2);
      k=kbd_getc(); 
      printf(lcd_putc,"%c ",k); 
   } 
}

JKramer

#define use_portb_kbd TRUE

Bu satırı silip kbd.c içinde aktif (un-comment) yapmanız gerekiyor. Eğer Lcd ve tuş takımlarında istediğiniz pini kullanmak istiyorsanız flex_lcd.c ve flex_kbd.c dosyalarını kullanabilirsiniz:

Flexible LCD Driver
Flexible Keypad Driver


Bunun dışında kbd.c içinde yazdığı gibi "kbd_getc();" ile geri dönen değer basılan tuştur, eğer herhangi bir tuşa basılmamışsa "\0" karakteridir. Bu yüzden önce tuşa basılıp basılmadığını kontrol etmeniz gerekiyor:
...
while (TRUE) 
   { 
      lcd_gotoxy(2,2); 
      k=kbd_getc();
      if(k!='\0') //Tuşa basılmışsa
     {
        printf(lcd_putc,"%c ",k);
     } 
   }
...

iruraz

@JKramer yardımınız için teşekkür ederim. Kodu dediğiniz gibi değiştirdim fakat gene bir şey göremedim. "kbd.c" içinde dediğiniz değişikliği yaptım ama  olmadı. "flex_kbd.c" ile denedim ve pinleri bağlantıya göre değiştirdim gene olmadı bir yerlerde yanlış yapıyorum ama fark edemedim onun için kodlar tekrar yazıyorum. Galiba değerleri tarama yöntemiyle alsam daha iyi olacak görünüyor.
flex_kbd.c
#define col0 PIN_B0 
#define col1 PIN_B1 
#define col2 PIN_B2 
#define row0 PIN_B3 
#define row1 PIN_B4 
#define row2 PIN_B5 
#define row3 PIN_B6 

// Keypad layout: 
char const KEYS[4][3] = {{'1','2','3'}, 
                         {'4','5','6'}, 
                         {'7','8','9'}, 
                         {'*','0','#'}}; 

#define KBD_DEBOUNCE_FACTOR 33    // Set this number to apx n/333 where 
                                  // n is the number of times you expect 
                                  // to call kbd_getc each second 



void kbd_init() { 
} 


short int ALL_ROWS (void) 
{ 
   if (input (row0) & input (row1) & input (row2) & input (row3)) 
      return (0); 
   else 
      return (1); 
} 



char kbd_getc( ) { 
   static byte kbd_call_count; 
   static short int kbd_down; 
   static char last_key; 
   static byte col; 

   byte kchar; 
   byte row; 

   kchar='\0'; 
   if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) { 
       switch (col) { 
         case 0   : output_low(col0); 
               output_high(col1); 
               output_high(col2); 
                    break; 
         case 1   : output_high(col0); 
               output_low(col1); 
               output_high(col2); 
                    break; 
         case 2   : output_high(col0); 
               output_high(col1); 
               output_low(col2); 
                    break; 
       } 

       if(kbd_down) { 
         if(!ALL_ROWS()) { 
           kbd_down=false; 
           kchar=last_key; 
           last_key='\0'; 
         } 
       } else { 
          if(ALL_ROWS()) { 
             if(!input (row0)) 
               row=0; 
             else if(!input (row1)) 
               row=1; 
             else if(!input (row2)) 
               row=2; 
             else if(!input (row3)) 
               row=3; 
             last_key =KEYS[row][col]; 
             kbd_down = true; 
          } else { 
             ++col; 
             if(col==3) 
               col=0; 
          } 
       } 
      kbd_call_count=0; 
   } 
  return(kchar); 
}


kbd.c:
#define use_portb_kbd TRUE

// Make sure the port used has pull-up resistors (or the LCD) on
// the column pins


#if defined(__PCH__)
#if defined use_portb_kbd
   #byte kbd = 0xF81                   // This puts the entire structure
#else
   #byte kbd = 0xF83                   // This puts the entire structure
#endif
#else
#if defined use_portb_kbd
   #byte kbd = 6                  // on to port B (at address 6)
#else
   #byte kbd = 8                 // on to port D (at address 8)
#endif
#endif

#if defined use_portb_kbd
   #define set_tris_kbd(x) set_tris_b(x)
#else
   #define set_tris_kbd(x) set_tris_d(x)
#endif



//Keypad connection:   (for example column 0 is B2)
//                Bx:

#ifdef blue_keypad  ///////////////////////////////////// For the blue keypad
#define COL0 (1 << 2)
#define COL1 (1 << 3)
#define COL2 (1 << 6)

#define ROW0 (1 << 4)
#define ROW1 (1 << 7)
#define ROW2 (1 << 1)
#define ROW3 (1 << 5)

#else ////////////////////////////////////////////////// For the black keypad
#define COL0 (1 << 5)
#define COL1 (1 << 6)
#define COL2 (1 << 7)

#define ROW0 (1 << 1)
#define ROW1 (1 << 2)
#define ROW2 (1 << 3)
#define ROW3 (1 << 4)

#endif

#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2)

// Keypad layout:
char const KEYS[4][3] = {{'1','2','3'},
                         {'4','5','6'},
                         {'7','8','9'},
                         {'*','0','#'}};

#define KBD_DEBOUNCE_FACTOR 33    // Set this number to apx n/333 where
                                  // n is the number of times you expect
                                  // to call kbd_getc each second


void kbd_init() {
}

char kbd_getc( ) {
   static BYTE kbd_call_count;
   static short int kbd_down;
   static char last_key;
   static BYTE col;

   BYTE kchar;
   BYTE row;

   kchar='\0';
   if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
       switch (col) {
         case 0   : set_tris_kbd(ALL_PINS&~COL0);
                    kbd=~COL0&ALL_PINS;
                    break;
         case 1   : set_tris_kbd(ALL_PINS&~COL1);
                    kbd=~COL1&ALL_PINS;
                    break;
         case 2   : set_tris_kbd(ALL_PINS&~COL2);
                    kbd=~COL2&ALL_PINS;
                    break;
       }

       if(kbd_down) {
         if((kbd & (ALL_ROWS))==(ALL_ROWS)) {
           kbd_down=FALSE;
           kchar=last_key;
           last_key='\0';
         }
       } else {
          if((kbd & (ALL_ROWS))!=(ALL_ROWS)) {
             if((kbd & ROW0)==0)
               row=0;
             else if((kbd & ROW1)==0)
               row=1;
             else if((kbd & ROW2)==0)
               row=2;
             else if((kbd & ROW3)==0)
               row=3;
             last_key =KEYS[row][col];
             kbd_down = TRUE;
          } else {
             ++col;
             if(col==3)
               col=0;
          }
       }
      kbd_call_count=0;
   }
  set_tris_kbd(ALL_PINS);
  return(kchar);
}


kendi program kodum:
#include <16f877.h>     // Kullanılacak denetleyicinin başlık dosyası tanıtılıyor.

// Denetleyici konfigürasyon ayarları
#fuses HS,NOWDT,NOPROTECT,NOLVP 

#use delay (clock=4000000) // Gecikme fonksiyonu için kullanılacak osilatör frekansı belirtiliyor.

#use fast_io(b) //Port yönlendirme komutları B portu için geçerli
#use fast_io(d) //Port yönlendirme komutları B portu için geçerli

#define use_portd_lcd TRUE   // LCD B portuna bağlı

#include <lcd.c>   // lcd.c dosyası tanıtılıyor
#include <kbd.c>

char k;

void main()
{
   setup_psp(PSP_DISABLED);        // PSP birimi devre dışı
   setup_spi(SPI_SS_DISABLED);     // SPI birimi devre dışı
   setup_timer_1(T1_DISABLED);     // T1 zamanlayıcısı devre dışı
   setup_timer_2(T2_DISABLED,0,1); // T2 zamanlayıcısı devre dışı
   setup_adc_ports(NO_ANALOGS);    // ANALOG giriş yok
   setup_adc(ADC_OFF);   
   
   kbd_init();
   lcd_init();
   
   while(1)
   {
      lcd_gotoxy(2,2); 
      k=kbd_getc(); 
      if(k!='\0') //Tuşa basılmışsa 
     { 
        printf(lcd_putc,"%c ",k); 
     } 
   }
   
}

JKramer

Denedim, birkaç değişiklikle çalışıyor. Yalnız son gönderdiğiniz kodda "#use fast_io(b)" kullanmışsınız. Eğer bunu kullanıyorsanız "set_tris_x()" (x port harfi) ile o portun hangi pinlerinin giriş, hangi pinlerinin çıkış olacağını önceden tanıtmanız gerekir. Bu satırı yazmazsanız derleyici "#use_standart_io()" olarak algılayacaktır, yani bir şey yazmanıza gerek yok şu aşamada.

Belki proteus'ta devreyi hazırlarken bir hata yaptınız, resim küçük olduğu için emin değilim. Bu yüzden bende çalışan dosyaların hepsini bir araya koyup yükledim, buradan indirebilirsiniz.

Bana lcd ile ilgili bir sorun var gibi geliyor, indirdiğiniz dosyalarla kendi dosyalarınızı karşılaştırısınız. Bir de bu gibi durumlarda (sorun tuş takımında mı lcd'de mi) tek tek deneyerek sorunu daha hızlı çözebilirsiniz. Mesela öncelikle tuş takımından okuma yapmadan sadece sabit bir değeri lcd'ye yazdırıp sonuca bakarsınız ya da lcd'ye yazdırmadan sadece tuş takımından okunan değere göre bir led yakarsınız.

Unutmadan, include dosyalarının isimlerini ana programda da değiştirmelisiniz;
#include <flex_kbd.h>
CCS programının kurulu olduğu klasördeki dosyayı,
#include "flex_kbd.h"
derlediğiniz programın içinde olduğu klasördeki dosyayı ekler. Gönderdiğim dosyaların hepsi aynı klasörde olduğundan çift tırnak (") içine aldım.

iruraz

Yardımlarınız için çok teşekkür ederim. Bastığım tuşun karşılığını lcd'de görebiliyorum. Asıl amacım şifreli kilit yapabilmek. Bu aldığım değerlerden 4 haneli bir şifreyi nasıl oluşturabilir ve bunu eeprom'daki başlangıç değeri ile nasıl karşılaştırabilirim acaba? Tabi menüde şifre değiştirme de mümkün olmalı. Fonksiyonlar oluşturarak bir şeyler yapmaya çalıştım fakat olmadı. Bir  yol gösterirseniz sevinirim. Çok şey sorduğumun farkındayım, kusuruma bakmayın lütfen...

JKramer

Öncelikle adımlarımızı belirleyelim:

1- Tuş takımından aldığımız değerleri bir değişkende (okunan_şifre) toplama
2- Bu değişkeni en başta belirlediğimiz sabit bir değerle (gercek_şifre) karşılaştırma
3- Eeprom'a başlangıç değerini yazma, karşılaştırma yapmadan önce değeri okuyup bir değişkene atma
4- Şifre değiştirme.

Her bir adım için mutlaka ayrı program dosyaları oluşturun, (şifreli_kilit_v1, şifreli_kilit_v2 gibi) böylece nerede hata yaptığınızı daha kolay yakalayabilirsiniz.

Birinci adımdan başlayalım. Dikkat ettiyseniz tuş takımından okuduğumuz değerler integer değil character. Bu yüzden okuduğumuz değerleri bir dizide toplayıp daha sonra integer'a çevirmeliyiz. Çevirme işlemi için atoi() (8-bit için), atol() (16-bit için) ya da atoi32() (32-bit için) fonksiyonlarını kullanabiliriz. Şifremiz kaç basamaklı olacaksa ona uygun fonksiyonu kullanmalıyız. CCS'in yardım dosyasında fonksiyonun kullanımı ile ilgili örnekler mevcut. Buraya kadar biraz inceleyin, takıldığınız yerde tekrar bakarız.

iruraz

@JKramer yardımlarınız için çok çok teşekkür ederim. Benim beceremediğim bu 4 haneli sayıyı oluşturmak ccs-manuel'den dediğiniz fonksiyona baktım. Bu 4 haneli sayıyı oluşturuken döngü mü kullanmalıyım? Bu işlerde çok acemi olduğum için bir türlü ilerleme sağlayamıyorum. Ayrıca bunu haftaya kadar yetiştirmem gerekiyor.