I have spent several days researching and modifying code to be able to read the keypresses on a 4x3 matrix keypad. I see that it has been done a gazillion times and I guess there is something that I am just not grasping. I have downloaded several different versions, modified them for the microcontroler I am using, ATMega168A, and I have not been sucessful in getting any of them to work. After trying several modifications on each one to get one to work without success, I decided to pick one and just move forward with that method. I selected a version posted by Bob Gardner as he seems pretty knowlegable and his code looked like it would be fairly easy to modify to work as I needed. If there are others, I am open to suggestion.
So my process was to get the code from Bob to work first. I modified the code to address the correct port for the keypad and then set up an LED to toggle each time a key was identified for testing purposes. I loaded the code and then applied a jumper from PIND0 to PIND3 (which should correspond to C0 and R0 which is #0 ??) The LED should toggle each time the jumper is applied but I didn't get any response. So then I went to the debugger (Atmel Studio 6) and stepped through the code. Watching PINB1, it kept toggling on and off without supplying any input.
So I don't know where the problem is. Here is the modified code:
#include<avr/io.h> char keytab[16]={ // 0 1 2 3 <-col 'C','D','E','F', //3 '8','9','A','B', //2 '4','5','6','7', //1 '0','1','2','3' //0 <-row }; char getkp(void){ //return key pressed on pad outs lo nib, in hi nib unsigned char c,row,col,rowcode,keyndx; for(col=0; col < 4; col++){ PORTD &= ~(0x80 >> col); //out 0,1,2,3 lo asm volatile("nop"); asm volatile("nop"); rowcode=PIND & 0x0F; //7,b,d,e=row 0,1,2,3 PORTD |= 0xff; //all outs off // cprintf(" % 02x\n",rowcode); if(rowcode != 0x0F) break; //this col has a row lo } if(rowcode == 0x0F){ c=0xff; }else{ switch(rowcode){ case 0x07: row=3; break; case 0x0b: row=2; break; case 0x0d: row=1; break; case 0x0e: row=0; break; }//switch keyndx=col*4 + row; c=keytab[keyndx]; } // cprintf("% 02x % 02x % 02x % 02x\n",rowcode,row,col,keyndx); return(c); } int main (void){ DDRB=0xFF; PORTB=0xFF; for(;;){ char keyCode=getkp(); switch(keyCode){ case 0: PORTB ^=1<<PINB1; break; case 1: PORTB ^=1<<PINB2; break; } } }
When stepping through the code I noticed a couple strange issues.
These lines
rowcode=PIND & 0x0F; //7,b,d,e=row 0,1,2,3 if(rowcode != 0x0F) break; //this col has a row lo
So if I understand correctly, without any buttons being pressed, the value of PIND will be 0x00 and then PIND & 0x0F (to check for a value on PIND0-PIND3?) will make PIND still 0x00. Then the if statement is testing for rowcode (0x00) == 0x0F seems to pass the test. Maybe I am not understanding the degugger as it jumps around.
and if I type in the immediate window to print getkp() I get an error...Call to unknown function:getkp
What do I need to do to get this working?