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.
'{$STAMP BS2}
'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
'STAMP EEPROM DATA
Companyname DATA "Lennard Electronics "
URL DATA "www.lennard.net.nz "
'CONSTANTS
SDA CON 1 'I2C Data line
SCL CON 0 'I2C Clock line
'VARIABLES
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
DIRS=%0011111111111111
Main:
PAUSE 1000 'Give the MO Display time to initalise it's self - 1 seconds
GOSUB StartI2C
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
next
GOSUB StopI2C
end
'^^^^^^^^^^^^^^ I2C SUBROUTINES ^^^^^^^^^^^^^^
'Start Procedure. Set start condition on bus: SDA Hi-Lo while SCL Hi
StartI2C:
HIGH SDA
HIGH SCL
LOW SDA
LOW SCL
RETURN
'Stop Procedure. Set stop condition on bus: SDA Lo-Hi while SCL Hi
StopI2C:
LOW SDA
HIGH SCL
HIGH SDA
RETURN
'Write Address/Data Procedure
Write_data:
shiftout SDA, SCL, msbfirst, [I2C_data]
'Check for Receiver Acknowledge
RX_ACK:
HIGH SDA
DIRS=%0011111011111011
HIGH SCL
ack = IN2
LOW SCL
DIRS=%0011111111111111
'if ack = 1 then indicate_NO_ACK
'debug "Acknowledged", 13
'RETURN
'indicate_NO_ACK:
' debug "NO Acknowledge", 13
RETURN
'^^^^^^^^^^^^^^ I2C SUBROUTINES ^^^^^^^^^^^^^^
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
main()
{
configure();
setbit(P1.6);
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
clrbit(SMB0CN.3);
while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 88; //Clear Display
clrbit(SMB0CN.3);
while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'H'; //now send ASCII data
clrbit(SMB0CN.3);
while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'e';
clrbit(SMB0CN.3);
while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'l';
clrbit(SMB0CN.3);
while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'l';
clrbit(SMB0CN.3);
while (!tstbit(SMB0CN,3)) {}
SMB0DAT = 'o';
clrbit(SMB0CN.3);
while (tstbit(SMB0CN,7)) {} //wait until the bus is free
setbit(SMB0CN.4); //Stop condition
clrbit(SMB0CN.3);
This application note applies to displays:
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.
A: No, the display does not reply to general calls address.
A: The display modules can be clocked up to 100 kbps.
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.
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.
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).
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.