interface lcd and keypad with atmega88

Thread Starter

mr_l

Joined Aug 20, 2011
12
Hello everyone.
I am a bit stuck with one task and i need help.
I am trying to read input from keypad and display it on the display.
I first wrote the program code which reads the input from the keyboard and tested it with LEDs and it works
well.
Then I wrote code that prints text to display with no input from the keyboard and then tested it and it also
works well.
But when I put together whole code it does not work as it should.
I am new in programming of embedded systems and i know
that my code is not the best and that probably has a lot of mistakes but I try to do the best they can.
Here is my code

Rich (BB code):
#define F_CPU 8000000UL
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>



#define RS 0 //pin nr in port
#define RW 1 //pin nr in port
#define E 2 //pin nr in port

FILE *myFile;
void write_LCD(unsigned char data, FILE *stream);
int get_char(FILE *stream);
void write_instruction(unsigned char data);
void init_LCD(void);
void delay8us(void);


void delay8us(void) {
volatile unsigned char x;
for(x=0;x<5;x++);
}

void test_if_busy(void) {
unsigned char x;
PORTC &=~(1<<RS);
PORTC |= (1<<RW);
DDRB &=~(1<<7);		// input
PORTB &=~(1<<7);	// remove pullup
do {
PORTC |= (1<<E);
delay8us();
x = (PINB & 0x80); // read high nibble
PORTC &=~(1<<E);
PORTC |= (1<<E);
PORTC &=~(1<<E);	// read low nibble
		 
}
while(x);
DDRB |= (1<<7);	// output
}

void write_LCD(unsigned char data, FILE *stream) {
char x;
PORTB = (data & 0xf0); //high nibble
PORTC &=~(1<<RW);
PORTC |= (1<<RS);
PORTC |= (1<<E);
PORTC &=~(1<<E);
x = (data<<4);
 _delay_ms(65);
PORTB = x; //low nibble
PORTC &=~(1<<RW);
PORTC |=(1<<RS);
PORTC |=(1<<E);
PORTC &=~(1<<E);
test_if_busy();
}

char get_key(void)
{
volatile char button;
volatile char position;

button = PINB;

if (button == 0b01111011)
position = 49;
else if (button == 0b01111101)
position = 50;
else if (button == 0b01111110)
position = 51;
else if (button == 0b10111011)
position = 52;
else if ( button == 0b10111101)
position = 53;
else if ( button == 0b10111110)
position = 54;
else if ( button == 0b11011011)
position = 55;
else if ( button == 0b11011101)
position = 56;
else if ( button == 0b11011110)
position = 57;
else if ( button == 0b11101011)
position = 8;
else if ( button == 0b11101011)
position = 48;
else if ( button == 0b11101101)
position = 13;
else if ( button == 0b11101110)
position = 68;
else if (button == 0b11101111)
position = 5;
return position;
}


int get_char(FILE *stream){
char c;
volatile char column;
volatile char row;

do{
row = 0b01111111;	// send 0 to first row
for (int i = 0; i<2; i++){ 
PORTB = row;
column = PINB;		// read input from keypad
}

for(int i = 0, a = 64; i<5; i++){  // check all 4 rows
if(column == row)// if key is not pressed in first row
row = column + a;		// check next row 
for(int j = 0; j < 2; j++){ 
PORTB = row;
column = PINB;
}
i++;
a = a/2;
}   
else
c = get_key();
}
c = get_key();
}while(column == 0b11101111); // if neither key is not pressed repeat loop

write_LCD(c, stream);
return (int)c;
	
}


void write_instruction(unsigned char data) {
unsigned char x;

PORTB = (data & 0xf0);
PORTC &=~(1<<RW);
PORTC &=~(1<<RS);
PORTC |= (1<<E);
PORTC &=~(1<<E);
x = (data<<4);
PORTB = x;
PORTC &=~(1<<RW);
PORTC &=~(1<<RS);
PORTC |= (1<<E);
PORTC &=~(1<<E);
test_if_busy();
}


void set4bitmode() {
_delay_ms(65);
PORTB = (0x20 & 0xf0);
PORTC &=~(1<<RW);
PORTC &=~(1<<RS);
PORTC |= (1<<E);
PORTC &=~(1<<E);
}


 void init_LCD(void) {
unsigned char x;
for(x= 0;x<5;x++) {
_delay_ms(65);
}
PORTB = 0; //all low
PORTC &=~(1<<RS);
PORTC &=~(1<<RW);
PORTC &=~(1<<E);
DDRB = 0xF0; // all output
PORTB = 0x0F;
DDRC |= (1<<RS);
DDRC |= (1<<RW);
DDRC |= (1<<E);
_delay_ms(65);
set4bitmode(); // 4 bit interface
for(x=0;x<3;x++) {
write_instruction(0x28);
_delay_ms(65);
}
write_instruction(0x0F);
write_instruction(6);
write_instruction(1);
}


int main(void) 
{
char teck;
init_LCD();
write_instruction(1); // clear display
myFile = fdevopen(write_LCD, get_char);
	
while(1){

scanf("%c", &teck);
printf("%d",teck);
}
}
 

hgmjr

Joined Jan 28, 2005
9,029
Can you post a schematic of your circuit? That will give us crucial information needed to assist you with diagnosing your problem.

hgmjr
 

hgmjr

Joined Jan 28, 2005
9,029
Without a schematic it is difficult to confirm everything but from the looks of your code you are using PORTB for both the LCD display data as well as your keypad scanning function.

Is that being done intentially?

hgmjr
 

Thread Starter

mr_l

Joined Aug 20, 2011
12
Here is scheme of my circuit



I solved the problem I changed port i mean i put all lcd pins
on the PORTC and now it works. But now i have another problem.
Number printing works fine but as soon as I press the letter or symbol it prints
pressed letter and then lot of unpressed numbers.
I thought first that this is due data types so i tested to change type of variable position in int type but the result was the same. Have you any idea what it could be.
 

hgmjr

Joined Jan 28, 2005
9,029
Circuit diagram attachment did not appear. Can you try again?

hgmjr
 

hgmjr

Joined Jan 28, 2005
9,029
I will have to wait until after work to view your schematic since the website that you used to post the schematic is blocked on my company network.

hgmjr
 

ErnieM

Joined Apr 24, 2011
7,992
Here's mr_l's schematic:



(mr_l: in the advanced post window there is a box to hit to add in the url of pictures like this. The icon is a sun over a hill with a yellow sky.)
 

ErnieM

Joined Apr 24, 2011
7,992
I can't really follow your code but it seems there is no check for a key to be unpressed, meaning you press it once and then whenever the loops returns it again prints the key. Or possibly a debouncing issue.

Has your code changed since you added it above?
 

hgmjr

Joined Jan 28, 2005
9,029
I think we could use an update to your code since you said that you have altered your code.
 

Thread Starter

mr_l

Joined Aug 20, 2011
12
I solved the problem. First as I said, I put all LCD pins on the portC
and LCD started to work.
Another problem I've solved so that I changed

Rich (BB code):
 char get_key(void) into int get_key(void)
because get_key function () should be returned characters ASCII value

I then deleted the row
Rich (BB code):
 write_LCD(c, stream);
because it returns the value of printf () function and has nothing to do with scanf() function
so
Rich (BB code):
 int get_char(FILE *stream)
function returns value to scanf() function
and the last thing I changed is in main() function
Rich (BB code):
printf("%d",teck); into 
printf("%c",teck);
And as I said, now it works well
In any case thanks for the help guys
 
Last edited:

hgmjr

Joined Jan 28, 2005
9,029
Can we please request that you put your latest code (That works) into this thread so that future users can have the benefit of seeing your solution?

hgmjr
 
Top