1. You can now buy finished microcontroller project from us, Check out the Store for the complete list of projects.
  2. Need a custom project, Send us some details about your project. So that we can quote the price for it.

Interfacing Example - Keyboard to AT89S52 Microcontroller 1.0

Circuit diagram and program for Interfacing Keyboard to AT89S52 Microcontroller

  1. Binu
    Interfacing Example - Keyboard to AT89S52 Microcontroller
    Normally in this series of web pages, we connect something to the PC, to demonstrate the protocols at work. However this poses a problem with the keyboard. What could be possibly want to send to the computer via the keyboard interface?

    Straight away any devious minds would be going, why not a little box, which generates passwords!. It could keep sending characters to the computer until it finds the right sequence. Well I'm not going to encourage what could possibly be illegal practices.

    In fact a reasonably useful example will be given using a AT89S52 single chip microcontroller. We will get it to read the data from the keyboard, convert the scan codes into ASCII and send it out in RS-232 format at 9600 BPS. However we won't stop here, you will want to see the bi-directional use of the KBD Clock & Data lines, thus we will use the keyboards status LEDS, Num Lock, Caps Lock and Scroll Lock.

    The keyboard doesn't need to be expensive either. Most people have many old keyboards floating around the place. If it's an AT Keyboard, then use it (XT keyboards will not work with this program.) If we ever see the introduction of USB keyboards, then there could be many redundant AT keyboards just waiting for you to hook them up.

    Circuit Diagram
    [​IMG]
    Program
    Code (Text):
    1. $mod52
    2. ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    3. ;                PORT DECLERATION
    4. ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    5. KEYB_CLOCK        EQU        P2.7
    6. KEYB_DATA        EQU        P2.6
    7.  
    8. KB_LSHIFT        EQU      12H
    9.     KB_RSHIFT        EQU      59H
    10.     KB_CTRL                EQU      14H
    11.     KB_ALT                EQU      11H
    12.     KB_CAPS                EQU      58H
    13.     KB_SCROLL        EQU      7EH
    14.     KB_NUML                EQU      77H
    15.     KB_TAB                EQU      0DH
    16.     KB_REL                EQU      0F0H
    17.     KB_EXT                EQU      0E0H
    18.     KB_PAUSE        EQU      0E1H
    19.  
    20.     CAPS                EQU          01H
    21.     NUML                EQU          02H
    22.     SCROLL        EQU          04H
    23.     SHIFT        EQU          08H
    24.     ACK                EQU          10H
    25.     CTRL                EQU          20H
    26.     ALT                EQU          40H
    27.  
    28.     RELEASE        EQU                80H
    29.     PAUSED        EQU        40H
    30.     EXTENDED EQU      80H
    31.  
    32. DSEG            ; This is internal data memory
    33. ORG    20H    ; Bit adressable memory
    34. FLAGS1:        DS                1
    35. RECEIVED        BIT FLAGS1.0
    36. AM                        BIT        FLAGS1.1
    37. MAS                BIT        FLAGS1.2
    38. KEYBRD        BIT        FLAGS1.3
    39. AMS                BIT        FLAGS1.4
    40.  
    41.  
    42. CAPPS_ON:        DS                1
    43. CAAPS                BIT        CAPPS_ON
    44.  
    45. KB_OK:                DS                1
    46. KB_DATA:                DS                1
    47. KB_STATS:                DS                1
    48. KB_SCAN:                DS                1
    49. KB_TEMP:                DS                1  ; For the da*n pause key
    50. KB_COUNT:                DS                1
    51. NAMES:                DS                16
    52. COUNTT:                DS                1
    53. STACK:                DS          1
    54. CSEG            ; Code begins here
    55.        
    56. ;  ---------==========----------==========---------=========---------
    57. ;  Main routine. Program execution starts here.
    58. ;  ---------==========----------==========---------=========---------
    59.               ORG    00H    ; Reset
    60.               AJMP MAIN
    61.          
    62.               ORG 23H
    63.               JMP SERIAL
    64. ;  ---------==========----------==========---------=========---------                              
    65. MAIN:              
    66.             MOV    SP,#STACK      
    67.               MOV TMOD,#20H                ;Enable Timer 1 from Baud rate Generation
    68.               MOV TH1,#0FDH
    69.               MOV SCON,#50H                ;Enable serial port for 9600Baud rate
    70.               SETB ES
    71.               SETB EA                        ;Enable serial port interrupt
    72.               SETB TR1
    73.               CALL InitKeyb                ;Inizialize Keyboard
    74.             MOV a, KB_OK
    75.             JZ KBNotOK
    76.              
    77. LOOPS:        CALL Check_Keyb                ;Check for any keypress
    78.               JNC LOOPS
    79.               MOV A,KB_DATA                ;get data
    80.               MOV SBUF,A
    81.               AJMP LOOPS
    82.  
    83.  
    84. ;---------==========----------==========---------=========---------
    85. ;                SERIAL INTERRUPT ROUTINE
    86. ;---------==========----------==========---------=========---------
    87. SERIAL:              
    88.               JB TI,TRANS
    89.               CLR RI
    90.               RETI
    91. TRANS:        CLR TI
    92.               RETI
    93. ;**********************************************************
    94.  
    95.  
    96. KBNotOK:
    97.               AJMP $                ;Keyboard Error
    98. ;---------------------
    99. ; Keyboard Routines:
    100. ;---------------------
    101. ;*************************************
    102. ; WaitKB: Wait for keypress
    103. ;*************************************
    104. WaitKB:
    105.         call  Check_Keyb
    106.         jnc    WaitKB
    107.         ret
    108. ;*************************************
    109. ; InitKeyb: c=1 if ACK OK
    110. ;*************************************
    111. CheckACK:
    112.         mov    a, KB_STATS
    113.         mov    c, acc.4
    114.         clr    acc.4
    115.         mov    KB_STATS, a
    116.         ret
    117.  
    118. ;*************************************
    119. ; InitKeyb:
    120. ;*************************************
    121. InitKeyb:
    122.         mov    KB_TEMP, #0
    123.         mov    KB_OK, #0
    124.         mov    r1, #0FFH
    125.         call  Write_Keyb
    126.         call  Check_Keyb
    127.         call  CheckACK
    128.         jnc    InitKeyb
    129.  
    130.         mov    r1, #0F4H      ; Enable
    131.       call  Write_Keyb
    132.         call  Check_Keyb
    133.         call  CheckACK
    134.         jnc    KeybErr
    135.  
    136.         mov    r1, #0F3H      ; Set Typematic
    137.         call  Write_Keyb
    138.         call  Check_Keyb
    139.         call  CheckACK
    140.         jnc    KeybErr
    141.         mov    r1, #00H      ; Typematic = 250 ms / 30 cps
    142.         call  Write_Keyb
    143.         call  Check_Keyb
    144.         call  CheckACK
    145.         jnc    KeybErr
    146.  
    147.         mov    KB_OK, #1
    148.         mov    KB_STATS, #2    ; Num Lock ON
    149.  
    150. ;*************************************
    151. ; Keyb_Leds: Set KB_STATS as leds
    152. ;*************************************
    153. Keyb_Leds:
    154.         mov    r1, #0EDH      ; Set Leds
    155.         call  Write_Keyb
    156.         call  Check_Keyb
    157.         call  CheckACK
    158.         jnc    KeybErr
    159.         mov    r1, KB_STATS
    160.         call  Write_Keyb
    161.         call  Check_Keyb
    162.         call  CheckACK
    163. KeybErr:
    164.         ret
    165. ;*************************************
    166. ; Zero2One: Wait for 0 to 1 on kb
    167. ; clock line, read the kb data line
    168. ; and shift right the bit to acc.7
    169. ;*************************************
    170. Zero2One:
    171.         jnb    KEYB_CLOCK, $
    172.         jb      KEYB_CLOCK, $
    173.         mov    c, KEYB_DATA
    174.         rrc    a
    175.         ret
    176.  
    177. ;*************************************
    178. ; Check_Keyb: Check to see if any key
    179. ; are pressed or release, returns
    180. ; ASCII codes on KB_DATA, or 1 for
    181. ; special keys, 2 for same special
    182. ; with shift. Return also the scan
    183. ; code on KB_SCAN.
    184. ; Special Keys are basicaly all non
    185. ; printable keys. See the table below
    186. ; all 1 and 2 returned are special keys
    187. ;*************************************
    188. Check_Keyb:
    189.         setb    KEYB_DATA
    190.         setb    KEYB_CLOCK              ; CLOCK & DATA high = Idle Pos
    191.         mov    r0, #50              
    192. CheckAgain:
    193.         jnb    KEYB_CLOCK, KeyHit
    194.         djnz    r0, CheckAgain          ; check r0 times
    195.         sjmp    KeyEnd
    196. KeyHit:
    197.         jnb    KEYB_DATA, KeyHit2      ; Start bit must be 0
    198. KeyEnd:
    199.         clr    KEYB_CLOCK              ; disable keyb
    200.         clr    c                      ; c=0 = no keypress
    201.         ret
    202. KeyHit2:
    203.         mov    r0, #8          ; 8 bits
    204.         clr    a
    205. KeyHit3:
    206.         call  Zero2One
    207.         djnz    r0, KeyHit3
    208.         mov    r1, a
    209.  
    210.         clr    a
    211.         call  Zero2One        ; Parity bit
    212.         call  Zero2One        ; Stop bit
    213.         ; acc.7 = stop, acc.6 = parity
    214.         clr    KEYB_CLOCK
    215.  
    216.         mov    a, KB_TEMP
    217.         jz      NoIgnore    
    218.         dec    KB_TEMP        ; Igonre pause scans
    219.         sjmp    ChkKbEndNC
    220.  
    221. NoIgnore:
    222.         mov    KB_SCAN, r1
    223.  
    224.         cjne    r1, #0FAH, NoKbACK
    225.         orl    KB_STATS, #ACK
    226.         sjmp    ChkKbEndNC
    227.  
    228. NoKbACK:
    229.         cjne    r1, #KB_PAUSE, NoKbPause
    230.         mov    KB_TEMP, #7            ; Ignore next 7 scans
    231.         mov    a, KB_OK
    232.         cpl    acc.6
    233.         mov    KB_OK, a
    234.         sjmp    ChkKbEndNC
    235.  
    236. NoKbPause:
    237.         cjne    r1, #KB_EXT, NoKbExt
    238.         orl    KB_OK, #EXTENDED
    239.         sjmp    ChkKbEndNC
    240.  
    241. NoKbExt:
    242.         cjne    r1, #KB_REL, NoRelease
    243.         orl    KB_STATS, #RELEASE
    244.         sjmp    ChkKbEndNC
    245.  
    246. NoRelease:
    247. ; Test Num lock, if pressed toggle led
    248.         cjne    r1, #KB_NUML, NoNumLock
    249.         mov    a, KB_STATS
    250.         jnb    acc.7, ChkKbEndNC
    251.         cpl    acc.1
    252.         clr    acc.7
    253.         mov    KB_STATS, a
    254.         call  Keyb_Leds
    255.         sjmp    ChkKbEndNC
    256.  
    257. NoNumLock:
    258. ; Test Caps lock, if pressed toggle led
    259.         cjne    r1, #KB_CAPS, NoCapsLock
    260.         mov    a, KB_STATS
    261.         jnb    acc.7, ChkKbEndNC
    262.         cpl    acc.2
    263.         clr    acc.7
    264.         mov    KB_STATS, a
    265.         call  Keyb_Leds
    266.         sjmp    ChkKbEndNC
    267.  
    268. NoCapsLock:
    269. ; Test Scroll lock, if pressed toggle led
    270.         cjne    r1, #KB_SCROLL, NoScrollLock
    271.         mov    a, KB_STATS
    272.         jnb    acc.7, ChkKbEndNC
    273.         cpl    acc.0
    274.         clr    acc.7
    275.         mov    KB_STATS, a
    276.         call  Keyb_Leds
    277. ChkKbEndNC:
    278.         clr    c
    279.         ret
    280.  
    281. NoScrollLock:
    282. ; Test L & R shifts, set bit if pressed, clear on release
    283.         cjne    r1, #KB_LSHIFT, NoShift1
    284. ShiftOK:
    285.         mov    a, KB_STATS
    286.         jbc    acc.7, ShiftRel
    287.         setb    acc.3          ; not releasing, so Set SHIFT bit
    288.         sjmp    ShiftEnd
    289. ShiftRel:
    290.         clr    acc.3          ; releasing, so Clear SHIFT bit
    291. ShiftEnd:
    292.         mov    KB_STATS, a
    293.         sjmp    ChkKbEndNC  
    294. NoShift1:
    295.         cjne    r1, #KB_RSHIFT, NoShift
    296.         sjmp    ShiftOK
    297.  
    298. NoShift:
    299.         cjne    r1, #KB_CTRL, NoCtrl
    300.         mov    a, KB_STATS
    301.         jbc    acc.7, CtrlRel
    302.         setb    acc.5          ; not releasing, so Set CTRL bit
    303.         sjmp    CtrlEnd
    304. CtrlRel:
    305.         clr    acc.5          ; releasing, so Clear SHIFT bit
    306. CtrlEnd:
    307.         mov    KB_STATS, a
    308.         sjmp    ChkKbEndNC  
    309.  
    310. NoCtrl:
    311.         cjne    r1, #KB_ALT, NoAlt
    312.         mov    a, KB_STATS
    313.         jbc    acc.7, AltRel
    314.         setb    acc.6          ; not releasing, so Set ALT bit
    315.         sjmp    AltEnd
    316. AltRel:
    317.         clr    acc.6          ; releasing, so Clear ALT bit
    318. AltEnd:
    319.         mov    KB_STATS, a
    320.         sjmp    ChkKbEndNC  
    321.  
    322. NoAlt:
    323.         mov    a, KB_STATS            ; Releasing key test
    324.         jnb    acc.7, NoRel2        
    325.         clr    acc.7                  ; if releasing > clear
    326.         mov    KB_STATS, a            ; rel bit on KB_STATS
    327.         clr    c                      ; and do nothing
    328.         ret
    329. NoRel2:
    330.         mov    a, KB_OK                ; Extended key test
    331.         jnb    acc.7, KbChars        
    332.         clr    acc.7                  ; if Extended > clear
    333.         mov    KB_OK, a                ; EXT bit on KB_OK
    334.         clr    c                      ; and do nothing
    335.         ret
    336. KbChars:mov    dptr, #KbScanCodes
    337.         mov    a, KB_STATS
    338.         jnb    acc.2, TestShift
    339.         jb      acc.3, KbChkOK
    340.         mov    a, r1
    341.         movc    a, @a+dptr
    342.         mov    r0, a
    343.         subb    a, #97
    344.         jc      KbChkOK
    345.         mov    a, r0
    346.         subb    a, #123
    347.         jnc    KbChkOK
    348.         mov    dptr, #KbScanCodes2    ; if (a to z) & Caps > table 2
    349.         sjmp    KbChkOK
    350. TestShift:
    351.         jnb    acc.3, KbChkOK
    352.         mov    dptr, #KbScanCodes2    ; with shift table 2
    353. KbChkOK:
    354.         mov    a, r1
    355.         movc    a, @a+dptr
    356.         mov    KB_DATA, a
    357.         setb    c
    358.      
    359.         ret
    360.  
    361. ;*************************************
    362. ; Zero2One2: Wait for high to low in
    363. ; kb clock line
    364. ;*************************************
    365. Zero2One2:
    366.         jnb    KEYB_CLOCK, $
    367.         jb      KEYB_CLOCK, $
    368.         ret
    369. ;*************************************
    370. ; Write_Keyb: Send r1 to the kb
    371. ;*************************************
    372. Write_Keyb:
    373.         mov    r0, #8          ; 8 bits to receive
    374.         clr    KEYB_CLOCK      ; break the Keyboard
    375.         mov        r7, #00H      ; some delay (safety reasons)
    376. _WKwait:djnz        r7, _WKwait
    377.         clr    KEYB_DATA      ; request to send
    378.         setb    KEYB_CLOCK      ; enable the Keyboard
    379.         acall  Zero2One2      ; Start Bit
    380.         mov    a, r1          ; Data Bits
    381. TxData:
    382.         rrc    a
    383.         mov    KEYB_DATA, c
    384.         call  Zero2One2
    385.         djnz    r0, TxData
    386.  
    387.         mov    a, r1          ; calculate parity bit
    388.         mov    c, psw.0        ; this is Even parity
    389.         cpl    c              ; and Keyboard needs Odd parity
    390.         mov    KEYB_DATA, c    ; send parity bit
    391.         call  Zero2One2
    392.  
    393.         setb    KEYB_DATA      ; send stop bit
    394.         call  Zero2One2
    395.  
    396.         call  Zero2One2
    397.         mov    c, KEYB_DATA    ; get ACK bit
    398.         clr    KEYB_CLOCK      ; stop the keyboard  
    399.         ret
    400. ;*************************************
    401. ; last 262 addr of code mem with scan codes tables
    402. ;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$              
    403. ; last 262 addr of code mem with scan codes tables
    404. KbScanCodes:
    405. ; Keyboard Scancodes
    406. ;      ?,  F9, ?,  F5,  F4,  F1,  F2, F12, ?, F10,  F8,  F6,  F4, TAB,  ~
    407. db    0,  1 , 0,  1 ,  1 ,  1 ,  1 ,  1 , 0,  1 ,  1 ,  1 ,  1 ,  1 , '~'
    408. ;      ?, ?,Lalt,Lshf, ?,Lctr,  Q ,  ! , ?, ?, ?,  Z ,  S ,  A ,  W ,  @
    409. db    0, 0,  0 ,  0 , 0,  0 , 'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2'
    410. ;      ?, ?,  C ,  X ,  D ,  E ,  $ ,  # , ?, ?, " ",  V ,  F ,  T ,  R
    411. db    0, 0, 'c', 'x', 'd', 'e', '4', '3', 0, 0, ' ', 'v', 'f', 't', 'r'
    412. ;      % , ?, ?,  N ,  B ,  H ,  G ,  Y ,  ^ , ?, ?, ?,  M ,  J ,  U ,  &
    413. db    '5', 0, 0, 'n', 'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j', 'u', '7'
    414. ;      * , ?, ?,  < ,  K ,  I ,  O ,  ) ,  ( , ?, ?,  > ,  ? ,  L ,  : ,  P
    415. db    '8', 0, 0, ',', 'k', 'i', 'o', '0', '9', 0, 0, '.', '/', 'l', ';', 'p'
    416. ;      _ , ?, ?, ?,  " , ?,  { ,  + , ?, ?,Caps,Rshf,Entr,  } , ?,  |
    417. db    '-', 0, 0, 0, 39 ,  0,  '[',  '=', 0, 0,  0 ,  0 ,  1 , ']', 0,  92
    418. ;      ?, ?, ?, ?, ?, ?, ?, ?,BkSp, ?, ?,  1 , ?,  4 ,  7 , ?, ?, ?,  0
    419. db    0, 0, 0, 0, 0, 0, 0, 0,  1 , 0, 0, '1', 0, '4', '7', 0, 0, 0, '0'
    420. ;      . ,  2 ,  5 ,  6 ,  8 , ESC,Numl, F11,  + ,  3 ,  - ,  * ,  9 ,Scrl
    421. db    '.', '2', '5', '6', '8',  1 ,  0 ,  1 , '+', '3', '-', '*', '9',  0
    422. ;      ?, ?, ?, ?,  F7
    423. db    0, 0, 0, 0,  1
    424.  
    425. KbScanCodes2:
    426. ; Keyboard Scancodes with shift
    427. ;      ?,  F9, ?,  F5,  F4,  F1,  F2, F12, ?, F10,  F8,  F6,  F4, TAB,  ~
    428. db    0,  2 , 0,  2 ,  2 ,  2 ,  2 ,  2 , 0,  2 ,  2 ,  2 ,  2 ,  2 , '`'
    429. ;      ?, ?,Lalt,Lshf, ?,Lctr,  Q ,  ! , ?, ?, ?,  Z ,  S ,  A ,  W ,  @
    430. db    0, 0,  0 ,  0 , 0,  0 , 'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@'
    431. ;      ?, ?,  C ,  X ,  D ,  E ,  $ ,  # , ?, ?, " ",  V ,  F ,  T ,  R
    432. db    0, 0, 'C', 'X', 'D', 'E', '$', '#', 0, 0, ' ', 'V', 'F', 'T', 'R'
    433. ;      % , ?, ?,  N ,  B ,  H ,  G ,  Y ,  ^ , ?, ?, ?,  M ,  J ,  U ,  &
    434. db    '%', 0, 0, 'N', 'B', 'H', 'G', 'Y', '^', 0, 0, 0, 'M', 'J', 'U', '&'
    435. ;      * , ?, ?,  < ,  K ,  I ,  O ,  ) ,  ( , ?, ?,  > ,  ? ,  L ,  : ,  P
    436. db    '*', 0, 0, '<', 'K', 'I', 'O', ')', '(', 0, 0, '>', '?', 'L', ':', 'P'
    437. ;      _ , ?, ?, ?,  " , ?,  { ,  + , ?, ?,Caps,Rshf,Entr,  } , ?,  |
    438. db    '_', 0, 0, 0, '"', 0, '{', '+', 0, 0,  0 ,  0 ,  2 , '}', 0, '|'
    439. ;      ?, ?, ?, ?, ?, ?, ?, ?,BkSp, ?, ?,  1 , ?,  4 ,  7 , ?, ?, ?,  0
    440. db    0, 0, 0, 0, 0, 0, 0, 0,  2 , 0, 0, '1', 0, '4', '7', 0, 0, 0, '0'
    441. ;      . ,  2 ,  5 ,  6 ,  8 , ESC,Numl, F11,  + ,  3 ,  - ,  * ,  9 ,Scrl
    442. db    '.', '2', '5', '6', '8',  2 ,  0 ,  2 , '+', '3', '-', '*', '9',  0
    443. ;      ?, ?, ?, ?,  F7
    444. db    0, 0, 0, 0,  2                                                                                
    445. END