Preloader image

8051 Tutorial 2

Ok… Back on track.


The next tutorial we need to read a 4 x 3 ( 12 key ) keypad…


If we attach a keypad to port 0 and place some resistors as external pull up’s we can read can read the 12 possible on the keypad on only 7 pins… 4 pins as columns and 3 pins as rows.. Here is the connection I used… I have included a 7 segment LED as a simple visual response…




The pinout is shown above… We don’t have enough power to sink the current so I used a line driver.. The 74C245 is a bidirectional buffer… We can output a small current on the micro and the buffer will allow more current to be used for the LED’s, the maximum current is 24mA on each pin so with a 470 ohm current limiting resistor will still give a good visual output on the display..


Attach a common cathode display to our circuit like so..




The keypad will require pullup resistors ( I have used 1k ) on the row pins… The way I read a keypad is by making each column negative ( 0 volts ) in turn, then if a key is being pressed it will show on the 4 row pins 0~3..


Here is the code in ASM to read a keypad and display the same value on the display.


Code 7
Code (asm):
org    0        ; Reset vector
sjmp    Startorg    30H        ; Code starts here
clr    A        ; A = 0
acall    keypad    ; Fetch keypress ( mono…only one key at a time )
acall    delay    ; delay so we see it
acall    Display    ; Show on display
sjmp    While    ; do it again ( Forever loop )keypad:
mov    R1,#0EFH    ; keymask
mov    R2,#3        ; Three columns
mov    A,#1
clr    C
mov    P0,R1        ; ready keypad mask
jb    P0.0,row2    ; Key pressed? row 1
sjmp    keydone    ; found a key
jb    P0.1,row3    ; Key pressed? row 2
add    A,#1
sjmp    keydone    ; found a key
jb    P0.2,row4    ; Key pressed? row 3
add    A,#2
sjmp    keydone    ; found a key
jb    P0.3,nextcol    ; Key pressed? row 4
add    A,#3
sjmp    keydone    ; found a key
add    A,#4        ; add row count…0,4,8 + key press
push    Acc        ; save count
mov    A,R1        ; get mask
setb    C        ; Rotate with
rlc    A            ; carry R1 mask
mov    R1,A        ; store new mask
pop    Acc            ; restore the count
djnz    R2,OLoop    ; Last column???
clr    A            ; No keys detected…
keydone:            ; return with keypad condition
mov    DPTR,#digits    ; Use A to get 7 segment pattern
movc    A,@A+DPTR    ;
;cpl    A        ; Common cathode… Uncomment for common anode.
mov    P1,A        ;  put pattern on port 1

delay:    mov    R2,#225    ; 2 clock cycles (call)        = 2
mov    R1,#0        ; 2 clock cycles (loading)    = 2
djnz    R1,d1    ; 2 * 256 clock cycles *225    = 115200
djnz    R2,d1    ; 2 * 225 clock cycles     = 450
ret                ; 2 clock cycles (return)    = 2

digits:    db    03FH,006H,005BH,04FH,066H,06DH,07DH,007H,07FH,06FH,077H,07CH,039H            ; 7 segment patterns 0 to C


This is getting near to pixel output… The patterns to create the digits 0 ~ C are stored similar to bitmaps… The code bitmaps are for common cathode displays.. If you use a common anode (as I have done ) then the complement “cpl A” command inverts the output…


The key pad read function is looped three times whilst keeping an eye on the four row inputs.


As the resistors keep the pins in a high state, the columns are pulsed low in turn, if the pin s 0 ~ 3 are low then a key press is detected and whilst we keep a track of the loop the count stored in A will give us the actual key pressed.


There are some low level things we can’t do in C so we have little work rounds.. Take this command.


rlc A. We can’t rotate left with carry, In C the shift left operator ‘<<‘ will clear the LSBit . ie.. 11101111 ( 0xEF) after the shift will become 11011110 ( 0xBE) so we have to remember in this instance to add one to make the shift work as we want…


Here is the C version..

Code 8
Code (c):
#include<8051.h>        // definition file.unsigned char digits[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D
,0x07,0x7F,0x6F,0x77,0x7C,0x39};void delay(void)        // How to get 125mS..
int x = 10500;        // The while statement consumes 11.89uS (11 clock cycles )
while(x–);        // So 10500 * 11.89uS = nearly 125mS.
}char keypad(void)
unsigned char keymask = 0xEF;
char key = 0, x;
for(x=0;x<3;x++)        // Three columns.
P0 = keymask;    // check each
if(!P0_0) key = 1;    // bit for
if(!P0_1) key = 2;
if(!P0_2) key = 3;    // key detect.
if(!P0_3) key = 4;
{        // If we see a key press we
key += (x*4);    // need to add in the loop.
return key;
keymask<<=1;    // We have no status control in C so we manually
keymask++;        // shift a bit into the mask register..
}            // or the LSBit will be an output !sizzle!..
return key;

void display(unsigned char dt)
P1 = ~digits[dt];    // Common anode uses ‘~’ delete for common cathode.

void main(void)            // Main entry point

while(1)            // Forever loop
display(keypad());    // we can nest functions in C like this
delay();        // delay..


Hopefully you can now start to see a difference in C when you are entering code..


C has 28 lines of code and ASM has 46… We can optimise the ASM. code to use mackro’s and use symbols for better readability, but with C identifiers we can read it quite well without remarks.. I know we can do the same in ASM but the readability is still not as good as C.


The keypad function returns a key which can be used directly with the display function..


This is the second tutorial in this little series… I’ll post the next as soon as I havea little more time…


Share this post on the following platforms easily:

No Comments

Post A Comment

error: Context Menu disabled!