Sometimes you only need a simple and cheap RS232 terminal to get sufficient control over a PC or a RS232 device. There is no need, no space or even no power to place a monitor, a computer case and a keyboard. Maybe there exists also the problem, that the PC or the device is located somewhere else and you want to interact with it over a short distance.
The cheapest way to obtain a complete user interface is the use of standard components, such as LCD modules and PC keyboards. A standard PC keyboard (PS/2 type) costs about US-$ 12, a 2 lines by 40 characters dot matrix LCD module around US-$ 20.
The RS232 terminal for instance is very convenient in conjunction with a PC based Juke-Box playing MP3 files. You only need a command line programmable MP3 player (or a player with a supplied Active-X interface) and a software-based connection between player and RS232 port. This software 'connection' could be realized using Visual Basic and the often supplied Active-X interfaces of the various Windows based MP3 players.
Another possible area for applications is PC observed access control. Therefore, the RS232 terminal is placed at the entrance to the supervised area.
A further enhancement to be able to satisfy todays needs for network-based communication would be a complete TCP/IP based communication layer together with an Ethernet front-end. Then it would be possible to control simple Ethernet appliances, e.g. your coffee maker, electrical rolling shutters, autonomous net-based lawn mower,... ;-) by this remote terminal. Brave new world ...
The routine below contains no support for an LCD display. It only shows the complete fetch and decoding of AT keyboard scan patterns and RS232 transmission of ASCII characters to the RS232 client. If you want a PIC 16F84 based solution with additional LCD, have a look at the keyboard v2xx project.
The problem with the PIC 16F84 is the lack of RS232 hardware. The whole keyboard scan pattern fetch, decode and RS232 data transmission is done by software. Additional RS232 data reception has also to be carried out by software - based on interrupts - but is not implemented within this project. The current implementation features a preemptive interrupt-based keyboard scan pattern acquisition.
How it works
Any key stroke on the local keyboard will send the corresponding scan patterns from the keyboard to the PIC microcontroller. Afterwards, the microcontroller converts the keyboard scan patterns to ASCII characters and transmits them to the RS232 target device.
The keyboard scan code capture is done by an interrupt service routine (ISR). The event, which triggers the interrupt is a falling edge on the keyboard clock line (PORTB,0). Keyboard scan pattern acquisition takes place at the keyboard data line (PORTA,4). After 11 clocks (i.e. 11 external interrupts on RB0/INT), the interrupt service routine has completely captured an 8 bit element of the entire scan pattern and sets a ready flag. The decoding of this 8 bit element is then carried out during normal operation mode, activated by a valid ready flag whilst keeping the keyboard stalled (keyboard clock line low).
The fact, that the scan pattern acquisition is carried out using an interrupt service routine and the decoding thereof is done during normal operation mode allows for performing other tasks concurrently: That's why I call the acquisition methodology preemptive, it does not block the processor in the main loop while acquiring keyboard data - therefore passing processing resources to other services. Explicitely, it works as follows:
Only RS232 transmission is supported by this program, since PORTB,0 interrupt is already used by the keyboard clock line. There exists no possibility to implement also RS232 reception using my modules m_rsxxx.asm, because they require PORTB,0 as well and are laid out as non-preemptive data acquisition routines (see also 'Limitations').
For dedicated code adaptations, please refer to the section 'User-specific Customization' below.
Processor: Microchip PIC 16F84
To visualize the ASCII data sent by this microcontroller application, use a terminal program like the Windows Hyperterminal. Below an example session, which proves the correct functionality of the keyboard interface. This terminal program and the Excel 97 RS232 Debug Interface have been used to debug the interface during implementation time.
In case you want RS232 reception and keyboard decoding simultaneously on a single PIC 16X84, you'll have to configure either the keyboard clock line or the RS232 reception data line (both targeting PORTB,0 interrupt) to another separate interrupt source (e.g. PORTB,4 - PORTB,7 change interrupt) and to alter the RS232 data fetch routine to a preemptive one. But then you'll also run into troubles by using the LCD modules, because they are written to work on entire 8 bit ports (such as PORTB on 16X84, and PORTC & PORTD on 16X74).
So if you really appreciate to run the RS232 terminal entirely on a PIC 16X84 - from a technical perspective it is possible - you'll have to rewrite the LCD modules and the software RS232 reception routine. Be aware that there won't be a lot of code space remaining for other enhancements after putting all terminal related stuff onto the 16X84.
A workaround to get RS232 reception on the PIC 16X84 using this software could be a solution based on polling. But make sure you are polling fast enough, also in worst case.
Important note from Jason Plumb:
First, lemme say that I like your site and thank you for providing excellent reference material for us home-hobbyist microcontroller geeks. I am currently working on a music/noise project that uses a PS/2 keyboard interfaced to a PIC16F84, and I used your page at http://www.electronic-engineering.ch/microchip/projects/keyboard/v1xx/keyboard_v1xx.html heavily as a reference when designing hardware and writing code. Anyway, I just thought that I would mention that I ran into a problem that I have since solved. The problem involved sending bytes *TO* the keyboard from the PIC (in order to light NumLock and ScrollLock). Your "Host To Keyboard Protocol" section indicates that the keyboard will take the data line low for a clock after the byte is sent to create an ACK bit. Apparently, the PS/2 keyboard that I have (generic $10 comp-USA brand) doesn't send an ACK bit, but rather sends a whole byte. If my code attempted to wait for the ACK bit, it hung indefinitely. I changed the wait to look for a byte (by calling my existing function) and everything worked perfectly. I stumbled on this idea by looking at other online references (most notably, some Linux kernel code at http://www.mscs.mu.edu/~georgec/Classes/207.1998/14Minix_book/S/src%20kernel%20keyboard.c.html#307). I have seen this ACK *byte* mentioned elsewhere too. I *think* the keyboard sends back 0xFA as an ACK byte, but I have not personally confirmed this. Perhaps your excellent documentation could just use a quick note of clarification so that other don't run into the same problem. Maybe something as simple as: "NOTE: Some keyboards send an ACK byte (value 0xFA) instead of an ACK bit.".
Note from the author:
The comment above refers to bi-directional communication between PIC microcontroller and AT keyboard, i.e. to the source code of the AT Keyboard Interface V2.xx and higher versions. The bi-directional communication between host and keyboard is designed to support both Ack bits and Ack bytes.
•Every command sent from the host to the keyboard needs to have an Odd Parity bit and an Ack bit at the end.
;*** switch keyboard LEDs on (default status) ***
However, some AT keyboards may behave different and may need code adaptations to get bi-directional communication working properly.
AT Keyboard Theory
A complete functional description and timing diagram of the AT keyboard is available at Craig Peacock's website. Please refer to his website Interfacing the PC's Keyboard for an excellent and comprehensive description of all features and commands of the AT keyboard. At this place, I want to thank Craig Peacock for his outstanding work with his website.
Keyboard Scan Codes
The diagram below shows the scan codes assigned to the individual keys for the english keyboard layout. The keys' corresponding scan codes are the numbers on the keys, for example the scan code of the ESC key is 0x76. All scan codes are shown in hexadecimal representation.
The scan code assignments are quite random (thanks to IBM and other early computer manufacturers) and appear to be really weird sometimes, for instance the break key. In many cases the easiest way to convert the scan code to ASCII characters would be to use a lookup table. Below are the scan codes shown for the extended part of the keyboard and the numeric keypad.
Cite of Craig Peacock: "How about E1,14,77,E1,F0,14,F0,77! Now that can't be a valid scan code? Wrong again. It happens to be sent when you press the pause/break key. Don't ask me why they have to make it so long! Maybe they were having a bad day or something?"
By the way, AT stands for Advanced Technology...
The AT keyboard sends different scan codes on pressing, holding and releasing of each button. An example is given at the table below:
Press & Hold Down Scan Code Release Scan Code
All scan patterns can easily be visualized and verified with the AT Scan Code Debug Routine and the RS232 Debug Interface.
Keyboard to Host Protocol
The data transfer is implemented as bi-directional protocol: The keyboard can send data to the host (microcontroller) and the host can send commands and data to the keyboard. The host has the ultimate priority over the direction. It can at anytime (although not recommended) send a command to the keyboard.
The keyboard is free to send data to the host when both KBD data and KBD clock lines are high (idle). The serial clock is generated by the keyboard, but the host can also use it as a clear-to-send line: If the host takes the KBD clock line low, the keyboard will buffer any data until the KBD clock is released, i.e. goes high. Should the host take also the KBD data line low, then the keyboard will prepare to accept a command from the host.
The transmission of data in the forward direction, i.e. keyboard to host, is done with a frame of 11 bits. The first bit is a start bit (logic 0) followed by 8 data bits (LSB first), one parity bit (odd parity) and a stop bit (logic 1). Each bit has to be read on the falling edge of the clock.
Once the host commands are sent from the host to the keyboard, the keyboard commands must be
Host to Keyboard Protocol
The host to keyboard protocol is initiated by taking the KBD data line low. However to prevent the keyboard from sending data at the same time that you attempt to send the keyboard data, it is common to take the KBD clock line low for more than 60 us. This is more than one bit length. Then the KBD data line is taken low, while the KBD clock line is released. The keyboard will start generating a clock signal on its KBD clock line. This process can take up to 10 ms. After the first falling edge has been detected, you can load the first data bit on the KBD data line. This bit will be read into the keyboard on the next falling edge, after which you can place the next bit of data. This process is repeated for all 8 data bits. After the data bits comes an odd parity bit.
Odd parity = NOT(XOR(bits[0..7]))
Once the parity bit has been sent and the KBD data line is in a idle state (high) for the next clock cycle, the keyboard will acknowledge the reception of the new data. The keyboard does this by taking the KBD data line low for the next clock transition. If the KBD data line is not idle after the 10th bit (start, 8 data bits, and parity bit), the keyboard will continue to send a KBD clock signal until the KBD data line becomes idle (Note: see also Limitations).
These commands are sent by the host to the keyboard. The most common command would be the setting/resetting of the status indicators (i.e. the Num lock, Caps Lock & Scroll Lock LEDs). The more common and useful commands are shown below.
ED Set status LED's - This command can be used to turn on and off the Num Lock, Caps Lock & Scroll Lock LED's. After sending ED, keyboard will reply with ACK (FA) and wait for another byte which determines their status. Bit 0 controls the Scroll Lock, bit 1 the Num Lock and bit 2 the Caps lock. Bits 3 to 7 are ignored.
Please refer to Craig Peacock's website for more information: Interfacing the PC's Keyboard
Available Microchip PIC Assembler Code
Main File Main Keyboard Decode Lookup Table SHIFT Keyboard Decode Lookup Table HEX Files
Schematic, Data Sheets and Pinout
The schematic of the AT keyboard interface using the PIC 16F84: Keyboard_V1xx.pdf.
You don't know how a dot matrix LCD is working? Have a look at my data sheets page.
Download ASCII Character Map: ASCII-Map.pdf
You can get the pinout and a description of the various keyboard connectors
User-specific Customization / FAQ
This section covers important details of the code structure. For a high level view, please refer to the section 'How it works' above. Basically, I have written this keyboard project in such a way that it is completely customizable depending on your programming/PIC assembler skills.
How do I use the AT Keyboard Input?
Question: I'm running your AT Keyboard code. But how do I use the decoded input of the AT keyboard...?
Answer: The decoded content resides usually in the register KBD. You can use the content of this register in the main routine in the infinitive loop. Please see the section 'How it works' above.
How does the Scan Pattern Decoding work exactly?
Question: How does your AT scan pattern decoding work exactly? You are using two strange look-up tables...
Answer: Have a look at some parts of the 'AT Keyboard Lookup Table', e.g. the eng_main.asm (QWERTY):
The simple lookup table decoding is done with retlw x and DT x. These directives just return the corresponding ASCII character. The more sophisticated decoding is done with subroutines, i.e. goto _XYZ. This means for instance that for a ENTER/RETURN key hit on the keyboard, the subroutine _CRLF is executed (carriage return, line feed) and for ALT, CTRL, SHIFT and CAPS_LOCK, the corresponding flags are set in their corresponding subroutines.
goto _ALT ; ALT (set/clear ALT flag)
Because the keyboard sends slightly different scan patterns for both, key hit and key release, there is need for a key release handling. This is done with the so-called release flag. So for every single character typed, the interrupt service routine is called twice (due to two different scan codes for hit and release) and the scan pattern decoding routine is executed twice.
#define RELflag FLAGreg,0x00 ; release flag (0xF0)
There are these four main code blocks in the keyboard assembler source:
1.Interrupt based keyboard scan pattern acquisition
•Small letters (a-z) are translated directly with the main look-up table, capital letters (A-Z) are obtained by simply adding d'224' (8 bit unsigned wrap-around) to the main look-up table results of small letters. Active shift button of the keyboard is only tracked by the shift flag.
My own Key Customization
Question: I have built successfully your AT keyboard project and it is running very well.
Answer: This is not a difficult task, if you just use one specific key, for instance F9.
It is essentially a LUT which performs the decoding of the acquired keyboard scan codes into characters. At the top, the entries for the F1-F12 function keys are located.
KBDtable ; (not used for characters typed with shift button active)
KBDtable ; (not used for characters typed with shift button active)
Then you implement your own key-specific handler/subroutine _MyRoutine in the main file (section sub-routines), which displays your string, e.g. something like:
You can do anything in this routine, just terminate with a RETLW 0 and ensure not to change any reserved registers...
_OUTP ;*** RS232 ***
There, the acquired keyboard character (in KBD) is sent to the RS232 interface.
_OUTP ;*** LCD & RS232 ***
This is roughly what is done in the '_OUTP' section in the assembler source file kbd_2xx.asm.
My own Key Sequence
Question: I have built successfully your AT keyboard project and it is running very well.
Answer: This is a more challenging task. (Alternatively, consider to just use one specific key e.g. F9 as described above.)
Confusion about Sweden and Switzerland...?
Do you know Microsoft? Are you a global player, too? Or do you travel sometimes to Europe?
Don't worry, even Microsoft is confused by the two european countries, Sweden and Switzerland.
Microsoft Wired Keyboard 500
Last updated: 23.04.2006
News on theme: