|
|
View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 21, 2005 12:26 am |
|
|
Quote: | "You need pull-ups (or LCD) on COL0, COL1, COL2 (D5-D7)."
"To read the keypad the software will set ROW0 to low, and ROW1,ROW2
and ROW3 to high. If COL0-COL3 all read high then no key in ROW0 is
pressed. The software then sets ROW1 low and the others HIGH. Again if
COL0-COL3 are all high nothing is pressed in that row. If one of the COLx
pins reads low then that column and the row that is now low will indicate
the key that is pressed. The software rotates through all rows and then
repeats." |
Maybe they're looking at a different driver file than me. They have given
a description that is the exact opposite of the way that KBD.C works,
in terms of the Row and Column pins. The KBD.C driver file in
c:\Program Files\Picc\Drivers sets the column lines low, one at a time,
and reads the rows.
The following code is from the kbd_getc() routine. I've added comments
to show what the bitmasks are.
If you look at the kdb_getc() code in KBD.C, you can see that the
column variable "col" is incremented down at the bottom of the routine.
Each time you call it, "col" will cycle through one of the values
of 0, 1, and 2. So, each time you call kbd_getc(), a different "case"
in the switch statement is performed. Notice what they do.
The value "kbd" is equivalent to Port D. They take the inverted
form of the column bitmask, AND it with ALL_PINS, and shove
it out to Port D. They are setting one Column line low, in
sequence, each time they call kbd_getc().
Code: |
#define COL0 (1 << 5) // = 00100000b
#define COL1 (1 << 6) // = 01000000b
#define COL2 (1 << 7) // = 10000000b
// The inverted forms of the column bitmasks are:
// ~COL0 = 11011111b
// ~COL1 = 10111111b
// ~COL2 = 01111111b
// ALL_PINS = 11111110b
#byte kbd = 8
switch (col) {
case 0 : set_tris_kbd(ALL_PINS&~COL0);
kbd=~COL0&ALL_PINS;
break;
case 1 : set_tris_kbd(ALL_PINS&~COL1);
kbd=~COL1&ALL_PINS;
break;
case 2 : set_tris_kbd(ALL_PINS&~COL2);
kbd=~COL2&ALL_PINS;
break;
} |
Here is the row code from KBD.C. Notice that they take
the value of kbd (that is, they read Port D), and they mask
it down with the bitmask of the Row that they want to test.
Since once each pass, a Column line is held low, if a button
is pushed, a connection will be made between that Column
line and a Row line. When they read the Row pins, and
mask it down to a particular row, and if the result is zero,
then they know the column and the row of the button that's
been pushed.
For this to work, the Row pins must have pull-ups on them.
If they're floating, you can't be sure of the bit values
that are read.
Example:
Suppose the button for COL2 and ROW3 is pressed. Let's
assume we're on the 3rd call to kbd_getc() from your main
routine. Then the line for Column 2 will be set low.
First they read kbd (Port D), and mask it down with ALL_ROWS
to see if any Row line is low. If one is low, then they
check to see which specific Row it is. They do this with
a series of if-else statements, below.
When you use the value of "kbd" below, you have read
the whole of Port D. You've read both the Row pins
and the Column pins. But, the code is only testing
the value of the Row pins, because it's using bitmasks
for the Row pins. This is why the Row pins, as inputs,
must have pull-up resistors on them. Otherwise they'd
be floating and you could read any random value. Without
a pull-up, you might read a low value on a Row pin even
though a button wasn't pushed on that row.
Code: |
#define ROW0 (1 << 1) // = 00000010b
#define ROW1 (1 << 2) // = 00000100b
#define ROW2 (1 << 3) // = 00001000b
#define ROW3 (1 << 4) // = 00010000b
if((kbd & (ALL_ROWS))!=(ALL_ROWS)) {
if((kbd & ROW0)==0)
row=0;
else if((kbd & ROW1)==0)
row=1;
else if((kbd & ROW2)==0)
row=2;
else if((kbd & ROW3)==0)
row=3;
|
|
|
|
JimB
Joined: 25 Aug 2005 Posts: 65 Location: Huntington Beach, CA
|
|
Posted: Sat Sep 24, 2005 3:09 am |
|
|
I reviewed the great reply from PCM Programmer and learned a great deal from that reply. However, I did get the keyboard and lcd to work as CCS advertised in their exercise, i.e. I got them to work correctly placing the lcd and the keypad on port D, without any pullups. What is a little confusing is that without the program running I measured the voltages on the port D pins and found the following.
D0 - low, D1 - +5V, D2 - +5V, D3 - low, D4 - low, D5 - +5V, D6 - low, and D7 - low. The same hold when the program is loaded but no keypad buttons pushed. This implies that two rows and one column is pulled up by the lcd??????
Where is the book that explains all this stuff in detail. Seems like this forum and all the code displayed is becoming my best instructor. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Sep 24, 2005 11:41 am |
|
|
Download the specification for the controller chip used on many
characters LCDs:
http://www.melabs.com/downloads/hd44780u.pdf
Go to page 54, which shows a schematic of the input circuits.
Notice that signals DB0-DB7, R/W, and RS, are labeled with "pull up MOS".
This means they are using a MOSFET to create a weak pullup on those pins.
On page 48, they say the typical pull-up current is 50ua at 3v.
This means the pullups are typically 60K ohms.
While I was searching for the LCD driver document above, I also
found a good appnote from Maxim on keypad interfacing.
http://www.maxim-ic.com/appnotes.cfm/appnote_number/3414
It can also be downloaded as a PDF, at the bottom of the page. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|