Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
Resource icon

Basic 8051 tutorial 2 2014-04-15

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...

7seg.png

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..

Keypad.png


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:
    org    0        ; Reset vector
    sjmp    Start

    org    30H        ; Code starts here
Start:
    clr    A        ; A = 0
While:
    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
OLoop:
    clr    C
    mov    P0,R1        ; ready keypad mask
    jb    P0.0,row2    ; Key pressed? row 1
    sjmp    keydone    ; found a key
row2:
    jb    P0.1,row3    ; Key pressed? row 2
    add    A,#1
    sjmp    keydone    ; found a key
row3:
    jb    P0.2,row4    ; Key pressed? row 3
    add    A,#2
    sjmp    keydone    ; found a key
row4:
    jb    P0.3,nextcol    ; Key pressed? row 4
    add    A,#3
    sjmp    keydone    ; found a key
nextcol:
    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
    ret


Display:
    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
    ret

delay:    mov    R2,#225    ; 2 clock cycles (call)        = 2
    mov    R1,#0        ; 2 clock cycles (loading)    = 2
d1:    
   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
    end

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
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(key)
            {        // 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...
  • 7seg.png
    7seg.png
    10.8 KB · Views: 2,887
  • Keypad.png
    Keypad.png
    24.1 KB · Views: 2,446

Latest reviews

Well explained. Now I can compare which is better-- I prefer C from the start. I just turned down my plan to study ASM. Nice one!

Latest threads

New Articles From Microcontroller Tips

Back
Top