Using an I2C LCD with the Infineon C500 microcontroller family. Reference code and applications including visual effects

Microcontrollers
ApNote
AP2427
æ additional file
AP242701.ZIP available
Using an I2C LCD with the Infineon C500 microcontroller
family. Reference code and applications including visual
effects.
This application note describes the usage of I2C interface Liquid Crystal Displays with Infineon
microcontrollers and presents a standard library of functions used to manipulate the Display
contents efficiently. The last part includes some examples of complex visual effects. The code
provided is in C and does not use any hardware-specific instructions, so it can be easily ported
to Infineon 16bit microcontrollers. By replacing the I 2C bus interface code with another interface
code, one can use the standard library for other configurations (i.e. parallel interface) too.
Authors: Dimitrios Skraparlis / Andreas Jansen
1999-06, Rel. 01
Edition 1999-06
Published by
Infineon Technologies AG
81726 München, Germany
© Infineon Technologies AG 2006.
All Rights Reserved.
LEGAL DISCLAIMER
THE INFORMATION GIVEN IN THIS APPLICATION NOTE IS GIVEN AS A HINT FOR THE
IMPLEMENTATION OF THE INFINEON TECHNOLOGIES COMPONENT ONLY AND SHALL NOT BE
REGARDED AS ANY DESCRIPTION OR WARRANTY OF A CERTAIN FUNCTIONALITY, CONDITION OR
QUALITY OF THE INFINEON TECHNOLOGIES COMPONENT. THE RECIPIENT OF THIS APPLICATION
NOTE MUST VERIFY ANY FUNCTION DESCRIBED HEREIN IN THE REAL APPLICATION. INFINEON
TECHNOLOGIES HEREBY DISCLAIMS ANY AND ALL WARRANTIES AND LIABILITIES OF ANY KIND
(INCLUDING WITHOUT LIMITATION WARRANTIES OF NON-INFRINGEMENT OF INTELLECTUAL
PROPERTY RIGHTS OF ANY THIRD PARTY) WITH RESPECT TO ANY AND ALL INFORMATION GIVEN
IN THIS APPLICATION NOTE.
Information
For further information on technology, delivery terms and conditions and prices please contact your nearest
Infineon Technologies Office (www.infineon.com).
Warnings
Due to technical requirements components may contain dangerous substances. For information on the types
in question please contact your nearest Infineon Technologies Office.
Infineon Technologies Components may only be used in life-support devices or systems with the express
written approval of Infineon Technologies, if a failure of such components can reasonably be expected to
cause the failure of that life-support device or system, or to affect the safety or effectiveness of that device or
system. Life support devices or systems are intended to be implanted in the human body, or to support
and/or maintain and sustain and/or protect human life. If they fail, it is reasonable to assume that the health
of the user or other persons may be endangered.
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
&RQWHQWV
,QWURGXFWLRQ 1.1
1.2
1.3
1.4
1.5
1.6
1.7
2
Brief introduction to the I C bus ...................................................................................................................3
The communication between the master and the slave...............................................................................4
2
How is I C implemented? .............................................................................................................................6
The Liquid Crystal Display............................................................................................................................8
The LCD controller/driver .............................................................................................................................8
Using other instruction sets ........................................................................................................................10
Starting up – testing the LCD .....................................................................................................................11
7KHVRIWZDUHOLEUDU\ 2.1 Description of the basic procedures...........................................................................................................13
2.2 Description of the standard procedures .....................................................................................................19
2.3 Discussion of the code-size and the optimization ......................................................................................21
7KHLPSOHPHQWDWLRQRIYLVXDOHIIHFWV 3.1
3.2
3.3
3.4
texteffect.....................................................................................................................................................25
texttrans......................................................................................................................................................25
textroll .........................................................................................................................................................25
printinfineonlogo .........................................................................................................................................26
(SLORJXH $SSHQGL[ A
i2c_8b.def – include file 1 .......................................................................................................................27
B
lcd.h – include file 2 ................................................................................................................................27
C
i2c_lcd.h – include file 3 .........................................................................................................................31
D
i2c_lcd.c – demonstration: main() .........................................................................................................47
E
i2c_sw8b.c – i c bus interface software emulation.................................................................................54
2
$3$S1RWH±5HYLVLRQ+LVWRU\
Actual Release : Rel.01
Previous Release: none
Page of
Page of
Subjects changes since last release)
Actual Rel.
prev. Rel.
No changes
2 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
,QWURGXFWLRQ
This application note focuses on Liquid Crystal Screens driven by a controller/driver chip, as shown on
figure 1. This controller is programmed by the C500 Infineon microcontroller. The LCD used in this
2
application note is shown in figure 2 and has a two pin interface to the I C bus.
%ULHILQWURGXFWLRQWRWKH, &EXV
2
The I C bus is a bidirectional two line bus, enabling communication between any kind of integrated circuit
that supports this protocol, either by hardware or software. Examples of such ICs are LCD controllers,
EEPROMs, RAMs, data converters or general purpose microcontrollers. The main advantage of this protocol
is its two line interface, as shown in figure 3.
LCD
I/O pins (2 for
I2C interface)
connected to
the Infineon
microcontroller
(e.g. C508)
LCD
controller/driver
example:
PCF2116
power, contrast
and backlight
connections
Liquid Crystal
)LJXUH
([DPSOHRIDQ/&'ZLWKDQHPEHGGHGFRQWUROOHUGULYHU
)LJXUH
([DPSOHRID&KLSRQJODVVDSSOLFDWLRQOLQH[YLVLEOHFROXPQV, &LQWHUIDFH
3 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
Vcc Vcc
Pull-up
resistors
6'$
6&/
uC
LCD
EEPROM
master
slave
slave
)LJXUH
([DPSOHRIDQ, &EXVFRQILJXUDWLRQ
The two-line bus consists of lines SDA (serial data line) and SCL (serial clock line). These lines should be
connected to a positive supply via pull-up resistors. However this is not always necessary because some
microcontroller ports (i.e. the Infineon microcontroller C504 port 1) have an internal pullup. In any case,
2
careful consideration must be given to the I C bus specification.
2
It should be noted that the multi-master capability of the I C bus is not used in this application; there is only
one master (the Infineon microcontroller) and a slave (the Display).
7KHFRPPXQLFDWLRQEHWZHHQWKHPDVWHUDQGWKHVODYH
By using the word „master“ one refers to the device which initiates and terminates a transfer and also
provides the clock signals on line SCL. Master devices operate as transmitters or receivers.
At the start of each transfer, a slave is addressed by its own unique address. A transfer consists of a VWDUW
condition, the GDWDELWV, an DFNQRZOHGJH bit and possibly a VWRS condition. This concept is shown in figures 4
and 5.
A VWDUW condition is defined by a falling edge at SDA while the SCL is high. A VWRS condition is defined by a
rising edge at SDA while the SCL line is high. When transmitting data, no changes at the SDA line while the
clock is high are permitted, otherwise this will result in a stop or a start condition! In order to avoid this, the
master should change the data at SDA only when the SCL line is low.
After the transmission of the 8 data bits, the master sets the SDA line to high and the slave acknowledges
the transfer by pulling the SDA line to ground. This indicates a successful transfer.
Master-read mode is not exactly the same. The master still provides the clock but the slave is now the one
who submits the data (requested by the master) at the SDA line. At the end of the transmission, the master
does not acknowledge (SDA is set and remains high).
4 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
8 bits
change of
data allowed
change of
data allowed
acknowledgment
no acknowledge
6'$
acknowledge
6&/
start
condition
transmitting a "1"
transmitting a "0"
$FNQRZOHGJHPHQW:
SDA line is pulled low by the slave during the
SCL pulse while in slave write mode.
In slave read mode, SDA line remains HIGH
during the SCL pulse (no acknowledge by the
master).
stop
condition
)LJXUH
$QH[DPSOHRIDWUDQVIHU
2
The I C protocol defines two modes: standard mode (maximum transfer rate of 100 kbit/s) and fast mode
(maximum transfer rate of 400 kbit/s). This application note uses the standard mode for communication. This
2
could probably be easily changed but any changes should be made in accordance to the original I C-bus
specification.
2
2
For further information the interested reader is referred to the original I C-bus specification («the I C-bus and
how to use it (including specification)», Philips Semiconductors).
5 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
I2C start
transmit slave
address
slave
acknowledges
send data to
slave
N times
slave
acknowledges
transfer
continue
or
stop transmitting
I2C Stop
)LJXUH
$QH[DPSOHRIDVXFFHVVIXOPDVWHUZULWH
+RZLV, &LPSOHPHQWHG"
2
The code found in the appendix uses true software routines: the I C is emulated by the software routines and
therefore there is no need for special hardware. Nevertheless, some Infineon microcontrollers provide a
2
hardware I C interface. Please refer to the following table, table 1. It should be noted that software emulation
2
is possible with any Infineon microcontrollers – one may only replace the I C driver software with the
2
appropriate I C driver code for the microcontroller used. The application notes proposed can be found on the
internet at www.infineon.com.
6 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
software
emulation
hardware
implementation
8 bit
16 bit
*
**
C161RI
-
C161PI
C161SI/CI
C161CS
________________________________________________________
2
* software emulated I C interface with the C500 family. Complete description and source code is found in:
,QWHUIDFLQJ6/[&[[,&%XV
6HULDO((3520VWR&RQWUROOHU)DPLO\HVSHFLDOO\WRWKH6LHPHQV,QILQHRQ
V&&RQWUROOHU)DPLO\
$3
2
This is a source for the I C bus procedures (e.g. I2cMasterWrite(), I2cMasterRead();) used in this application
note.
________________________________________________________
2
** software emulated I C interface with the C166 family. Complete description and source code is found in:
6RIWZDUHHPXODWLRQRIWKH,&EXVXVLQJWKH*HQHUDO3XUSRVH7LPHUXQLWRIWKH&IDPLO\
7KLVLVDVRIWZDUHHPXODWLRQRIWKH,&EXVE\XVLQJWZRJHQHUDOSXUSRVHWLPHUVRIDPLFURFRQWUROOHUIURPWKH&
IDPLO\7KH,&EXVLVXVHGLQPDQ\DSSOLFDWLRQVPDLQO\WRFRPPXQLFDWHEHWZHHQGHYLFHVFRQQHFWHGWRWKHEXV
$3
6RIWZDUHHPXODWLRQRI,&EXVXVLQJ&38WLPHRI&IDPLO\
7KLVLVDVRIWZDUHHPXODWLRQRI,&EXVXVLQJ&38WLPHRIWKH&IDPLO\WRJHQHUDWHWKHFORFNDQGGDWD
$3
6RIWZDUHHPXODWLRQRIWKH,&EXVXVLQJWKH+LJK6SHHG6\QFKURQRXV6HULDO,QWHUIDFHRI&IDPLO\
7KLVLVDVRIWZDUHHPXODWLRQRI,&EXVXVLQJ+LJK6SHHG6\QFKURQRXV6HULDO,QWHUIDFHRIWKH&IDPLO\WRJHQHUDWH
WKHFORFNDQGGDWD
AP162601
________________________________________________________
2
Some versions of the C161 have hardware I C interface capability. A related application note is:
+DUGZDUH,&EXVLQVODYHPRGHE\XVLQJSROOLQJDQGLQWHUUXSWPHWKRGVIRU&5,PLFURFRQWUROOHU
7KLVLVDVRIWZDUHPRGXOHIRUKDUGZDUH,&EXVLQVODYHPRGHE\XVLQJVRIWZDUHSROOLQJDQGKDUGZDUHLQWHUUXSWPHWKRGV
IRU&5,PLFURFRQWUROOHU7KH,&EXVLVXVHGLQPDQ\DSSOLFDWLRQVPDLQO\WRFRPPXQLFDWHEHWZHHQGHYLFHV
FRQQHFWHGWRWKHEXV
$3
7 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
7KH/LTXLG&U\VWDO'LVSOD\
2
The Liquid Crystal Display used in this application note is a „Chip on glass“ LCD using an I C interface
(figure 2)*. The Display controller driving the display is a PCF2116 from Philips Semiconductors. The user
2
has access to six pins; two pins are used for I C communication with the master - Infineon microcontroller
while the other four pins are used for the power supply interfacing and for connecting 2 fixed resistors (or a
potentiometer) that adjust the contrast of the Display, according to figure 5.
6 5 4 3 2 1
3LQRXW
1 VSS
2 VDD
3 VLCD
4 V0
5 SDA
6 SCL
The 100K potentiometer could be replaced by two resistors after setting an appropriate contrast level.
)LJXUH
7KH/&'SLQRXWDQGWKHFRQWUDVWFLUFXLWXVLQJDVLQJOHSRZHUVXSSO\LI3&)ELW* 7KH/&'FRQWUROOHUGULYHU
Bytes sent to the PCF2116 are either control bytes, commands or data.
A control byte selects the desired instruction group according to table 1.
•
A control byte consists of 3 bits, followed by 5 zeros:
Co RS RW‘ 0
0
0
0
0
Bit Co=0 defines whether the following bytes are not control bytes and bit Co=1 defines that the following
two bytes are a command/data byte and another control byte.
Please note that in this application note,
instructions with RS=0, RW‘=0 will be called „first instruction group“ instructions,
instructions with RS=1, RW‘=0 will be called „second instruction group“ instructions and
Other instructions are read instructions and do not abide to any instruction group; they are also not used
in this application note.
This convention will be used in the code.
•
A command consists of 8 bits:
DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
* The ordering number is EA 7123-I2C and is distributed by Electronic Assembly: www.lcd-module.de.
8 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
A complete instruction is therefore 2 bytes:
Co RS RW‘ 0
0
0
0
0
DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
although one could send a control byte only once (with Co=0) and then send commands and always refer to
the same instruction group.
The PCF2116 instruction set is presented in the following table:
7DEOHD
7KH3&)IDPLO\LQVWUXFWLRQVHW
7DEOHE
'HVFULSWLRQRIWKHFRPPDQGELWV
9 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
The architecture and instructions of the PCF2116 will not be fully described here. Please refer to the
„PCF2116 family LCD controller/drivers“ product specification.
8VLQJRWKHULQVWUXFWLRQVHWV
It is of course possible to use other Displays, which have a controller with different commands or interface. In
general, as it can be seen in table 2 (the instruction set for the Hitachi HD44710 microcontroller), the
instructions are similar to the PCF2116 – that is, the manufacturers preserve a common instruction set. This
is why it is very easy to program different LCDs by using the code in this application note as a start. It should
be noted that it is also possible to switch to other LCD interfaces (serial or parallel) very simply because the
code presented here is general (using procedures and include files). Therefore one can build his/her own
2
interface routines and not use the I C routines provided here. The application can then take advantage of the
2
ready procedures in this paper, but not the optimized ones, as they are written specifically for an I C LCD
interface.
7DEOHD
7KH+'LQVWUXFWLRQVHW
7DEOHE
'HVFULSWLRQRIWKHFRPPDQGELWV
10 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
6WDUWLQJXS±WHVWLQJWKH/&'
2
Supposing that all connections are made correctly and ensuring that the I C bus is configured properly
(having appropriate pullups), one is ready to test the functionality of the LCD. A simple „HELLO!“ algorithm is
appropriate. The following code is based in the example from the PCF2116 datasheet. Step 4 should be
changed according to the LCD used (refer to the „function set“ instruction in the datasheet).
/********************************************************************************************* */
/* Test LCD
*/
/*
*/
/* Description:
*/
/* Send instructions to LCD according to the example in the PCF2116 datasheet.
*/
/********************************************************************************************* */
#include “i2c_sw8b.c“
// Siemens I2C-bus module
// Some characters from character set C
#define character_space 0x20
#define character_H
0x0C8
#define character_E
0x0C5
#define character_L
0x0CC
#define character_O
0x0CF
#define character_excl 0x0A1
void main(void)
{
I2cInit();
// Initialize I2C bus
I2cStart();
// step 1 : Start communication
I2cMasterWrite(0x74);
//01110100
// step 2 : SendSLAVE ADDRESS
I2cMasterWrite(0x00);
//00000000
// step 3 : CONTROL BYTE (first instruction group)
I2cMasterWrite(0x3E);
//00111110
// step 4 : _FUNCTION SET
I2cMasterWrite(0x0E);
//00001110
// step 5 : _DISPLAY ON/OFF CONTROL
I2cMasterWrite(0x06);
//00000110
// step 6 : _ENTRY MODE SET
// * change this
// I2cStop(); // This is not needed
I2cStart();
// step 7
I2cMasterWrite(0x74);
//01110100
// step 8 : Send SLAVE ADDRESS
I2cMasterWrite(0x40);
//01000000
// step 9 : CONTROL BYTE (second instruction group)
I2cMasterWrite(character_H);
// Write „H“ to DDRAM (also on the Display)
I2cMasterWrite(character_E);
// Write „E“
I2cMasterWrite(character_L);
// Write „L“
I2cMasterWrite(character_L);
// Write „L“
I2cMasterWrite(character_O);
// Write „O“
I2cMasterWrite(character_excl);
// Write „!“
I2cStop();
// (step 17) // stop communication
}
11 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
7KHVRIWZDUHOLEUDU\
The basic procedures were built arround the PCF2116 instruction set. These are:
352&('85(1$0(
,1387
287387
RIQRQRSWLPL]HGSURFHGXUH
success
error
other
cls_LCD
-
0
1
-
returnHome_LCD
-
0
1
-
entry_mode_set_LCD
bit ID, bit S
0
1
-
display_control_LCD
bit D, bit C, bit Blink
0
1
-
cursor_display_shift_LCD
bit SC, bit RL
0
1
-
function_set_LCD
-
0
1
-
set_CGRAM_address_LCD
unsigned char
address
0
1
-
set_DDRAM_address_LCD
unsigned char
address
0
1
-
write_char2LCD
unsigned char
character, unsigned
char offset
0
1
-
,16758&7,21
*5283
first
second
7DEOH
%DVLFSURFHGXUHVWKDWFRUUHVSRQGWRWKH'LVSOD\&RQWUROOHU¶VLQVWUXFWLRQV
Each procedure can be called RQO\ after calling the appropriate procedure for the instruction group in which
it belongs (otherwise the instructions will not be executed!):
YRLGILUVWBLQVWUXFWLRQBJURXSYRLG
YRLGVHFRQGBLQVWUXFWLRQBJURXSYRLG
Based on these procedures, one can initialize and use the LCD. To facilitate programming, certain routines
were developped and are presented in table 4.
* the optimized procedures do not have output ( void proc(..) )
12 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
352&('85(1$0(
,1387
287387
RIQRQRSWLPL]HGSURFHGXUH
success
wait
wait2
error
time_out : [0..65535]
other
-
gotoXY_LCD
unsigned char pos
0
1
-
initialize_LCD
bit ID,bit S,bit D,bit C,bit Blink,bit SC,bit RL
0
1
-
writedata2LCD_reverse unsigned char number, unsigned char
*value, unsigned char offset
0
character position at
which the error
occured (1..number)
writedata2LCD_normal
unsigned char number, unsigned char
*value, unsigned char offset
0
character position at
which the error
occured (1..number)
send_instruction2LCD
bit Co,bit RS,bit RW
0
1
-
7DEOH
6WDQGDUGSURFHGXUHV
'HVFULSWLRQRIWKHEDVLFSURFHGXUHV
QRQRSWLPL]HG
RSWLPL]HG
FOVB/&'
unsigned char cls_LCD(void)
ILUVWLQVWUXFWLRQJURXS
LQSXWV
void cls_LCD(void)
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
Clears the whole display (including non-visible areas) and returns cursor to
position 1. Display shift is also cancelled.
FRPPHQWV
After executing this command, the master-microcontroller will wait for about 2
ms until the LCD is ready to accept new commands.
VHHDOVR
ZDLW
* the optimized procedures do not have output ( void proc(..) )
13 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
QRQRSWLPL]HG
RSWLPL]HG
UHWXUQ+RPHB/&'
unsigned char returnHome_LCD(void)
ILUVWLQVWUXFWLRQJURXS
LQSXWV
void returnHome_LCD(void)
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
Returns cursor to position 1.
FRPPHQWV
VHHDOVR
FOVB/&'JRWR;<B/&'
QRQRSWLPL]HG
RSWLPL]HG
HQWU\BPRGHBVHWB/&' unsigned char
void entry_mode_set_LCD(bit ID, bit S)
entry_mode_set_LCD(bit ID, bit S)
ILUVWLQVWUXFWLRQJURXS
LQSXWV
bits ID, S. They are described in the PCF2116 datasheet
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
Instructs how the display should behave when writing characters or when
shifting the display with the cursor_display_shift_LCD command.
FRPPHQWV
VHHDOVR
FXUVRUBGLVSOD\BVKLIWB/&'
14 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
QRQRSWLPL]HG
GLVSOD\BFRQWUROB/&'
ILUVWLQVWUXFWLRQJURXS
RSWLPL]HG
unsigned char display_control_LCD(bit
D, bit C, bit Blink)
void display_control_LCD(bit D, bit C,
bit Blink)
LQSXWV
bits D, C, Blink. They are described in the PCF2116 datasheet
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
Sets display, cursor, or cursor-blink on or off.
FRPPHQWV
VHHDOVR
QRQRSWLPL]HG
RSWLPL]HG
FXUVRUBGLVSOD\BVKLIWB unsigned char
cursor_display_shift_LCD(bit SC, bit
/&'
void cursor_display_shift_LCD(bit SC,
bit RL)
RL)
ILUVWLQVWUXFWLRQJURXS
LQSXWV
bits SC, RL. They are described in the PCF2116 datasheet
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
Moves the cursor or shifts the visible area of the display left or right, according
to the bits ID and S (set by the entry_mode_set_LCD instruction).
FRPPHQWV
When the cursor is at the end of a line and is instructed to proceed right (/ left,
at the start of a line), the cursor will move to the start of the next line (/ the end
of the previous line). However, shifting the display outside the line boundaries
will result in a wrap-around. Cursor wrap-around occurs only between the end
of the last and the start of the first line.
VHHDOVR
HQWU\BPRGHBVHWB/&'
15 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
QRQRSWLPL]HG
RSWLPL]HG
IXQFWLRQBVHWB/&'
unsigned char function_set_LCD(void)
ILUVWLQVWUXFWLRQJURXS
LQSXWV
void function_set_LCD(void)
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
Sets the bits DL,N,M,G, which are defined as constant at the start of the code,
according to the type of the LCD.
FRPPHQWV
DL is set to 1 when an 8 bit data transmission during any I2C transfer is
2
desired. DL can be set to 0 when a 4 bit data transmission during any I C
transfer is desired, but WKLVKDVQRWEHHQWHVWHG.
Bits N ,M are set according to the number of lines and columns in our display.
To change this, define USE_4_LINES or USE_2_LINES or USE_1_LINE at the
start of the lcd.h module; one does not need to pay attention to these bits (N, M)
because they are automatically properly when selecting the appropriate
USE_x_LINEs definition.
Bit G should be set to one if one wishes to use a single and positive power
supply. Otherwise (bit G=0 – this is default at LCD startup) one would need to
use two power supplies, one negative and one positive. Please refer to the
comments of the lcd.h file for the schematics.
VHHDOVR
QRQRSWLPL]HG
VHWB&*5$0BDGGUHVV
B/&'
ILUVWLQVWUXFWLRQJURXS
RSWLPL]HG
unsigned char
set_CGRAM_address_LCD(unsigned
char address)
void
set_CGRAM_address_LCD(unsigned
char address)
LQSXWV
address : [0..63] (other inputs are processed with their 5 least significant bits)
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
Sets the CGRAM address.
FRPPHQWV
16 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
This instruction is used to define new characters/fonts. It is executed before
writting to the CGRAM with the write_char2LCD() or the
writedata2LCD_normal() procedures. It is also used inside the create_font()
procedure.
Each line of a character is a byte (with only the 6 least significant bits used).
Each bit indicates whether a dot is present or not (1 or 0). For example, the first
character of the CGRAM is addresses 0000000 to 0000111 (8 lines) with each
address containing a 6 bit value.
An example is found at the visual effects chapter, where an «Infineon» logo is
created and shown in a complex way on screen.
VHHDOVR
FUHDWHBIRQW
QRQRSWLPL]HG
VHWB''5$0BDGGUHVV
B/&'
ILUVWLQVWUXFWLRQJURXS
RSWLPL]HG
unsigned char
set_DDRAM_address_LCD(unsigned
char address)
void
set_DDRAM_address_LCD(unsigned
char address)
LQSXWV
address : [0..255]
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
Sets the DDRAM address.
FRPPHQWV
DDRAM address corresponds to the cursor position.
VHHDOVR
17 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
QRQRSWLPL]HG
ZULWHBFKDU/&'
VHFRQGLQVWUXFWLRQJURXS
RSWLPL]HG
unsigned char
write_char2LCD(unsigned char
character, unsigned char offset)
void write_char2LCD(unsigned char
character, unsigned char offset)
LQSXWV
the desired byte to write.
the offset is added to the character number.
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
Writes a byte to the LCD.
FRPPHQWV
when writing to the display, one must consult the appropriate character set table
for the LCD used. The offset byte is used in order to convert between ASCII and
the LCD character sets. For example, the ASCII «A» should be written with an
offset of 0x81, in order to be displayed correctly.
VHHDOVR
ZULWHGDWD/&'BQRUPDOZULWHGDWD/&'BUHYHUVH
18 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
'HVFULSWLRQRIWKHVWDQGDUGSURFHGXUHV
QRQRSWLPL]HGRSWLPL]HG
ZDLW
ZDLW
void wait(time_out)
void wait2(time_out)
LQSXWV
the desired time out
RXWSXWV
GHVFULSWLRQ
wait() slows the uC down for about 10*time_out clock cycles.
wait2() uses a double loop (calling wait()), so one can achieve greater time-outs
of several seconds.
FRPPHQWV
These routines are used to create time-outs. They are very useful when
creating visual effects, because they slow a process down, so that the human
eye can perceive it.
wait() is normally used after a cls_LCD() instruction. Here, it is included inside
the cls_LCD() procedure.
VHHDOVR
FOVB/&'DQ\YLVXDOHIIHFW
QRQRSWLPL]HG
JRWR;<B/&'
RSWLPL]HG
unsigned char gotoXY _LCD(unsigned
char pos)
void gotoXY _LCD(unsigned char pos)
LQSXWV
desired position of the cursor
RXWSXWV
0 if success
1 if there was an error (could not send
instruction to the LCD)
-
GHVFULSWLRQ
The cursor is placed in pos.
FRPPHQWV
This moves the cursor to a desired position. Example:
th
st
gotoXY(line1_start+3); //move to the 3+1 = 4 column, 1 line
line1_start is automatically defined when selecting an LCD with the
USE_x_LINEs definition
VHHDOVR
UHWXUQ+RPHB/&'
19 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
QRQRSWLPL]HGRSWLPL]HG
LQLWLDOL]HB/&'
unsigned char initialize_LCD(bit ID, bit
S, bit D, bit C, bit Blink, bit SC, bit RL)
void initialize_LCD(bit ID, bit S, bit D,
bit C, bit Blink, bit SC, bit RL)
LQSXWV
bits ID, S, D, C, Blink, SC, RL
RXWSXWV
0 if success
1 if there was an error (could not send
an instruction to the LCD)
-
GHVFULSWLRQ
Initializes the LCD. This procedure calls all the initialization procedures. It
should be included in a new project only if it is called in two or more discrete
positions of the code, otherwise simple initialization-procedure calls will produce
smaller code size.
FRPPHQWV
VHHDOVR
HQWU\BPRGHBVHWB/&'GLVSOD\BFRQWUROB/&'FXUVRUBGLVSOD\BVKLIWB/&'
IXQFWLRQBVHWB/&'
QRQRSWLPL]HG
RSWLPL]HG
ZULWHGDWD/&'BUHYHUVH unsigned char
writedata2LCD_reverse(unsigned
char number, unsigned char *value,
unsigned char offset)
ZULWHGDWD/&'BQRUPDO
void writedata2LCD_reverse(unsigned
char number, unsigned char *value,
unsigned char offset)
void writedata2LCD_normal(unsigned
unsigned char
writedata2LCD_normal(unsigned char char number, unsigned char *value,
unsigned char offset)
number, unsigned char *value,
unsigned char offset)
LQSXWV
number [1..255], a matrix beginning at pointer *value, offset
RXWSXWV
character position at which an error occured (1..number of characters) or zero
if no error occured
GHVFULSWLRQ
These two procedures print a string on the LCD. Inputs are the pointer to the
string and the length of the string. For example, the string «INFINEON» is an
8 character string.
FRPPHQWV
writedata2LCD_normal() prints from left to right, while
writedata2LCD_reverse() prints backwards(from right to left).
VHHDOVR
ZULWHBFKDU/&'
20 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
QRQRSWLPL]HG
VHQGBLQVWUXFWLRQ/&'
RSWLPL]HG
unsigned char
send_instruction2LCD(void)
void send_instruction2LCD(void)
LQSXWV
RXWSXWV
0 if success
1 if there was an error (could not send
an instruction to the LCD)
-
GHVFULSWLRQ
This command sends the "Co RS RW 0 0 0 0 0" control byte to the slave LCD.
FRPPHQWV
This procedure is not used in this application note’s code. The instructions
first_ and second_instruction_group() are prefered instead. In addition, bit Co
is always written as zero because this proved to be more efficient. However
there is some possibility that another application could benefit from the use of
Co as 1. The code size would then be reduced.
VHHDOVR
ILUVWBLQVWUXFWLRQBJURXSVHFRQGBLQVWUXFWLRQBJURXS
'LVFXVVLRQRIWKHFRGHVL]HDQGWKHRSWLPL]DWLRQ
There are two possible ways to optimize the code:
•
2
disable any code related to I C error checking/returning. For example, instead of using XQVLJQHGFKDU
SURFHGXUH, one could use YRLGSURFHGXUH:
unsigned char write_char2LCD(unsigned char character,unsigned char offset)
{
if(I2cMasterWrite(character+offset)) return(1);
return(0);
}
This can be replaced by
void write_char2LCD(unsigned char character,unsigned char offset)
{
I2cMasterWrite(character+offset);
}
Also, instead of executing a
while(I2cMasterWrite(byte));
// send byte until an acknowledge is received
one could simply do a
I2cMasterWrite(byte);
discarding the output from this procedure.
21 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
•
replace a procedure call with the procedure’s code. As an example, instead of having
write_char2LCD(0x7A,0x80);
it is better to have this:
I2cMasterWrite(0x7A+0x80);
When using an LCD, the code size of the procedures related to LCD controlling is usually critical. Using the
non-optimized procedures may indeed provide communication error-detection, but the difference in code
size should be set into consideration. From the author’s point of view, one should use the optimized routines
because the memory required is much smaller.
2
An error during the I C initialization results in a blank Display. An error during runtime (and after a succesfull
2
initialization) is not important; execution continues and the display will output text as soon as the I C error is
corrected. It is also not very hard to assure error-free communication by checking the hardware connections
(and perhaps run a very simple test-LCD program, see §1.6).
To conclude, any communication errors need not to be identified and possibly reported because a LCD is not
a critical component and the code-size is significant in most applications.
Code-size is important. This is why all visual effects in the next chapter are code size-optimized. In the code,
the non-optimized procedures are provided as remarks next to the optimized ones. Also, excluding (deleting)
unused procedures is very important because this will reduce the code size.
How much is the code size? The first lines of the link results are presented below:
BL51 BANKED LINKER/LOCATER V3.70c
25/10/99
15:32:48
PAGE 1
MS-DOS BL51 BANKED LINKER/LOCATER V3.70c, INVOKED BY:
C:\PROGLOC\MCU\C51PK\BIN\BL51.EXE C:\USERDATA\SKRAPA~1\FINAL_~1\I2C_SW8B.OBJ,
>> C:\USERDATA\SKRAPA~1\FINAL_~1\I2C_LCD.OBJ TO C:\USERDATA\SKRAPA~1\FINAL_~1\
>> I2C IX RS (256) PL (68) PW (78) CO (1000H) REGFILE (I2C.REG)
MEMORY MODEL: SMALL
INPUT MODULES INCLUDED:
C:\USERDATA\SKRAPA~1\FINAL_~1\I2C_SW8B.OBJ (I2C_SW8B)
C:\USERDATA\SKRAPA~1\FINAL_~1\I2C_LCD.OBJ (I2C_LCD)
C:\PROGLOC\MCU\C51PK\LIB\C51S.LIB (?C_STARTUP)
C:\PROGLOC\MCU\C51PK\LIB\C51S.LIB (?C?CLDOPTR)
C:\PROGLOC\MCU\C51PK\LIB\C51S.LIB (?C?IMUL)
LINK MAP OF MODULE:
C:\USERDATA\SKRAPA~1\FINAL_~1\I2C (I2C_SW8B)
22 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
TYPE
BASE
LENGTH
RELOCATION
SEGMENT NAME
-----------------------------------------------------
* * * * * * *
D A T A
M E M O R Y
* * * * * * *
REG
0000H
0008H
ABSOLUTE
"REG BANK 0"
DATA
0008H
0005H
UNIT
?DT?_WRITEDATA2LCD_REVERS
000DH
0002H
UNIT
?DT?I2C_SW8B
000FH
0011H
0020H.0
0002H.2
>> E?I2C_LCD
DATA
BIT
*** GAP ***
UNIT
_BIT_GROUP_
0022H.2
0000H.6
DATA
0023H
001AH
UNIT
_DATA_GROUP_
IDATA
003DH
0001H
UNIT
?STACK
* * * * * * *
C O D E
CODE
*** GAP ***
M E M O R Y
* * * * * * *
0000H
0003H
ABSOLUTE
0003H
0FFDH
CODE
1000H
0531H
INBLOCK
?PR?MAIN?I2C_LCD
CODE
1531H
0119H
INBLOCK
?PR?TEXTEFFECT?I2C_LCD
CODE
164AH
0104H
UNIT
?CO?I2C_LCD
CODE
174EH
00A6H
INBLOCK
?PR?CREATE_FONT?I2C_LCD
CODE
17F4H
000CH
UNIT
?C_C51STARTUP
CODE
1800H
00C9H
INBLOCK
?PR?PRINTINFINEONLOGO?I2C
CODE
18C9H
00C3H
INBLOCK
?PR?_TEXTROLL?I2C_LCD
CODE
198CH
0070H
INBLOCK
?PR?I2CSTOP?I2C_SW8B
CODE
19FCH
006DH
INBLOCK
?PR?_TEXTTRANS?I2C_LCD
CODE
1A69H
006AH
INBLOCK
?PR?_I2CMASTERWRITE?I2C_S
CODE
1AD3H
005BH
INBLOCK
?PR?_I2CMASTERREAD?I2C_SW
CODE
1B2EH
0041H
UNIT
?C?LIB_CODE
CODE
1B6FH
003AH
INBLOCK
?PR?INITIALIZE_LCD?I2C_LC
CODE
1BA9H
002DH
INBLOCK
?PR?_WRITEDATA2LCD_REVERS
CODE
1BD6H
002BH
INBLOCK
?PR?_WRITEDATA2LCD_NORMAL
CODE
1C01H
0029H
INBLOCK
?PR?I2CSTART?I2C_SW8B
CODE
1C2AH
0021H
INBLOCK
?PR?SEND_INSTRUCTION2LCD?
CODE
1C4BH
001EH
INBLOCK
?PR?CHECK_SCL?I2C_SW8B
*** GAP ***
>> _LCD
>> W8B
>> 8B
>> D
>> E?I2C_LCD
>> ?I2C_LCD
>> I2C_LCD
23 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
CODE
1C69H
001DH
INBLOCK
?PR?DISPLAY_CONTROL_LCD?I
>> 2C_LCD
CODE
1C86H
001BH
INBLOCK
?PR?I2CINIT?I2C_SW8B
CODE
1CA1H
0019H
INBLOCK
?PR?CURSOR_DISPLAY_SHIFT_
CODE
1CBAH
0018H
INBLOCK
?PR?_WAIT2?I2C_LCD
CODE
1CD2H
0013H
INBLOCK
?PR?ENTRY_MODE_SET_LCD?I2
CODE
1CE5H
0012H
INBLOCK
?PR?FIRST_INSTRUCTION_GRO
1CF7H
0012H
INBLOCK
?PR?SECOND_INSTRUCTION_GR
CODE
1D09H
000DH
INBLOCK
?PR?CLS_LCD?I2C_LCD
CODE
1D16H
000DH
INBLOCK
?PR?_GOTOXY_LCD?I2C_LCD
CODE
1D23H
000BH
INBLOCK
?PR?_WAIT?I2C_LCD
CODE
1D2EH
000AH
INBLOCK
?PR?_SET_CGRAM_ADDRESS_LC
CODE
1D38H
0008H
INBLOCK
?PR?CHECKCLOCK?I2C_SW8B
CODE
1D40H
0008H
INBLOCK
?PR?_SET_DDRAM_ADDRESS_LC
CODE
1D48H
0007H
INBLOCK
?PR?_WRITE_CHAR2LCD?I2C_L
CODE
1D4FH
0006H
INBLOCK
?PR?RETURNHOME_LCD?I2C_LC
CODE
1D55H
0006H
INBLOCK
?PR?FUNCTION_SET_LCD?I2C_
>> LCD?I2C_LCD
>> C_LCD
>> UP?I2C_LCD
CODE
>> OUP?I2C_LCD
>> D?I2C_LCD
>> D?I2C_LCD
>> CD
>> D
>> LCD
2
2
I C bus interface routines are marked with grey, while the very basic procedures for the I C LCD control are
marked with yellow. This gives us a very rough approximation of the code size:
2
I C bus interface takes about 212 bytes, while the procedures used to control and print text on the LCD have
a code length of about 238 bytes. Please note that these sizes are not the absolute minimum: they can be
decreased. The number of procedures that is needed depends on the application. Their size depends on the
level of manual optimization performed by the programmer.
7KHLPSOHPHQWDWLRQRIYLVXDOHIIHFWV
Visual effects can now be developed by simply using the basic and standard procedures from the previous
chapter. The reader is encouraged to read through the code, so as to fully understand the effects and modify
them according to his/her needs.
In some of the procedures presented in this paper, offset is used. A suggested value for offset is 0x80 –
when using compiler-defined ASCII strings. This is because ASCII and the LCD character set are different;
normal ASCII characters correspond to LCD character set C characters by adding 0x80 (see the character
set table in the PCF2116 datasheet). However, this is used only for testing. A final application could read the
strings from an eeprom; or the strings could be stored with their correct values according to the LCD
character set. offset should then be deleted from the procedures, saving code size.
The sample effects are:
24 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
WH[WHIIHFW
void texteffect(bit height, unsigned char *text1, unsigned char *text2, unsigned char length, unsigned char
pos, char direction, unsigned char clearchar, unsigned char offset)
GHVFULSWLRQ
This procedure prints out with a fade-in effect (with a direction of right, if direction=1 or left, if direction=0) a
string or two strings at position pos on the display.
height is the number of strings minus one (:0 for one string and 1 for two strings) and text1, text2 are the
matrices that contain the strings. Length is the length of each string (they must have the same length).
clearchar is the character from which the fade-in begins. A standard value is the space character(0xA0) and
other interesting values are 0xA4 or 0x3D.
offset has been described before. It is added to each character of the two texts.
One could experiment by modifying the code in order to achieve faster or slower printing (change the values
of maxmuzzy2 and the factor 10 at muzzystep2 - see the start of the procedure)
WH[WWUDQV
void texttrans(unsigned char *text1, unsigned char length1, unsigned char *text2, unsigned char length2,
unsigned char pos, unsigned char maxmuzzy3, unsigned char muzzystep3, interval, unsigned char offset)
GHVFULSWLRQ
This effect is a transmission between two texts. The first text fades out while the second fades in at the same
place. Transitional speed is defined by the values of maxmuzzy3 and muzzystep3.
WH[WUROO
void textroll(unsigned char *text, unsigned char length, unsigned char pos, interval , unsigned char rolltop,
unsigned char offset)
GHVFULSWLRQ
This effect is like the train-station boards that announce the departure and time-schedule of trains
Each character starts from the rolltop character and is decreased until it reaches the corresponding
character from *text. Any space characters (defined as character_space) are ignored.
interval controls the speed of this effect.
25 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
It would be interesting to develop a similar but more complicated procedure like
void textroll2(unsigned char *text1, unsigned char *text2, unsigned char length, unsigned char pos, interval,
unsigned char offset)
description: a line continually prints characters. Each character starts from the corresponding character from
text1 and is decreased until it reaches the desired character (from text2), with a possible wrap-around
(characters 0xA0 and 0xFF).
Suggested offset is 0x80.
SULQWLQILQHRQORJR
// special characters are defined and arranged in the lcd.h file
void create_font(void)
void printinfineonlogo(bit direction, bit clearchar, bit displaycursor, bit clr)
GHVFULSWLRQ
This effect combines the use of special characters, texteffect and the cursor. It prints out the Infineon logo.
This is a nice effect to implement before entering a sleep or idle mode.
direction and clearchar are defined in texteffect.
displaycursor is either true or false (if one desires the cursor to be printed during predefined intervals or not)
bit clr instructs to clear the screen before printing the logo (if true).
(SLORJXH
As described before, this application note can be used as a start when designing new LCD applications.
Examples of such applications are portable instruments, home appliances and public information displays.
26 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
$SSHQGL[
The full executable code together with an I2C-bus module is found in the zip file that accompanies this
application note. The C-compiler used was Keil 8051 v5.20 but one could of course use any C-compiler. This
code was originally written for the Infineon C504 microcontroller. If one decides to use another
microcontroller (example: Infineon C508), one should adapt the wait intervals inside and outside the effects
in order to achieve normal speeds.
main() includes a demonstration of all the visual effects.
$
/******************************************************************************* */
/* The include file name: I2C_8b.DEF
*/
/*
*/
/* This is an include file for I/O port declaration of SCL and SDA
*/
/* The users can modify this include file according to the I/O port
*/
/* assignment of their preference.
*/
/*
*/
/******************************************************************************* */
sbit SCL = 0x90^0;
/* Port 1.0*/
sbit SDA = 0x90^1;
/* Port 1.1*/
//sbit SCL = 0xf8^0;
/* Port 1.0*/
//sbit SDA = 0xf8^1;
/* Port 1.1*/
%
/********************************************************************************/
// lcd.h
//
// LCD configuration, constant definitions for the visual effects, LCD graphics
//
// An include file for the I2C_LCD.C program
/********************************************************************************/
#define LCD_device_address 0x74
#define USE_4_LINES
#define G 1
#define DL 1
// LCD slave address: 01110100
// Is it a 1, 2 or 4-line LCD?
// See remark below
// i2c interface to the lcd is used, so DL is predefined as 1
27 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
// These values define the speed of some of the effects
#define maxmuzzy 1000
//1300
#define muzzystep 10
//20
// Used with the wait() procedure
#define for_10_s 65535
//maximum wait
#define for_2_ms 580
#define nocursor 0
#define cursor 1
#define clearscreen 1
#define noclearscreen 0
// if G=1, use only one external voltage supply
// if G=0, use two external voltage supplies
// Please refer to the following schematics. They are used to control LCD contrast..
/*
Circuit diagram for the single LCD supply (bit G=1):
Vdd +3.6..+6V
^
100nF |
Vlcd----||---+----+
|
|
O
|
V0------+->O
O
-- 100nF
--
100KOhm |
|
pot
|
|
|
|
_
_
Vss
28 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
Circuit diagram for the double LCD supply (bit G=0):
Vdd +2.5..+6V
^
|
V0---------+
|
|
O
10K
about |
O
resistor
6.5V
|
O
v
|
|
O
Vlcd------+->O
5K
potentiometer
O
|
|
|
|
^
-1V..-5V
*/
// The infineon logo
// These can be read from an eeprom!
// the following are used to create the font
unsigned char code logo0[8]={0x00,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C};
unsigned char code logo1[8]={0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C};
unsigned char code logo2[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x1B};
unsigned char code logo3[8]={0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B};
unsigned char code logo4[8]={0x00,0x07,0x0F,0x0C,0x0C,0x0C,0x1F,0x0C};
unsigned char code logo5[8]={0x00,0x00,0x00,0x0C,0x0C,0x00,0x0C,0x0C};
unsigned char code logo6[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x1B};
unsigned char code logo7[8]={0x1B,0x1B,0x1F,0x18,0x1B,0x1B,0x0E,0x0E};
unsigned char code logo8[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x1B};
unsigned char code logo9[8]={0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x0E,0x0E};
unsigned char code logo10[8]={0x00,0x00,0x00,0x0C,0x1E,0x1E,0x0C,0x00}; // the dot above I
29 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
/* Some defined characters which are not used
unsigned char logo11[8]={0x1F,0x1F,0x0F,0x0F,0x1F,0x1F,0x0C,0x00};
unsigned char logo12[8]={0x1F,0x1F,0x1F,0x0F,0x1F,0x1F,0x0C,0x00};
unsigned char logo13[8]={0x1F,0x1F,0x1E,0x0F,0x1F,0x1F,0x0C,0x00};
unsigned char logo14[8]={0x1F,0x1F,0x1D,0x0F,0x1F,0x1F,0x0C,0x00};
unsigned char logo15[8]={0x1F,0x1F,0x1C,0x0F,0x1F,0x1F,0x0C,0x00};
unsigned char logo16[8]={0x1F,0x1F,0x1B,0x0F,0x1F,0x1F,0x0C,0x00};
*/
// the following are used to construct the logo (arrange the previous defined fonts)
unsigned char code logo_0_0[8]= {0x00,0x02,0x04,0x05,0x02,0x06,0x08,0x02};
unsigned char code logo_0_1[8]= {0x01,0x03,0x01,0x01,0x03,0x07,0x09,0x03};
/*
unsigned char logo_0=0x00; //00000
unsigned char logo_1= 0x0C; //01100
unsigned char logo_2= 0x1E; //11110
unsigned char logo_3= 0x1B; //11011
unsigned char logo_4= 0x07; //00111
unsigned char logo_5= 0x0F; //01111
unsigned char logo_6= 0x1F; //11111
unsigned char logo_7= 0x0E; //01110
unsigned char logo_8= 0x18; //11000
#define logo_0 0x00 //00000
#define logo_1 0x0C //01100
#define logo_2 0x1E //11110
#define logo_3 0x1B //11011
#define logo_4 0x07 //00111
#define logo_5 0x0F //01111
#define logo_6 0x1F //11111
#define logo_7 0x0E //01110
#define logo_8 0x18 //11000
I
n
f
i
e
o
00000
00000
00111
00000
01100
00000
01111
00000
01100
00000
01100
01100
01100
00000
01100
01100
01100
00000
01100
00000
01100
00000
11111
00000
01100
11110
01100
01100
30 of 62
01110
01110
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
01100
11011
01100
01100
11011
11011
01100
11011
01100
01100
01100
11011
01100
01100
01100
11011
01100
01100
11000
11011
01100
11011
01100
01100
11011
11011
01100
11011
01100
01100
01100
11011
01100
01100
11011
11111
11011
11011
11011
01110
11011
01110
*/
&
/********************************************************************************/
/*
*/
/*
*/
/*
INFINEON TECHNOLOGIES Standard Software
/*
*/
*/
/*______________________________________________________________________________*/
/*
*/
/*
Programmer:
Dimitrios Skraparlis
*/
/*
Department:
iE Munich
*/
/*
Revision
2.0
*/
:
/*______________________________________________________________________________*/
/*
/*
*/
Description: This program has the appropriate procedures to use
*/
/*
LCD displays based on Philips PCF2116 family controllers
*/
/*
using the i2c protocol.
*/
/*
*/
/*______________________________________________________________________________*/
/*
/*
*/
Brief History:
*/
/*
10.08.1999: Start of the module
*/
/*
23.08.1999: Successful run
*/
/*
25.08.1999: The first effects!
*/
/*
08.09.1999: Beta version / cleaned up the code a little
*/
/*
26.10.1999: Code is included in the application note.
*/
/*______________________________________________________________________________*/
/*
*/
/* Comments:
*/
/*
*/
31 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
/* The usage of [Co] can speed-up the code a little. It is not however used,
*/
/* in order to produce general code. In other words, the code can be
*/
/* optimised by carefully using Co and not always I2cstart..
*/
/*
*/
/* Bear in mind that this code is not as optimised as it could be (in order
*/
/* for it to be an excellent reference source).
*/
/* It is also not optimized for readability.
*/
/********************************************************************************/
#include "lcd.h"
#include "i2c_sw8b.h"
#include "reg505L.h"
#define character_space 0x20 // the space character from character set C
//#define character_space 0xA0 // the second space character from character set C
#ifdef USE_4_LINES
// 4 lines * 12 characters
#define N 1
#define M 1
#define line1_start 0x00
#define line1_end 0x13
#define line2_start 0x20
#define line2_end 0x33
#define line3_start 0x40
#define line3_end 0x53
#define line4_start 0x60
#define line4_end 0x73
#define line_difference 0x20
#define line_length line_difference
#endif
#ifdef USE_2_LINES
// 2 lines * 24 characters
#define N 1
#define M 0
#define line1_start 0x00
#define line1_end 0x27
#define line2_start 0x40
#define line2_end 0x67
#define line_difference 0x40
32 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
#define line_length line_difference
#endif
#ifdef USE_1_LINE
// 1 line * 24 characters
#define N 0
#define M 0
#define line1_start 0x00
#define line1_end 0x4F
#define line_difference 0x00
#define line_length line_difference
#endif
#define DLNMG 2*G+4*M+8*N+0x10*DL+0x20
//**************************************************************************************************
// Send an instruction to the LCD
//
// This command outputs the "Co RS RW 0 0 0 0 0" control byte to the slave LCD
//
//**************************************************************************************************
void send_instruction2LCD(bit Co,bit RS,bit RW) //unsigned char send_instruction2LCD(bit Co,bit
RS,bit RW)
{
I2cMasterWrite(0x20*(unsigned char)(RW)|0x40*(unsigned char)(RS)|0x80*(unsigned char)(Co));
//
if (I2cMasterWrite(0x20*(unsigned char)(RW)|0x40*(unsigned char)(RS)|0x80*(unsigned char)(Co)))
return(1);
//
return(0);
}
//**************************************************************************************************
//*
//* Enable access to the first LCD uC instruction group (transmit RS=0, RW’=0)
//*
//**************************************************************************************************
void first_instruction_group(void)
{
33 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
I2cStart();
I2cMasterWrite(LCD_device_address);
send_instruction2LCD(0,0,0);
}
//**************************************************************************************************
//*
//* Enable access to the second LCD uc instruction group (transmit RS=1, RW’=0)
//*
//**************************************************************************************************
void second_instruction_group(void)
{
I2cStart();
I2cMasterWrite(LCD_device_address);
send_instruction2LCD(0,1,0);
}
//**************************************************************************************************
// Wait for a period of about (10 * time_out) cycles
//
// For the C504 with a 20MHz clock, 1 cycle=12/20480000 sec ~= 585.938 ns
// Therefore wait slows the uC down for (5.85938*time_out) usec
//
//**************************************************************************************************
void wait(time_out)
{
while (time_out--);
}
//**************************************************************************************************
// Example of a "wait for a much longer period" procedure
//
// With this procedure wait states of several seconds can be achieved
//**************************************************************************************************
void wait2(time_out)
{
while (time_out--) wait(time_out);
//unsigned int time_out2=time_out;
//while (time_out2--) {while (time_out--);}
}
34 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
//**************************************************************************************************
// Clear LCD Screen and wait until the LCD is ready (after about 2ms)
//
//
Screen is cleared, LCD shift is cancelled and cursor returns to position 0
//
//**************************************************************************************************
void cls_LCD(void) //unsigned char cls_LCD(void)
{
I2cMasterWrite(0x01);
wait(for_2_ms);
}
//**************************************************************************************************
// Return Home
//
//
Shift is cancelled and the cursor returns to position 0
//
// RS
R/W’
// --- --// 0
0
//**************************************************************************************************
void returnHome_LCD(void) //unsigned char returnHome_LCD(void)
{
I2cMasterWrite(0x02);
//
if (I2cMasterWrite(0x02)) return(1);
//
return(0);
// send command: "return home"
}
//**************************************************************************************************
// Set DDRAM address
//
// RS
R/W’
// --- ---
35 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
// 0
0
//**************************************************************************************************
void set_DDRAM_address_LCD(unsigned char address) //unsigned char set_DDRAM_address_LCD(unsigned
char address)
{
I2cMasterWrite(address|0x80);
//
if (I2cMasterWrite(address|0x80)) return(1);
//
return(0);
}
//**************************************************************************************************
// Set CGRAM address
//
// RS
R/W’
// --- --// 0
0
//**************************************************************************************************
void set_CGRAM_address_LCD(unsigned char address) //unsigned char set_CGRAM_address_LCD(unsigned
char address)
{
I2cMasterWrite((address&0x7F)|0x40);
//
if (I2cMasterWrite((address&0x7F)|0x40)) return(1);
//
return(0);
}
//**************************************************************************************************
// Write data backwards
// Inputs: *value : the start of the string
//
number : the string length
//
// Returns 0 if write was successful
// or the value of number +1 (i.e. 1 or 2 or 3.. etc) if not successful
// (this value indicates how many bytes were written +1)
// +1 is used because no written bytes would result in a return 0, which indicates successful write!
//
// Attention:
36 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
// One must specify Co=0 before this because here we send only data bytes. To send another control
byte,
// a I2cStart should be performed after this.
//
//
//**************************************************************************************************
void writedata2LCD_reverse(unsigned char number, unsigned char *value, unsigned char offset)
//unsigned char writedata2LCD_reverse(unsigned char number, unsigned char *value, unsigned char
offset)
{
second_instruction_group();
while (number>0)
{
I2cMasterWrite(offset+*(value+number-1));
//if(I2cMasterWrite(offset+*(value+number-1))) return(number+1); // if there is no
acknowledgement, abort and return the value of number
number--;
}
//return(0);
}
//**************************************************************************************************
// Write data normally (not backwards)
//
// Inputs: *value : the start of the string
//
number : the string length
//
// Returns 0 if write was successful
// or the value of counter +1 if not successful
// (this value indicates how many bytes were written +1)
// +1 is used because no written bytes would result in a return 0, which indicates successful write!
//
// Attention:
// One must specify Co=0 before this because here we send only data bytes. To send another control
byte,
// a I2cStart should be performed after this.
//
//
//**************************************************************************************************
37 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
void writedata2LCD_normal(unsigned char number, unsigned char *value, unsigned char offset)
//unsigned char writedata2LCD_normal(unsigned char number, unsigned char *value, unsigned char
offset)
{
/* Instead of this code:
unsigned char lastnumber=number;
second_instruction_group();
while (number>0)
{
if(I2cMasterWrite(offset+*(value+lastnumber-number))) return(lastnumber-number); // if there is
no acknowledgement, abort and return the value of number
number--;
}
return(0);
better use the following code:
*/
unsigned char counter=0;
second_instruction_group();
while (counter<number)
{
I2cMasterWrite(offset+*(value+counter));
//if(I2cMasterWrite(offset+*(value+counter))) return(counter+1); // if there is no
acknowledgement, abort and return the value of number
counter++;
}
//return(0);
}
//**************************************************************************************************
// Write a character to the LCD
//
// RS
R/W’
// --- --// 1
0
//
//**************************************************************************************************
void write_char2LCD(unsigned char character,unsigned char offset) //unsigned char
write_char2LCD(unsigned char character,unsigned char offset)
{
I2cMasterWrite(character+offset);
//
if(I2cMasterWrite(character+offset)) return(1);
//
return(0);
38 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
}
//**************************************************************************************************
// Goto (X,line) on the LCD memory
//
//**************************************************************************************************
void gotoXY_LCD(unsigned char pos) //unsigned char gotoXY_LCD(unsigned char pos)
{
first_instruction_group();
I2cMasterWrite(0x80|pos);
//
if(I2cMasterWrite(0x80|pos)) return(1);
//
return(0);
}
//**************************************************************************************************
// Entry mode set
//
// RS
R/W’
// --- --// 0
0
//**************************************************************************************************
void entry_mode_set_LCD(bit ID,bit S) //unsigned char entry_mode_set_LCD(bit ID,bit S)
{
I2cMasterWrite(((unsigned char)(S))|(2*(unsigned char)(ID))|0x04);
//
//
if (I2cMasterWrite(((unsigned char)(S))|(2*(unsigned char)(ID))|0x04)) return(1);
return(0);
}
//**************************************************************************************************
// Display control
//
// RS
R/W’
// --- --// 0
0
//**************************************************************************************************
void display_control_LCD(bit D,bit C,bit Blink)
Blink)
//unsigned char display_control_LCD(bit D,bit C,bit
39 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
{
I2cMasterWrite(((unsigned char)(Blink))|(2*(unsigned char)(C))|(4*(unsigned char)(D))|0x08);
//
if (I2cMasterWrite(((unsigned char)(Blink))|(2*(unsigned char)(C))|(4*(unsigned
char)(D))|0x08)) return(1);
//
return(0);
}
//**************************************************************************************************
// Cursor/display shift
//
// RS
R/W’
// --- --// 0
0
//**************************************************************************************************
void cursor_display_shift_LCD(bit SC,bit RL) //unsigned char cursor_display_shift_LCD(bit SC,bit RL)
{
I2cMasterWrite((4*(unsigned char)(RL))|(8*(unsigned char)(SC))|0x10);
//
if (I2cMasterWrite((4*(unsigned char)(RL))|(8*(unsigned char)(SC))|0x10)) return(1);
//
return(0);
}
//**************************************************************************************************
// Function set
//
// Note:
// the bits used inside(bit DL,bit N,bit M,bit G) are global constants//
//
// RS
R/W’
// --- --// 0
0
//**************************************************************************************************
void function_set_LCD(void) //unsigned char function_set_LCD(void)
{
I2cMasterWrite(DLNMG);
//
if (I2cMasterWrite(DLNMG)) return(1);
//
return(0);
}
40 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
//**************************************************************************************************
//
// Initialize liquid crystal display
//
// Addresses the LCD slave, initializes the display and stops communication (with I2cStop)
//
// Note:
// DL, N, M ,G are constant - this is why they are not p as parametres
//**************************************************************************************************
void initialize_LCD(bit ID,bit S,bit D,bit C,bit Blink,bit SC,bit RL) //unsigned char
initialize_LCD(bit ID,bit S,bit D,bit C,bit Blink,bit SC,bit RL)
{
//wait(for_2_ms);
// 2 ms wait for the LCD to start up
I2cStart();
I2cMasterWrite(LCD_device_address);
send_instruction2LCD(0,0,0);
function_set_LCD();
display_control_LCD(D,C,Blink);
entry_mode_set_LCD(ID,S);
cursor_display_shift_LCD(SC,RL);
/*
if (I2cMasterWrite(LCD_device_address))
// Address the slave
{
I2cStop();
// No acknowledge? Then
return(1);
// stop and return 1.
}
if (send_instruction2LCD(0,0,0)) //Co,RS,RW
{
I2cStop();
return(1);
}
if(function_set_LCD())
{
I2cStop();
return(1);
}
if(display_control_LCD(D,C,Blink))
{
41 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
I2cStop();
return(1);
}
if(entry_mode_set_LCD(ID,S))
{
I2cStop();
return(1);
}
if(cursor_display_shift_LCD(SC,RL))
{
I2cStop();
return(1);
}
// I2cStop(); // It is not needed
return(0);
*/
}
//**************************************************************************************************
//* Write (bit: height)-line text smoothly at position pos.
//* If height=1 then output a two line text
//* If height=0 then output a one line text
//* Direction:
//* 1 for right, 0 for left
//*
//**************************************************************************************************
void texteffect(bit height, unsigned char *text1, unsigned char *text2, unsigned char length,
unsigned char pos, char direction, unsigned char clearchar, unsigned char offset)
{
unsigned int muzzy;
char counter;
unsigned char maxmuzzy2=1000;
unsigned char muzzystep2=10*((unsigned char)(height)+1);
unsigned char startcounter;
char counterstep;
if (direction==1) { startcounter=0; counterstep=1; length=length-1; direction++;}
else if (direction==0) { startcounter=length-1; counterstep=-1; length=0;}
42 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
for (counter=startcounter;(direction-1)*counter<=length;counter=counter+counterstep)
{
for(muzzy=0;muzzy<maxmuzzy2;muzzy=muzzy+muzzystep2)
{
first_instruction_group();
I2cMasterWrite(0x80|(pos+counter));//gotoXY_LCD(pos+counter);
second_instruction_group();
I2cMasterWrite(clearchar);//write_char2LCD(clearchar,0);
if (height==1)
{
first_instruction_group();
I2cMasterWrite(0x80|(pos+counter+line_length));//gotoXY_LCD(pos+counter+line_length);
second_instruction_group();
I2cMasterWrite(clearchar);//write_char2LCD(clearchar,0);
}
wait(maxmuzzy2-muzzy);// This is a linear transition. Another possible value: maxymuzzy2/muzzy
first_instruction_group();
I2cMasterWrite(0x80|(pos+counter));//gotoXY_LCD(pos+counter);
second_instruction_group();
I2cMasterWrite(*(text1+counter)+offset);//write_char2LCD(*(text1+counter), offset);
if (height==1)
{
first_instruction_group();
I2cMasterWrite(0x80|(pos+counter+line_length));//gotoXY_LCD(pos+counter+line_length);
second_instruction_group();
I2cMasterWrite(*(text2+counter)+offset);//write_char2LCD(*(text2+counter), offset);
}
wait(muzzy);
}
//wait(10000);
}
}
//**************************************************************************************************
//* Text transition from text1 to text2 at position pos.
43 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
//*
//**************************************************************************************************
void texttrans(unsigned char *text1, unsigned char length1, unsigned char *text2, unsigned char
length2, unsigned char pos, unsigned char maxmuzzy3, unsigned char muzzystep3, interval, unsigned
char offset)
{
unsigned char muzzy;
for(muzzy=0;muzzy<maxmuzzy3;muzzy=muzzy+muzzystep3)
{
first_instruction_group();
I2cMasterWrite(0x80|pos);//gotoXY_LCD(pos);
second_instruction_group();
writedata2LCD_normal(length1,text1, offset);
wait(maxmuzzy3/muzzy); // This looks like an exponential transition. Another possible value:
maxymuzzy3-muzzy
first_instruction_group();
I2cMasterWrite(0x80|pos);//gotoXY_LCD(pos);
second_instruction_group();
writedata2LCD_normal(length2,text2, offset);
wait(muzzy);
}
wait2(interval);
}
//**************************************************************************************************
//* Roll text at pos
//*
//**************************************************************************************************
void textroll(unsigned char *text, unsigned char length, unsigned char pos, interval, unsigned char
rolltop, unsigned char offset)
{
unsigned char counter2;
unsigned char counter;
unsigned char min=rolltop;
for(counter=0;counter<length;counter++)
{
if ((*(text+counter)<min)&(*(text+counter)!=character_space)) min=*(text+counter); //calculate
minimum character code
//Do not mess with the space char: " "
44 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
}
for(counter2=rolltop;counter2>=(min+offset);counter2--)
{
first_instruction_group();
I2cMasterWrite(0x80|pos);//gotoXY_LCD(pos);
second_instruction_group();
for(counter=0;counter<length;counter++)
{
// Don’t do this effect if space character: " "
if ((*(text+counter)<counter2-offset)&(*(text+counter)!=character_space))
I2cMasterWrite(counter2);//write_char2LCD(counter2,0);
else I2cMasterWrite(*(text+counter)+offset);//write_char2LCD(*(text+counter),offset);
}
wait(interval);
}
}
//**************************************************************************************************
//* Writes the user-defined characters to the CG-RAM
//*
//**************************************************************************************************
void create_font(void)
{
first_instruction_group();
set_CGRAM_address_LCD(0x00);
second_instruction_group();
writedata2LCD_normal(8,logo0,0);
writedata2LCD_normal(8,logo1,0);
writedata2LCD_normal(8,logo2,0);
writedata2LCD_normal(8,logo3,0);
writedata2LCD_normal(8,logo4,0);
writedata2LCD_normal(8,logo5,0);
writedata2LCD_normal(8,logo6,0);
writedata2LCD_normal(8,logo7,0);
writedata2LCD_normal(8,logo8,0);
45 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
writedata2LCD_normal(8,logo9,0);
writedata2LCD_normal(8,logo10,0);
/*
writedata2LCD_normal(8,logo11,0);
writedata2LCD_normal(8,logo12,0);
writedata2LCD_normal(8,logo13,0);
writedata2LCD_normal(8,logo14,0);
writedata2LCD_normal(8,logo15,0);
writedata2LCD_normal(8,logo16,0);
*/
}
//**************************************************************************************************
//* Prints the infineon logo - good before idle mode entry
//*
//**************************************************************************************************
void printinfineonlogo(bit direction, bit clearchar, bit displaycursor, bit clr)
{
unsigned char dummy2[1];
I2cStart();
I2cMasterWrite(LCD_device_address);
first_instruction_group();
if(clr) // clear the screen?
{
cls_LCD();
wait(for_2_ms);
}
if(displaycursor)
{
display_control_LCD(1,0,0); //hide cursor
}
texteffect(1,logo_0_0,logo_0_1,8,2+line2_start,direction,clearchar,0);
if(displaycursor)
{
//show cursor
first_instruction_group();
46 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
gotoXY_LCD(10+line3_start);
display_control_LCD(1,1,1);
}
wait (65535);
wait (65535);
if(displaycursor)
{
//hide cursor
first_instruction_group();
display_control_LCD(1,0,0);
}
// SHOW DOT ABOVE I
*dummy2=0x0A;
texteffect(0,dummy2,0,1,2+line1_start,direction,0x20,0);
if(displaycursor)
{
//show cursor again
first_instruction_group();
gotoXY_LCD(10+line3_start);
display_control_LCD(1,1,1);
}
wait2 (500);
}
'
//*********************************
// DEMONSTRATION OF LCD ROUTINES
//
// Written by Dimitrios Skraparlis
//*********************************
#include "i2c_lcd.h"
unsigned char code string_spaces[6]="
";
unsigned char code string_sample[6]="sample";
unsigned char code string_code[6]=" code ";
unsigned char code string_LCD[6]=" LCD
";
47 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
//**************************************************************************************************
//**************************************************************************************************
//
//
MAIN
//
//**************************************************************************************************
//**************************************************************************************************
void main (void)
{
unsigned int dummy0;
unsigned int dummy1;
unsigned int dummy2;
bit direction=1;
// Initialize display
// Configure bits used in the LCD driver instructions
// __________________________________________________
// Entry mode set instruction
bit ID=1;
// decrement/increment
bit S=0;
// display freeze/shift
// Display control instruction
bit D=1;
// display off/on
bit C=1;
// cursor off/on
bit Blink=0;
// blink off/on
// Cursor/display shift instruction
bit SC=0;
// cursor move / display shift
bit RL=0;
// left/right shift
// Function set instruction
/*The following are defined somewhere else in the start of this code; they are constants
bit DL // 4/8 bits (interface data length - i2c protocol is used here)
bit N
// Selects type of display
bit M
// Selects type of display
bit G
// voltage generator Vlcd=Vo / Vlcd=Vo-0.8Vdd*/
//bit Co;
// indicates data bytes / data byte+another control byte
//bit RS;
// selects instruction
//bit RW;
// selects instruction
following
// __________________________________________________
48 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
I2cInit();
/*
// ################################################################################################
// ### Start of test - instructions send to lcd, according to the example in the datasheet.
I2cStart();
//step 1
I2cMasterWrite(0x74);//01110100);
//step 2 // SLAVE ADDRESS
I2cMasterWrite(0x00);//00000000);
//step 3 // CONTROL BYTE
I2cMasterWrite(0x3E);//00111110);
//step 4 // _FUNCTION SET
I2cMasterWrite(0x0E);//00001110);
//step 5 // _DISPLAY ON/OFF CONTROL
I2cMasterWrite(0x06);//00000110);
I2cStart();
###
// * changed
//step 6 // _ENTRY MODE SET
//step 7
I2cMasterWrite(0x74);//01110100);
//step 8 // SLAVE ADDRESS
I2cMasterWrite(0x40);//01000000);
//step 9 // CONTROL BYTE
I2cMasterWrite(character_H);
I2cMasterWrite(character_E);
I2cMasterWrite(character_L);
I2cMasterWrite(character_L);
I2cMasterWrite(character_O);
I2cStop();
//(step 17)
// ### End of test
###
// ################################################################################################
*/
initialize_LCD(ID,S,D,C,Blink,SC,RL);
while(1) //loop endlessly
{
//**************
// CLEAR SCREEN
//**************
first_instruction_group();
cls_LCD();
//**********************
49 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
// CREATE INFINEON FONT
//**********************
create_font();
//*********************
// PRINT INFINEON LOGO
//*********************
printinfineonlogo(direction, dummy1, cursor, noclearscreen);
display_control_LCD(1,0,0); //hide cursor
wait2(150);
//***********************
// PRINT INFINEON LOGO 2
//***********************
first_instruction_group();
cls_LCD();
dummy1=0x5C;
dummy0=2; //loop 2 times
while(dummy0--)
{
first_instruction_group();
cls_LCD();
dummy1++;
direction=!direction;
texteffect(1,logo_0_0,logo_0_1,8,2+line1_start,direction,dummy1,0);
texteffect(0,"technologies","",12,0+line3_start,!direction,dummy1,0x80);
wait(65535);
wait(65535);
}
//*********************
// SHIFT DISPLAY
//*********************
first_instruction_group();
dummy2=20;
50 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
while(dummy2--)
{
wait(29535);
cursor_display_shift_LCD(1,1);
}
wait (65535);
wait (65535);
//*********************
// CLEAR VISIBLE AREA
//*********************
texteffect(0,"
","",12,0+line3_start,1,character_space,0);
texteffect(1,"
","
",12,0+line1_start,0,character_space,0);
wait (65535);
//**************************************
// PRINT "infineon technologies Munich"
//**************************************
texteffect(0,"infineon","",8,2+line1_start,1,character_space,0x80);
texteffect(0,"technologies","",12,0+line2_start,0,character_space,0x80);
texteffect(0,"MMI
IE SE","",10,1+line3_start,1,0x2E,0x80);
wait (65535);
wait (65535);
wait (65535);
gotoXY_LCD(line1_start+12);
writedata2LCD_normal(8,logo_0_0,0);
gotoXY_LCD(line2_start+12);
writedata2LCD_normal(8,logo_0_1,0);
gotoXY_LCD(line3_start+12);
writedata2LCD_normal(7,"Munich!",0x80);
//***************
// SHIFT DISPLAY
51 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
//***************
first_instruction_group();
dummy2=10;
while(dummy2--)
{
wait(29535);
cursor_display_shift_LCD(1,0);
}
//***********************
// ERASE SOME CHARACTERS
//***********************
gotoXY_LCD(line1_start+10);
writedata2LCD_normal(2,"
",0);
gotoXY_LCD(line2_start+10);
writedata2LCD_normal(2,"
",0);
gotoXY_LCD(line3_start+10);
writedata2LCD_normal(2,"
",0);
gotoXY_LCD(20+line1_start);
writedata2LCD_normal(2,"
",0);
gotoXY_LCD(20+line2_start);
writedata2LCD_normal(2,"
",0);
gotoXY_LCD(20+line3_start);
writedata2LCD_normal(2,"
",0);
wait (65535);
wait (65535);
wait (65535);
//**************
// CLEAR SCREEN
//**************
first_instruction_group();
cls_LCD();
//******************************
// PRINT "Industrial Design iE"
52 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
//******************************
wait(65535);
wait(65535);
wait(65535);
wait(65535);
texteffect(1,"Ü NDUSTRIAL ","E LECTRONICS",12,0+line1_start,0,0x3D,0x80);
wait(65535);
texteffect(0,"E LECTRONICS","",12,0+line3_start,1,0x3D,0);
wait(65535);
wait(65535);
wait(65535);
//*********************************************
// PRINT "infineon technologies - sample code"
//*********************************************
first_instruction_group();
cls_LCD();
texttrans("
texttrans("
",8,"infineon",8,2+line1_start,maxmuzzy,muzzystep,500,0x80);
",12,"technologies",12,0+line2_start,maxmuzzy,muzzystep,500,0x80);
wait(65535);
wait(65535);
texttrans(string_spaces,6,string_sample,6,3+line3_start,maxmuzzy,muzzystep,500,0x80);
dummy1=2;
while(dummy1--)
{
texttrans(string_sample,6,string_code,6,3+line3_start,maxmuzzy,muzzystep,500,0x80);
texttrans(string_code,6,string_sample,6,3+line3_start,maxmuzzy,muzzystep,500,0x80);
}
texttrans(string_sample,6,string_LCD,6,3+line3_start,maxmuzzy,muzzystep,500,0x80);
texttrans(string_LCD,6,string_code,6,3+line3_start,maxmuzzy,muzzystep,500,0x80);
wait2(500);
53 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
//**************************************************
// PRINT by rolling "Siemens uC applying i2C LCD control."
//**************************************************
first_instruction_group();
cls_LCD();
wait(65535);
// SECOND EFFECT
textroll("Infineon
uC",12,0+line1_start,15000,0xFF,0x80);
//wait(65535);
textroll("applying i2C",12,0+line2_start,13000,0xFF,0x80);
//wait(65535);
textroll("LCD control.",12,0+line3_start,11000,0xFF,0x80);
wait(65535);
wait(65535);
wait(65535);
} // end of LOOP
} // end of main
(The following code is the I C bus interface code, taken from the Infineon 8 bit microcontrollers’ application note AP083701.
2
/******************************************************************************* */
/*
*/
/*
SIEMENS Standard Software
/*
*/
*/
/*
Unauthorized copying prohibited
/*
*/
*/
/*============================================================================== */
/*
Programmer:
Sylvia Gusowski
*/
/*
Department:
Siemens HL CC AT
*/
/*
Revision
1.0
*/
:
/*
*/
/*============================================================================== */
/*
/*
Description:
This module is a standard I2c bus single master
prococol by using CPU time.
/*
/*
*/
*/
*/
The clock frequency is approximately 100kHz with 20 MHz CPU clock
*/
/*
and 300 ns for a one-cycle instruction. The timing of the clock pulses
*/
/*
are controlled by using NOPs.
*/
54 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
/*
*/
/*
Subroutines can be called from main program: I2cInit, I2cStart,
*/
/*
I2cMasterWrite, I2cMasterRead, I2cStop.
*/
/*
*/
/*
Requirement: In application program, the include files called
*/
/*
I2C_SW8b.H and I2C_8b.DEF must be attached to the program. In the
*/
/*
I2C.DEF file, the variable SDA and SCL must be declared as any
*/
/*
two of the I/O pins.
*/
/*
/*
*/
In case there is a fault on the bus, for instance, the SDA line is
*/
/*
shorted to ground or pulled down to LOW by the slave device. This
*/
/*
module will generate clock pulses until the line is released and the
*/
/*
time-out is 10 ms before returing a "HIGH" value from the I2cInit or
*/
/*
I2cStop. For SCL line, it will monitor until the line is released and
*/
/*
the time-out is 10 ms. The return value of I2cInit or I2cStop will be
*/
/*
checked in the main program to take an appropriate action.
/*
*/
*/
/*
Input and output parameters of those subroutines:
*/
/*
(1) I2cInit: no input
*/
/*
output = "0" - no error, "1" - error
/*
/*
*/
(2) I2cStart: no input, no output
*/
/*
/*
*/
(3) I2cMasterWrite: input = one byte of data to be sent to slave
/*
device.
/*
*/
(0 - received, 1 - not received)
/*
(4) I2cMasterRead: input = "1"/"0" of acknowledge bit to slave device
(send on 9th clock pulse of data received)
/*
output = A byte of data from slave device.
/*
/*
*/
*/
/*
/*
*/
*/
output = acknowledge bit.
/*
/*
*/
*/
*/
*/
*/
(5) I2cStop: no input
*/
output = "0" - no error, "1" - error
/*
*/
*/
/*============================================================================== */
/*
/*
History:
*/
05/02/99: Start of the module
*/
/*
*/
/******************************************************************************* */
#include <reg51.h>
#include <intrins.h>
55 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
#include "i2c_8b.def"
#define NOP _nop_();
#define Delay1 NOP
#define Delay16 { NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP}
#define period 2900
/* approximately 10 ms time out for bus faulty */
unsigned int time_out;
void CheckClock();
unsigned char Check_SCL();
unsigned char I2cInit();
void I2cStart();
unsigned char I2cMasterWrite(unsigned char input_byte);
unsigned char I2cMasterRead(unsigned char ack);
unsigned char I2cStop();
/******************************************************************************* */
/*
Subroutine:
CheckClock
*/
/*
/*
*/
Description:
Send HIGH and read the SCL line. It will wait until
*/
/*
the line has been released from slave device for
*/
/*
every bit of data to be sent or received.
*/
/*
/*
*/
Input:
None
*/
/*
/*
*/
Return:
None
*/
/*
*/
/******************************************************************************* */
void CheckClock()
{
while (!SCL)
/* check for wait state before sending or */
/* receiving any data. */
SCL = 1;
}
56 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
/******************************************************************************* */
/*
Subroutine:
Check_SCL
*/
Description:
Send HIGH and read the SCL line. It will wait until
*/
/*
/*
*/
/*
the line has been released from slave device with the
*/
/*
time out of approximately 10 ms (20 MHz CPU and 300 ns
*/
/*
for a one-cycle instruction).
/*
*/
*/
/*
Input:
None
*/
/*
*/
/*
Return:
/*
"0" - SCL line is OK
"1" - SCL line is faulty
*/
*/
/*
*/
/******************************************************************************* */
unsigned char Check_SCL()
{
time_out = period;
while (time_out--)
{
if (!SCL)
/* wait if SCL is pulled down to LOW by slave device */
{
SCL = 1;
/* set clock to high */
return (0);
}
}
return (1);
/* ERROR: SCL line is stuck to low */
}
57 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
/******************************************************************************* */
/*
Subroutine:
I2cInit
*/
Description:
Initialize the I2C bus
*/
/*
/*
*/
/*
/*
*/
Input:
None
*/
/*
/*
*/
Return:
/*
"0" - bus line is OK
"1" - bus line is faulty
*/
*/
/*
*/
/******************************************************************************* */
unsigned char I2cInit()
{
if (!SDA)
/* if lines are low, set them to high */
if (I2cStop())
return (1);
if (!SCL)
if (I2cStop())
return (1);
return (0);
}
/******************************************************************************* */
/*
Subroutine:
I2cStart
*/
Description:
Generate a START condition on I2C bus
*/
/*
/*
*/
/*
/*
*/
Input:
None
*/
/*
/*
*/
Return:
None
*/
/*
*/
/******************************************************************************* */
void I2cStart()
{
58 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
SDA = 1;
/* to make sure the SDA and SCL are both high */
SCL = 1;
Delay16;
SDA = 0;
/* SDA line go LOW first */
Delay16;
SCL = 0;
/* then followed by SCL line with time delay */
}
/******************************************************************************* */
/*
Subroutine:
I2cMasterWrite
*/
Description:
Output one byte of data to slave device. Check for
*/
/*
/*
*/
/*
WAIT condition before every bit is sent.
/*
*/
*/
/*
Input:
one byte of data to be sent to slave device.
/*
*/
*/
/*
Return:
/*
acknowledgement from slave:
0 = acknowledge is received
/*
1 = no acknowledge is received
/*
*/
*/
*/
*/
/******************************************************************************* */
unsigned char I2cMasterWrite(unsigned char input_byte)
{
unsigned char mask,i;
mask = 0x80;
for (i=0; i<8; i++)
/* send one byte of data */
{
if (mask & input_byte)
/* send bit according to data */
SDA = 1;
else SDA = 0;
mask = mask >> 1;
/* shift right for the next bit */
59 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
Delay1;
CheckClock();
/* check SCL line */
Delay16;
SCL = 0;
/* clock is low */
Delay16;
}
SDA = 1;
/* release SDA line*/
Delay1;
SCL = 1;
/* generate 9th clock pulse */
Delay16;
mask = SDA;
SCL = 0;
/* read acknowledge */
/* clock is low */
Delay16;
/* to avoid short pulse transition on SDA line */
return (mask);
/* return acknowledge bit */
}
/******************************************************************************* */
/*
Subroutine:
I2cMasterRead
*/
/*
/*
*/
Description:
/*
Read one byte of data from the slave device. Check
for WAIT condition before every bit is received.
/*
/*
*/
*/
*/
Input:
Acknowledge require:
*/
/*
0 - generate LOW output after a byte is received
*/
/*
1 - generate HIGH output after a byte is received
*/
/*
/*
*/
Return:
received one byte of data from slave device
*/
/*
*/
/*
*/
/******************************************************************************* */
60 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
unsigned char I2cMasterRead(unsigned char ack)
{
unsigned char mask,i,rec_data;
rec_data = 0;
mask = 0x80;
for (i=0; i<8; i++)
{
CheckClock();
if (SDA)
/* clock is high */
/* read data while clock is high */
rec_data |= mask;
mask = mask >> 1;
SCL = 0;
/* clock is low */
Delay16;
}
if (ack)
SDA = 1;
/* set SDA data first before port direction */
/* send acknowledge */
else SDA = 0;
Delay1;
SCL = 1;
/* clock is high */
Delay16;
SCL = 0;
/* clock is low */
SDA = 1;
Delay16;
/* to avoid short pulse transition on SDA line */
return (rec_data);
}
61 of 62
AP2427 Rel. 01
8VLQJDQ,&/&'5HIHUHQFHFRGHDQGDSSOLFDWLRQV
LQFOXGLQJYLVXDOHIIHFWV
/******************************************************************************* */
/*
Subroutine:
I2cStop
*/
Description:
generate stop condition on the I2C bus
*/
/*
/*
*/
/*
*/
/*
Input:
none
*/
/*
*/
/*
Return:
"0" - the bus line is OK
/*
*/
"1" - the bus line has been pulled down to low
/*
*/
*/
/******************************************************************************* */
unsigned char I2cStop()
{
time_out = period;
while (time_out --)
{
if (!SDA)
/* check SDA line */
{
SCL = 1;
Delay16;
/* generate a clock pulse if SDA is pull */
/* down to low */
SCL = 0;
Delay16;
}
else
/* check SCL line */
{
SDA
= 0;
Delay1;
if (Check_SCL())
return (1);
/* to generate STOP condition */
/* ERROR: SCL line is stuck to low */
Delay16;
SDA = 1;
Delay16;
return (0);
}
}
return (1);
/* ERROR: SDA line is stuck to low */
}
62 of 62
AP2427 Rel. 01