It seems that quite a number of people are interested in using the LCD, and I am not very busy these days. I would start a new thread to share some experience in using these LCD, step by step from the very beginning (actually I am a beginner!)

I am sorry to type in English as I am very clumsy in typing Chinese (速成 only).

TOP

Controlling LCD with a Microcontroller

LCD categories (part 1)

There are basically two types of LCD. One type is CPU-peripheral-like interface and the other is Video-like interface. The CPU-peripheral-like interface LCD is easier to be controlled by a microcontrollers (or the LPT), because it has build in controller which accept commands and data from the interface. What we need is to connect the LCD to the I/O port of a microcontroller (or LPT) and the program in the microcontroller sends the commands and data to the LCD, that is.

The standard 16x2 character LCD, 128x64, 240x128 are of this type. The controller in 16x2 LCD is usually HD44780 (or compatible), one example is here:

http://www.beyondlogic.org/parlcd/parlcd.htm

For graphical LCD, some standard controllers are KS0107/KS0108, T6963, KS0713 etc. The command set and control sequence are different for different LCD controller IC. So when you are going to buy a LCD, make sure you know the LCD controller IC, and the pinout, it makes your life much easier.

I will use the LCD mentioned in “電容專家有 18pin 的 lcd 仔買” as an example, but the general principles are applicable to all CPU-peripheral-like interface. As I know there is a thread discussing how to control the LCD with PC software such as LCDStudio. I will share experience in controlling the LCD with microcontroller. The platform is

18pin LCD (132x64) with KS0713 controller
8051 architecture uC (such as S51, S52, DS89C430/DS89C450 etc.)
Software in Keil C.

To be continued…

TOP

Hardware connections and LCD controlling method (part 2):

I use port P1 for the data bus (D0-D7), other pin definitions are as follows:

/* Hardware */
#define LCD_DATA        P1
sbit LCD_WR         = P2^0;             // write data (active LOW)
sbit LCD_RD          = P2^1;            // read data (active LOW)
sbit LCD_CS         = P2^2;             // chip select (active LOW)
sbit LCD_RS         = P2^3;             // command/data selection: 0=command, 1=data (A0)
sbit LCD_RST        = P2^4;            // reset (active LOW)


LCD controlling method

To control a LCD, we must have the datasheet as it consists of the following key information:
Command set
Read/Write timing sequence
Other AC/DC characteristics

KS0713’s datasheet can be found here:

http://www.ortodoxism.ro/datashe ... tronic/mXyzvqzy.pdf

If you are going to write your own driver, you must read the datasheet. Even if you obtain the driver code from the Internet (I always do it!), you have to refer to the datasheet and tailor the code for your own projects.

Normally, we need three key functions:
To write a command to the LCD
To write a data to the LCD
To initialize the LCD

And some other supporting functions, for example clearing the screen, moving the cursor to a specific location, displaying a character, a string, a bitmap etc.


to be continued...

TOP

Writing command to the LCD (part 3)

To control the LCD, the controller IC defined a set of command (from datasheet), such as to turn of the display, set the cursor on/off etc.

The function is actually very simple, but you must read the timing sequence (from datasheet) very carefully to meet the setup time, hold time, requirements, etc. For slow uC (e.g. standard 11.0592Mhz 89C52), the requirements may be met easily. For high speed uC like DS89C450, some delay needed to be calculated/adjusted.

void lcdWriteCommand(unsigned char c) {
LCD_DATA = c;             // place data
LCD_RS = 0;                 // write command when RS (register select = 0)
LCD_RD = 1;        // write operation when (WR = 0 and RD = 1)
LCD_WR = 0;
LCD_CS = 0;                // enable chip by setting CS (chip select = 0)
_nop_();_nop_();_nop_();         // wait for a bit, depends on the timing requirement
_nop_();_nop_();_nop_();
LCD_CS = 1;        // disable chip select
LCD_WR = 1;        // pull WR to high to finish the write cycle
lcdDelay(10);        // some delay, sometimes can be omitted
}

// just a time delay loop, you may need to fix the datatype ulong for your case
void lcdDelay(ulong u32Duration)
{
        ulong u32Delay;
        for (u32Delay=0; u32Delay<u32Duration; u32Delay++);
}

to be continued...

TOP

Writing data to the LCD (part 4)

Sending data to LCD is similar to sending command. Some commands may have optional data to be sent and the graphical data is sent as data.

void lcdWriteData(uchar d) {
LCD_DATA = d;          // place data on the bus
LCD_RS = 1;                 // write data when RS (register select = 1)
LCD_RD = 1;        // write operation
LCD_WR = 0;
LCD_CS = 0;                 // enable chip
_nop_();_nop_();_nop_();     // wait, depends on timing requirement
_nop_();_nop_();_nop_();
LCD_CS = 1;
LCD_WR = 1;
lcdDelay(10);
}

to be continued...

TOP

A new thread sharing experience in controlling LCD with a Microcontroller


http://www.hkepc.com/bbs/viewthr ... &extra=page%3D1

TOP

Initializing the LCD (part 5)

Once we have the two functions to write command and data to the LCD. The next key one is to initialize the LCD. Each LCD controller IC defines its own initialization sequence and the default status after LCD RESET, these information are all specified in the datasheet. The initialization sequence usually involves:
Waiting for the power to become stable
Resetting the LCD
Setting the display options, configurations (You need not to set all of them as some are default settings after reset, but I usually set all of them explicitly to avoid confusion.)
Turning ON the display
Clearing the screen (as you wish!)

For more details on each settings, you can refer to the datasheet, but the followings are rather generic.

/*
        LCD Initialization
        lcdInit()
*/
void lcdInit(void)        
{
lcdDelay(100);                // wait for power to become stable
LCD_CS = 0;          // chip enable
LCD_RST = 0;                // send a Active LOW pulse to reset
_nop_();_nop_();_nop_();        // delay, depends on timing requirement
_nop_();_nop_();_nop_();
lcdDelay(100);                    // wait for power stable
LCD_RST = 1;
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();

lcdWriteCommand(0xA6);         // Normal Display
lcdWriteCommand(0xA0);   // ADC normal

lcdWriteCommand(0x2F);   // Power Control 111
lcdWriteCommand(0xC8);   // Common Output Mode select (reversed)
lcdWriteCommand(0xA3);   // LCD Bias (1=1/9 for ks0713)

lcdWriteCommand(0xAC);  // Static Inidcator OFF (double byte command)
lcdWriteCommand(0x00);   // Static Inidcator OFF

lcdWriteCommand(0x23);    // V5 Ra, Rb ratio (0x20-0x27)
lcdWriteCommand(0xEE);    // Read-Write-Modify OFF

lcdWriteCommand(0x40);    // start line = 0
lcdWriteCommand(0xB0);    // page = 0

lcdWriteCommand(0x10);     // Column = 0 (MSB) (double byte command)
lcdWriteCommand(0x00);         //                (LSB)

lcdWriteCommand(0x81);    // Electronic Volume Set (double byte command)
lcdWriteCommand(0x11);    // Electronic Volume Register (0x00-0x3F)

lcdWriteCommand(0xAF);    // set display ON

lcdClear();
}

Remarks: I changed back the value of LCD bias to A3 to match the KS0713 datasheet. (Originally, I set it as A2 as I based on ST7565 datasheet which has A2=1/9)

to be continued...

[ 本帖最後由 ktktkt 於 2007-7-16 10:23 編輯 ]

TOP

Clearing the screen (part 6)

Clearing the screen is simply sending 0x00 to the whole screen.
The LCD display is arranged as 132 columns x 8 pages, you can treat a ‘page’ as a row of height 8 pixels.

void lcdClear() {
uint i, j;
lcdWriteCommand(0xB0);        // set page = 0 (i.e. row 0)
for (i=0;i<8;i++) {
lcdWriteCommand(0xB0 | i);        // set page = i (i.e. row i)
lcdWriteCommand(0x10);         // set column = 0 (MSB) (double byte command)
lcdWriteCommand(0x00);         //                   (LSB)
for (j=0;j<132;j++) {
lcdWriteData(0x00);                // write the data 0x00, auto increment column
}
}
}

to be continued...

TOP

Displaying a test pattern on the screen (part 7)

OK, we can now test the LCD with a test pattern!

void main(void) {
uint i,j;

delay_ms(100);                // some delay to wait for power to become stable
lcdInit();                        // initialize the LCD
lcdClear();                        // clear the screen

while (1) {

delay_ms(2000);
lcdClear();

// display a test pattern
lcdWriteCommand(0xB0);          // page = 0
for (i=0;i<8;i++) {
lcdWriteCommand(0xB0 | i);   // page i
lcdWriteCommand(0x10);      // Column = 0 (MSB)
lcdWriteCommand(0x00);      //              (LSB)

for (j=0;j<132;j++) {
  if ((i % 2) == 0)
    lcdWriteData(0xFF);
  else
    lcdWriteData(0x00);
  }
}
}
}

That is!

TOP

Setting the pointer location (part 8)

/*
        X (0-131), Y (0-7)
        Note: X, Y here are screen coordinate (X is page, Y is column)
*/
void lcdGotoXY(uchar x, uchar y) {
lcdWriteCommand(0xB0 | y);                // page = y
lcdWriteCommand(0x10 | ((x & 0xF0) >> 4));        // Column = 0 (MSB)
lcdWriteCommand(x & 0x0F);        //                           (LSB)
}


Finished! I hope you would enjoy!

TOP