Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

Amazon Re: [AVR-Chat] The keyboard

2005-02-20 by brewski922

--- In AVR-Chat@yahoogroups.com, "Stefan Trethan" 
<stefan_trethan@g...> wrote:
> On Fri, 18 Feb 2005 15:16:04 -0500, Dave VanHorn <dvanhorn@d...>  
> wrote:
> 
> >
> > The easy way to do a matrix keyboard, is to take rows (or 
columns) and  
> > make
> > them inputs pulled up, and take the other side (col or row) and 
make them
> > the scanned outputs, active low.
> > So, when you are seeing all highs, no keys are pressed.
> > When you see a low on any row, then you check what col you have 
set low,
> > and now you know what key(s) are pressed.
> >
> 
> 
> I am currently making something with a 3x4 keyboard.
> I have connected the 3 columns to the 3 external iterrupts, and the 
4 rows  
> to I/O.
> The plan is to set the column pins (interrupts) to pullup, and 
input, and  
> the rows to output, low.
> My hope is when someone presses a key the interrupt line goes low, 
causing  
> a interrupt and in the ISR i switch the rows input and columns 
output to  
> see which button it was.
> 
> Would be nice to know if this will actually work, i just guessed...
> 
> ST

Haven't read messages in a day or so. Below is an interrupt driven 
program that scans a Grayhill Series 88 3x4 keypad. I completted it a 
week or so ago.
Mike

/*****************************************************
This program was produced by the
CodeWizardAVR V1.24.4a Standard
Automatic Program Generator
© Copyright 1998-2004 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
e-mail:office@hpinfotech.com

Project : 
Version : 
Date    : 1/31/2005
Author  : Mike Bronosky                   
Company : ICU LLC                         
Comments: 


Chip type           : ATmega8515
Program type        : Application
Clock frequency     : 4.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 128
*****************************************************

  PORTD.0..2 will be column outputs
  PIND.4..6 will be row inputs
  PORTD.3 Ext Int 1
  
  Connect the keypad matrix as follows:
   
 PORTD.3   D4
 Ext  -o--|>|-------   D4 - D7 = 1N4148
 Int1  |   D5       |
       o--|>|-----  |
       |   D6     | |
       o--|>|---  | |
       |   D7   | | |
        --|>|-  | | |
              | | | |
  PORTD      | | | |     [KEYS]
  5 PD4 ------------o---1----2----3
              | | |     |    |    |
  6 PD5 ----------o-----4----5----6
              | |       |    |    |
  7 PD6 --------o-------7----8----9
              |         |    |    |
  8 PD7 ------o---------10---11---12
                  D1    |    |    | 
  1 PD0 ----------|<|---     |    |   D1 - D3 = 1N4148  
                  D2         |    | 
  2 PD1 ----------|<|--------     |
                  D3              | 
  3 PD2 ----------|<|------------- 
   
  Use an 2x20 alphanumeric LCD connected
  to PORTC as follows:

  [LCD]   [STK500 PORTC HEADER]
   1 GND- 9  GND
   2 +5V- 10 VCC  
   3 VLC- LCD contrast control voltage 0..1V
   4 RS - 1  PC0
   5 RD - 2  PC1
   6 EN - 3  PC2
  BLite -    PC3
  11 D4 - 5  PC4
  12 D5 - 6  PC5
  13 D6 - 7  PC6
  14 D7 - 8  PC7
*/

#include <mega8515.h>

// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x15 ;PORTC
#endasm
#include <lcd.h>
#include <stdlib.h>
#include <delay.h>

#define Enable 0
#define Disable 1
void Scan(int i);
void DoCase(int ii);

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
// Place your code here
//delay_ms(50);
if (PIND.3==0) {
PORTD=0xFF;
//delay_ms(50);
//Column 1
  PORTD.0=Enable;
  Scan(0);
  PORTD.0=Disable;
//Column 2
  PORTD.1=Enable;
  Scan(1);
  PORTD.1=Disable;
//Column 3
  PORTD.2=Enable;
  Scan(2);
  PORTD.2=Disable;
  }
PORTD=0xF8;
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In 
Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T 
State0=T 
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In 
Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T 
State0=T 
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In 
Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T 
State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=Out Func1=Out 
Func0=Out 
// State7=T State6=T State5=T State4=T State3=T State2=0 State1=0 
State0=0 
PORTD=0xF8;
DDRD=0x07;

// Port E initialization
// Func2=In Func1=In Func0=In 
// State2=T State1=T State0=T 
PORTE=0x00;
DDRE=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: On
// INT1 Mode: Falling Edge
// INT2: Off
GICR|=0x80;
MCUCR=0x08;
EMCUCR=0x00;
GIFR=0x80;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;

// LCD module initialization
lcd_init(16);

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here

      };
}
void Scan(int i)
{
if ((PIND & 0XF0) != 0xF0) {
  switch(PIND & 0xF0){
    case 0b11100000: DoCase(1 + i);
      break;
    case 0b11010000: DoCase(4 + i);
      break;
    case 0b10110000: DoCase(7 + i);
      break;
    case 0b01110000: DoCase(10 + i);
      break;
    default: DoCase(PIND);
    }
  }
}

void DoCase(int ii)
{
  char s[1];
  lcd_clear();
  itoa(ii, s);
  if (ii<=9) lcd_putsf(" ");
  lcd_puts(s);
}

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.