Interfacing matrix keyboard with AVR

Keypad is most widely used input device to provide input from the outside world to the microcontroller. The keypad makes an application more users interactive.  The concept of interfacing a keypad with the ATmega16 is similar to interfacing it with any other microcontroller. Much application requires large number of keys connected to a computing system which includes a PC keyboard, Cell Phone keypad and Calculators. If we connect a single key to MCU, we just connect it directly to i/o line. But we cannot connect; say 10 or 100 keys directly MCUs because it will eat up precious i/o line and MCU to Keypad interface will contain lots of wires.


The rows R0 to R3 are Input to the Microcontroller. They are made input by setting the proper DDR Register in AVR. The columns C0 to C3 are also connected to MCUs i/o line. These are kept at High Impedance State (AKA input), in high z state (z= impedance) state these pins are neither HIGH nor LOW they are in TRI-STATE. And in their PORT value we set them all as low, so as soon as we change their DDR bit to 1 they become output with value LOW.

One by One we make each Column LOW (from high Z state) and read state of R0 to R3.


In the above image as you can see C0 is made LOW while all other Columns are in HIGH Z State. The Value of R0 to R3 is read to get their pressed status. Since the internal pull-ups have been enabled, if the keys are in the high state, the buttons are NOT PRESSED. These pull-ups keep their value high when they are floating (that means NOT connected to anything). But as soon as the key is pressed it gets connected to LOW line from the column thus making it LOW.

After that we make the C0 High Z again and make C1 LOW. And read R0 to R3 again. This gives us status of the second column of keys. Similarly all columns are scanned.


Each i/o port in AVR has three related registers PORTx, DDRx and PINx. For example port A has

  • PORTA Port Driver – when any bit is set to 1 it appears as HIGH i.e. 5v. But this is the case only if that bit is OUTPUT. If it is input, setting any bit to 1 enables the internal pull-up on that bit.
  • DDRA DATA DIRECTION REGISTER – Make any pin on than port as IN or OUT. When bit is 1 it represents Output. When bit is 0 it represents Input. Input state is also called tri-state or high Z state.
  • PINA – Read it to get the level (HIGH or LOW) at the actual i/o pin. It is read when the pin is made input.


Let’s say we selected column number C0, so we make it LOW (i.e. GND or logic 0), in the same time we make all other columns high impedance (i.e. input). If we don’t make other lines high impedance (tri-state or Input) they are in output mode. And in output mode they must be either LOW(GND or logic 0) or HIGH (5v or logic 1). We can’t make other lines LOW as we can select only one line at a time and C0 is already low as per assumption. So the only other possible state is all other columns are HIGH. This is shown in figure below. Red colour on column indicates high state while green is for low state.


If the user presses both keys at the same time, as shown in the figure


As you can see clearly that it create a short between C0 (GND) and C1 (5v), this will burn out the buffer of the MCU immediately!


Hence, all other columns are kept at tri-state (neither LOW nor HIGH) but at very high input impedance that prevent either source or sink of current from them. So if we kept C1 at high as impedance state it won’t allow current to flow to GND on C0.




#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"
#include "myutils.h"
uint8_t GetKeyPressed()
	uint8_t r,c;
			if(!(KEYPAD_PIN & (0X08>>r)))
				return (r*3+c);
	return 0XFF;//Indicate No keypressed
void main()
	//Wait for LCD To Start
	//Now initialize the module
	uint8_t key;
		key=GetKeyPressed();	//Get the keycode of pressed key
		LCDWriteIntXY(0,0,key,3);	//Print it at location 0,0 on LCD.

AVRStudio Project files to download: KEYPAD


Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *