Elektronik / Mikrodenetleyici Projeleri/

3-Wire Keypad

Her gün kullandığımız, fakat hiç bir zaman önemsemediğimiz bir araç keypad. Özellikle telefonlarda ve şu ara moda olan otomatik yiyecek makinelerinde kullanılan bu aracı biz elektronikçiler de oldukça fazla kullanıyoruz, elbette teknik anlamda.

Öncelikle 8051 derslerimde kullandığım keypad’i hep 7 ya da özel entegresiyle birlikte 4-5 kabloyla kullandım. Yaptığım son projede ise debounce ayarını yanlış hesapladığım için işverenden oldukça fazla şikayet alıp, bir daha gerekmedikçe kullanmamaya dikkat ettim. Fakat bugün, hem de picbasic ile ilgili bir sitede, öyle bir şey gördüm ki bununla ilgili bir örnek yapmadan duramadım.

3-Wire-Keypad-protes-isis

Yukarıdaki şema incelendiğinde (üzerine basarsanız büyür) 5V’luk gerilim 1kΩ’luk dirençler sayesinde 1V aralıklarla bölünüp bunlar keypad’e girilmiş ve 100kΩ’lık dirençler üzerinden Atmega16’nın 3 ADC kanalına ulaşılmıştır. Butonlara basıldığında oluşacak gerilim değişimini minimum seviyede tutmak için çıkışlarda 100kΩ’luk direnç kullanılmıştır. 7 kablo kullanıldığında uyguladığımız tarama mantığının benzerini yazdığım kodlarda görebilirsiniz.

3-Wire Keypad Örneğii:

/* **** www.FxDev.org ****
 * 3-Wire Keypad Demo Code
 */
#include "avr/io.h"
#include "lcd.h"
#include "avr/interrupt.h"

#define ADC_REF_AREF 0x00
#define ADC_REF_AVCC 0x40
#define ADC_REF_INT  0xC0

#define dEBOUNCE	50		// dEBOUNCE süresi kaç milisaniye olacak
#define BEKLEME		1200	// Bu sabit tuşlara basılı olduğunda kaç saniye sonra tuşun aktif olacağını belirtir

unsigned char 	ADC_REF_TYPE;
volatile int 	dbtmr=-1,
				menugecis=0;

ISR(TIMER1_OVF_vect)	// Timer1 taşma kesmesi
{
	TCNT1=0xFF83;	// TCNT1, 16 bitlik registerine 64286 yükleniyor

	if(dbtmr>=0) 		dbtmr++;
	if(menugecis>0) 	menugecis--;
}

void adc_init(unsigned char ADC_REF)
{
	ADCSRA = 0x87;
	ADC_REF_TYPE = ADC_REF;
}

unsigned int read_adc(unsigned char adc_channel)
{
	ADMUX = ADC_REF_TYPE | adc_channel;
	ADCSRA |= 0x40;
	while (ADCSRA & 0x40);
	return ADC;
}

unsigned char keypad(void)
{
	unsigned int gerilim=0;
	unsigned char key='\n';

	gerilim=read_adc(0);
	if(gerilim>100 && gerilim< =256) key= '*';
	if(gerilim>256 && gerilim< =512) key= '7';
	if(gerilim>512 && gerilim< =768) key= '4';
	if(gerilim>768) 		 key= '1';

	gerilim=read_adc(1);
	if(gerilim>100 && gerilim< =256) key= '0';
	if(gerilim>256 && gerilim< =512) key= '8';
	if(gerilim>512 && gerilim< =768) key= '5';
	if(gerilim>768) 		 key= '2';

	gerilim=read_adc(2);
	if(gerilim>100 && gerilim< =256) key= '#';
	if(gerilim>256 && gerilim< =512) key= '9';
	if(gerilim>512 && gerilim< =768) key= '6';
	if(gerilim>768) 		 key= '3';

	return key;
}

unsigned char readkeyboard(void)
{
	static char prev=0,prev1=0;
	char        curr=0,returnvalue=0;

	curr=keypad();

	if(curr!=prev1)
	{
	   dbtmr=0;
	   prev1=curr;
	   returnvalue=prev;
	}
	else
	{
		if(dbtmr>=dEBOUNCE)
		{
			prev=curr;
			prev1=curr;
			returnvalue=curr;
			dbtmr=-1;
		}
		else
		{
			returnvalue=prev;
		}
	}
	return returnvalue;
}

int main(void)
{
	PORTC=0x00;
	DDRC=0xFF;

	lcd_init();
	adc_init(ADC_REF_AVCC);

	TCNT1=0xFF83;		// TCNT1, 16 bitlik registerine 65411 yükleniyor
	TCCR1B=0x02;		// Prescaler değeri 1:8
	TIMSK|=0x04;		// Timer1 taşması kesmesi aktif

	sei();			// Genel kesmeler aktif ediliyor

	lcd_gotoxy(1,1);	// LCD'nin ilk karekterine gidiliyor
	menugecis=100;		// 100ms bekleniyor
	for(;;)
	{
		if((readkeyboard()!='\n')&& ( menugecis == 0))	// Tuşa basıldı mı
		{
			menugecis=BEKLEME;
			veri_yolla(readkeyboard());		// Basılan değer LCD'ye gönderiliyor
		}
	}
}

Kodları, ilk defa debounce sorunu yaşayan kişileri düşünerek, bu sorunu giderip, gerçek hayatta uygulanabilecek yapıda yazdım. Böylece, en azından, bu sorunu yaşayan arkadaşlarımıza yardımcı olacağımı düşünüyorum.
Herkese iyi çalışmalar.

Dip not: Okul ve ARM çalışmalarım nedeniyle bu sıralar yazılarım seyrekleşebilir.

Teşekkür: Debounce konusundaki yardımları için ENKO Elektronik’ten Hüseyin TUNA’ya sonsuz teşekkürler.

  1. hsyntuna 2013/05/17

Yorum

Soru: