I2C using a BS2 BASIC Stamp

This is a very simple example of using I2C to talk to a Matrix Orbital Display, using a BS2 BASIC Stamp from Parallax.

In this example, a LCD2041 is communicated to by a BS2 BASIC Stamp and displays some text using I2C. A BS2 BASIC Stamp does not have I2C support built in - so you have to "bit bash" a solution. You can use the I2C subroutines for other I2C based projects as well.


'I2C test program. 27/4/2003 Ben Lennard
'Bit Bashing I2C on a Parallax BS2
'Write to a Matrix Orbital LCD via I2C on a BS2

Companyname DATA "Lennard Electronics "
URL DATA "www.lennard.net.nz "

SDA CON 1 'I2C Data line
SCL CON 0 'I2C Clock line

ack VAR BIT 'Acknowledge from the I2C bus
I2C_data VAR BYTE 'Data to/from the I2C bus
i VAR BYTE 'just a for loop variable
LCDcharacter VAR BYTE


PAUSE 1000 'Give the MO Display time to initalise it's self - 1 seconds
I2C_data = %01010000 'MO Display address for WRITING to
GOSUB Write_data
I2C_data = %11111110 '254 = command
GOSUB Write_data
I2C_data = %01011000 '88 = clear display
GOSUB Write_data

for i = Companyname to Companyname + 39 ' this for loop writes the display message
READ i, LCDcharacter
I2C_data = LCDcharacter
GOSUB Write_data
'^^^^^^^^^^^^^^ I2C SUBROUTINES ^^^^^^^^^^^^^^
'Start Procedure. Set start condition on bus: SDA Hi-Lo while SCL Hi

'Stop Procedure. Set stop condition on bus: SDA Lo-Hi while SCL Hi

'Write Address/Data Procedure
shiftout SDA, SCL, msbfirst, [I2C_data]
'Check for Receiver Acknowledge
ack = IN2
'if ack = 1 then indicate_NO_ACK
'debug "Acknowledged", 13
' debug "NO Acknowledge", 13
'^^^^^^^^^^^^^^ I2C SUBROUTINES ^^^^^^^^^^^^^^

I2C using an 8051

This is a very simple example of using I2C to talk to a Matrix Orbital Display, using a C8051F005. The code is written in Dunefield Micro C.

Communication Type: I2C
Display Used: Any Matrix Orbital display that supports I2C such as the MOI or LK/VK/PK series.

In this example we are talking to a display at address 50 hex over I2C communication protocol.

 // 11/4/04 First test run of I2C bus.
// Display something on the LCD.

// Memory model = 3, use medium.lib, SDA = P0.0, SCL = P0.1

#include "config.h" //This library configures the I/O ports, interrupts, timers, etc.
#include <8051int.h> //moves data to/from stack before/after interrupt service routines
#include "macros.h" //Dunfield macro library - eg: clrbit() uses this


clrbit(SMB0CN.4); //stop flag
setbit(SMB0CN.5); //Start condition
clrbit(SMB0CN.5); //clear start flag to prevent false starts

while (!tstbit(SMB0CN,3)) {} //interrupt occured?
SMB0DAT = 0x50; //address of LCD
clrbit(SMB0CN.3); // clear the interrupt flag

while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 254; //command to LCD

while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 88; //Clear Display

while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'H'; //now send ASCII data

while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'e';

while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'l';

while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'l';

while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'o';

while (tstbit(SMB0CN,7)) {} //wait until the bus is free
setbit(SMB0CN.4); //Stop condition

General I2C development information.

This application note applies to displays:

Alphanumeric Displays:

  • LK/VK162-12 PCB Rev 3.0
  • LCD0821 PCB Rev 2.0
  • LCD/VFD2041 PCB Rev 2.0
  • LK/VK202-25 PCB Rev 3.0
  • LK/VK204-25 PCB Rev 2.0
  • LK402-25, LK404-25
  • MOI Series

