18 Series - Chapter 16 - Graphic LCD
The graphic display is a useful component in a project as it can display a lot more than just text. These types of LCD's are also known as transflective, they can only display one colour (monochrome) and are relatively slow, fast refresh rates are really not possible. In this chapter I will show how this type of display works, how to initialise and write data to it. Further in this chapter I will show how to display images from an SD card for example or how images can be stored on the microcontroller itself.
Below is the graphic display I will be choosing to use, it has 128 x 64 pixels.
Like with the character LCD there is a maximum number of characters that can be displayed, so for example with the HD44780 controller there was a maximum of 80 characters. One of my other projects contains a 4x40 display, 160 characters total, to achieve this it simply uses two controllers tied together, the only pins not tied are the enable pins. So one display is really split into two separate displays, this is the same with a graphic LCD.
The graphic LCD uses either the KS0108 or the NT7108 controller, they do the same thing so it doesn't really matter which one you get. The NT7108 is limited to a maximum of 4096 pixels or 64 x 64 (of course it could be 128 x 32, etc...). Since we need double this amount of pixels it is natural that we will need two controllers tied together, one controls the left side of the display and the other controls the right. These are normally known as "chip select 1" and "chip select 2", there will be two separate pins on the display that enable each of the chips additional to the enable pin which accepts the input data.
Since I'm dealing with two separate displays I will discuss how to control just one for now as they are both equal. The display is split up into columns and rows, or Y and X which is referred to in some datasheets. I honestly do not know who came up with this arrangement as "X" should be horizontal and "Y" should be vertical. For this chapter and how it should be correctly referred is that "Y" is the x-axis, the columns and that "X" is the y-axis, the rows and should be referred to as a page, each page is eight lines in length, so a total of eight pages (pages 0 to 7).
In most datasheets it is stated as "X - Pages" and "Y - Address" which is the columns. Since the 64 bits have been divided up into eight pages it means that each one is 8-bits high. There are eight data lines going into the LCD, DB0 - DB7, each one of these corresponds to a pixel. When starting at the beginning of the display each 8-bit piece of data will increment the "Y" address, when 64 pieces of data have been sent it will begin at "Y0" again, you have to instruct the display to jump to the next line / page. One last thing to note is there is a "Z" which is a value ranging from 0 to 63, this is an offset of the pages or the "X" address.
The commands are pretty straight forward but you will notice that it does differ greatly from a character display. The most simple command is to turn the display on or off, the purpose of this is to save power, it should be noted however that the back light draws the most current and this is not controlled by the LCD. The X and Y addresses are pretty easy to understand, note that the display will not shift characters and will only overwrite them. The display start line will offset the pages, it is best to leave as zero however it is an easy way to scroll the display. The Ram read is rarely implemented however the status read is used to check when more data can be received, this can also be done on the character LCD, I chose delays instead in that instance.
The pinout for my LCD is as follows, there are a few differences compared to the character LCD. Firstly the contrast requires a negative voltage however the LCD itself on pin 18 will provide a negative 5V, quite simply a potentiometer is placed between +V and pin 18, the center tap goes to contrast, always check the datasheet to confirm this. CS1 and CS2 will enable the left or right side of the display, enabling is active low, be careful as I have a similar display that is active high. The reset is not a command and has it's own dedicated pin, this is pulled high for normal operation and low to reset the display, resetting the display will turn it off and reset the page address, it does not clear RAM. R/W this time is used mainly to read the status of whether the display is ready to receive more data or not. RS, E and DB0-7 have the same functions as the character LCD. One final note is the backlight LED, since the display is smaller it only requires about 50mA of current, a resistor of around 30 ohm needs to be chosen.
I have found that dealing with a graphic display is a lot easier to get right the first time as there's no special initialisation procedures like that for the character LCD, like getting it into 4-bit mode (graphic displays do not have 4-bit mode).
Since the enable is required to be on / off for a minimum time of 450ns it would probably be best to round this up to between 600ns to 1us.
The clock frequency of the display itself is around 250kHz which means that data cannot be sent to the display any faster, around half of this.
One thing you have to remember with these graphic LCD's is that they have to write 8-bits at a time, since we are talking 128 x 64 pixels that would take 1024 bytes of data or just 10ms for the LCD to be written. If however you need less time to write just a single fraction of the LCD then simply an address can be chosen and the RAM over-written at that location, this can save huge amounts of time.
One more thing to note is the maximum refresh rate is only around 5Hz due to the response time of the crystals.
The chip I'm choosing to use for this chapter is what is known as a 18F24K40 which is one of the more advanced chips from the 18 series, so much so that the Pickit2 will be unable to program it, I have to use the Pickit3. Don't worry however as the program will mostly be the same, the difference is the inputs and outputs which you will choose to suit your own application. Just for ease I will be taking the program examples from one of my own projects. The particular display I'm using will have an active high chip / controller select, it's pinout will be much the same as above and the supply voltage is 5V.
The first section of program will load the data outputs lines, it will also allow the user to invert the data, this is so that pixels can be inverted. The first step is to clear all of the data bus output lines, for me all of the data is PortB so I can just clear the latch, if however they are different then you will have to clear them all separately. Our data is contained in the working register, each bit is tested to see whether the data line has to be risen or not. This program will be used as a subroutine, it is call every time data has to be presented to the data bus.
Another important section of program as below will pulse the enable pin, the enable pin tells the display to either receive data or to output data depending whether it is in read or write mode. Since the current microcontroller for this project is running at 64MHz and the display is running far slower it means that I must implement some delays.
The initialisation of the display is probably as easy as it gets. On power up the display must be held in reset for a small period of time, it is normally on the order of a few milliseconds but I tend to choose something a little longer to allow the power supply to settle, I have chosen 250ms. Each side of the display needs to be selected individually, a command sent to switch the display on and lastly the start line set, that's it. It is normally then a good idea to call up a subroutine that clears the display as the RAM within will contain random values, a white noise appearance on the display.
Again it is rather easy to clear the display, each side of the display has to be dealt with separately. The below program will clear the right side of the display, it has to be repeated again with the left. All the program does is tell the display to start at page zero, at the beginning and then receive blank data to clear the page, the process is repeated until all pages are clear.
The image to display will be taken from the inside program memory of the chip, I could use an SD card but it is not necessary. The first thing you will need is an image, it must be 128 x 64 pixels and be saved as a monochrome bitmap. There are many software's on the net that will convert a bitmap to hex data, here is the one that I have chosen to use, the image will be used for my chronograph project.
It will convert the image to a hex table, each section of data is the top two pages of data. When I copy this data I tend to split it into two half's, taking the first four lines from each section to be used for the left side of the display and the remaining four lines from each section for the right side of the display.
For MPLab to be able to recognise the data it must be presented in the following format.
The part I like about the 18 series is that the data anywhere in the memory can be read easily, to read this image we must load the table pointer with it's address, as in the following section of program.
To display the image it is much like that when I cleared the display, the difference this time is that instead of loading clear data it is taken from the table pointer instead, a subroutine is called that retrieves data from the table and increments the pointer.
You should be able to read in between the lines in how to implement this into your own project. I will not post the code as it may be best to look up my chronograph project and see what I have done there. The last thing I will say here is that it is not necessary to read the status of the display, the time I have used in the enable pulse has compensated for the time it takes for the display to accept data. It is of course possible to use the status read as I have already in one of my previous GPS projects, in reality however it saved very little time.
Here are a few examples of the display from my chronograph project, on the left is the image I used earlier and on the right shows an example of why I may choose to invert the data to my display, it creates a contrast.
Hello, if you have enjoyed reading this project, have taken an interest in another or want me to progress one further then please consider donating or even sponsoring a small amount every month, for more information on why you may like to help me out then follow the sponsor link to the left. Otherwise you can donate any amount with the link below, thank you!