Graphic Displays:

  • GLC24064, GLK24064-25 PCB Rev 2.0
  • GLK12232-25-SM PCB Rev 2.0
  • GLK12232-25-FGW PCB Rev 3.0
  • GLK240128-25 PCB Rev 1.0
  • GLK24064-16-1U PCB Rev 1.0
  • GLK19264-7T-1U PCB Rev 1.0

Q: How do I talk to the display?

A: We use a standard Phillips 7bit address as defined by Phillips. How ever, we at Matrix Orbital specify the I2C address in 8bits. The 8th bit, least significant bit (LSB or Low Order Bit) of the 8bit address is read/write bit. If we take a standard Phillips 7bit address of 45hex this would be in binary 1000101. This is 7bits. If one adds the read write bit to this 7bit address and you assume that you are writing one gets 10001010. Matrix Orbital would describe the Philips I2C address of 45hex as 8Ahex. The read address would be 8Bhex.

Q: Does the display reply to a General Call Address? (Address 00h)

A: No, the display does not reply to general calls address.

Q: How fast can I clock the display?

A: The display modules can be clocked up to 100 kbps.

Q: How do I read the keypad data?

A: The keypad is read by I²C master read. A simple master read transaction that is not preceded by a query command will always return the first unread key press. A read is initiated by writing to the module with its base address plus 1, then clocking the module's return byte after the module releases the SDA line. To poll the display for a keypad press, you send your I²C display address plus one.

eg. For a display with I²C address of 0x8A, the write address would be 0x8A, and the read address would be 0x8B.
The module contains a ten key press buffer so that it can be polled for key presses at an infrequent rate (every 250 to 1000 mS is typical). All returned key presses indicate the presence or absence of additional logged key presses by the most significant bit (MSB - bit 7). If the user has pressed two keys since the last poll of the keypad interface, the first read will return the key code with bit 7 set and the second read will return the key code with bit 7 clear. The application must take into account this bit to keep up with user key presses. If there are no keypresses detected, the module will return zero (0x00).
It is necessary to send the following commands to be able to read keypad presses from the display. Both commands need to be sent only once.
254 / 79 - Set Keypad Auto Transmit Off command – this will make sure that keypad presses stay in the buffer until a master read is sent
254 / 160 / 0 - Set Auto232 Tx Data to OFF – this will make the display to put the reply bytes in the I²C output buffer, instead of the RS232 output buffer.

Q: Can I get other data back form the display like Module Type or Module Version Number?

A: Yes, you can get data like module type and module version numbers. Because there is only a 16 byte output buffer on the dispaly, commands that return more than 16 bytes from the display is not guaranteed to work. This makes the command 'Read Customer Data' (which returns 16 bytes) to be the command with the most returned data that is guaranteed to work.

It is recommended that there be at least 3ms delay between each read commands and read transactions. It is also necessary to set the command 'Set Auto 232 Tx Data' to OFF (command 254 / 160 / 0) to get the display to put reply bytes in the I2C output buffer, instead of the RS232 output buffer.

Q: Can I upload fonts or bitmaps over I2C?

A: Theoretically, fonts and bitmaps can be uploaded over I2C but this is something that is not tested. The easiest way to perform font or bitmap upload is via the software mogd# (in RS32 mode).

Q: Do you use ACK? What do I do with it?

A: Yes, we do use ACK/NAK for acknowledgment of write/read transactions. Part of the I2C transaction is the acknowledgment bit. The display will send an ACK (on the 9th clock) when addressed. It will also send an ACK after a write by the master provided that hte write is successful. /if the write is not successful. the display will be sending a NAK. A master write is deemed successful when the module's buffer is still capable of accepting data (ie. when it is not full). When the module 's buffer is full or when it is busy processing data, the display will send a NAK in response to a write by the master. The master will then have to stop the transaction and re-send the NAK'd data. It is suggested that a delay is observed to give the display time to process data. This delay is based on the data previously sent to the display. For a graphic display. a minimum of 50ms delay is sufficient, usually the application will dictate if this delay is enoght, or may have to be extended.