I’m involved into developing a little instrument to display graphs and numerical values with characters of various sizes. I’m pretty expert with the classic controller standard “HD44780” for alphanumeric LCDs.  But this time I need something more flexible such as a graphic LCD, with the possibility of freely control every pixel of the screen. If you are interested in the topic I really recommend to thoroughly understand the operating logic, so you can freely create high-performance graphics to suit your needs… and also obviously having fun with tech stuff!

When you choose the correct device for you application, you must consider:

  • connector type
  • controller chip
  • dimensions in pixels
  • retroillumination color
  • LCD contrast regulation voltage

To briefly summarize these parameters, I chose a product that have connector holes spaced with 2.54mm as standard connectors, so I can easily pay off the cables / connectors, and make everything as flexible as a first prototype needs.

I chose the KS0108 controller; because looking online I found a lot of documentation and datasheet about it, so, i guess also a lot of support if in need.

king about the pixel size, my choice fell on the 128×64, which is internally divided into two separate controllers but with the same connections: by sending the information to the first controller i will work on the 64×64 pixels box at the top, while the second controller works on the bottom 64x64px box. For example, if i had purchased a 192×64 pixels, i would find three separate controllers. In fact the management is easier than you think, you will see below.

I will not use the backlight because I have to keep the consumption very low, but if you need it, in the datasheet the white backlight consumes much less compared to other colors (however life in hours seems less!): To be considered.

As a final point, speaking about the contrast adjustment voltage, some LCDs require a negative voltage: this becomes a problem because it’s not so easy to get a negative voltage with a prototype board if you do not have the necessary components available, thus not seems appropriate to engage a bench supply just to obtain the negative voltage in question. The model I have chose, despite this characteristic, is equipped with an internal DC / DC converter to provide the negative voltage required, simply connecting it to a contrast trimmer and then to the contrast pin… and that’s it! … Anyhow I had some trouble with the contrast because I found out, after a tedious and meticulous research that the reset pin needs to be connected to VCC through a 10kohm pull-up resistor at least, to limit the current. Initially I was driving the LCD with RST pin directly connected to VCC and this was cause of an “unstable contrast” issue.

With the availability of different FRDM_KL25Z boards I used as a programmer for ARM micro, I decided to exploit one to drive the graphic display in question. As explained in this article KL25Z as an OpenSDA programmer I first of all prepared the board so that it can be easily programmed via USB (with the J6 jumper inserted to connect the SDA clock with the clock of the onboard micro!).

Before connecting the LCD to the board I checked into their details if they are all freely controllable with digital I/O:

  • CS1, CS2: to enable controller 1 or controller 2, the two half of the screen;
  • DB0-DB7: pins enabled to describe the 8 bits of a byte sent to the l’LCD;
  • EN: enable pin, needs to be enabled to inform the controller to receive commands or data;
  • RW/DI: to set the communication mode (reading, writing, command);
  • RST: reset pin, needs to be high level (5v) to enable the LCD controllers;
  • Vee: LCD contrast, need to be connected to Vo through a trimmer, see below;
  • Vo: Voltage ouput from the internal DC/DC converter.

Then I have connected the LCD to the board checking the KL25z micro datasheet if some pins are open drain/collector (in that case to obtain a high logic level is necessary to add a pull-up resistor) or, as in the case of pin “PTD1” being in common with the RGB LED mounted on the board … I would avoid these mistakes if possible.

Graphical LCD pin diagram

In this scheme you can see all the necessary connections, but keep in mind the pullup resistor on the RST pin. I recommend: first of all make sure that your Vcc voltage does not exceed the limits specified by the LCD datasheet, and then double check if you have properly connected all the pins, otherwise you risk to irreparably compromise the LCD! At this point I just have to write down some code! Without going into specific detail of CodeWarrior with ProcessorExpert and arm-gcc compiler, I will explain how to properly communicate with the KS0108 controller so you will be able to use it regardless of the language, compiler or mcu used.

First of all the controllers need to be initialized, and to do that we must send to each one some commands. Now we will see some code to communicate with the LCD.

In my case, using CodeWarrior, i’ve configured every pin in ProcessorExpert directing them as shown in the diagram above, and then writing two functions to set them as outputs and manage the logic levels of the single bits as needed.

// this function sets every pin from D0 to D7 as outputs
void DATA_DIR_OUT() {
	LCD_D0_SetOutput();
	LCD_D1_SetOutput();
	LCD_D2_SetOutput();
	LCD_D3_SetOutput();
	LCD_D4_SetOutput();
	LCD_D5_SetOutput();
	LCD_D6_SetOutput();
	LCD_D7_SetOutput();
}

// this function sets every output data pin with 
// the respective bit of the byte that we want to sent
void WR_DATA(char lcddata) {
	
	LCD_D0_PutVal((lcddata) >> 1);
	LCD_D1_PutVal((lcddata >> 1) & 1);
	LCD_D2_PutVal((lcddata >> 2) & 1);
	LCD_D3_PutVal((lcddata >> 3) & 1);
	LCD_D4_PutVal((lcddata >> 4) & 1);
	LCD_D5_PutVal((lcddata >> 5) & 1);
	LCD_D6_PutVal((lcddata >> 6) & 1);
	LCD_D7_PutVal((lcddata >> 7) & 1);
}

// send simply a little pulse through the EN pin
void send_enable() {
	LCD_EN_SetVal();
	Delay100us(1); // delay di 1 microsecondo
	LCD_EN_ClrVal();
}

// controller selection (0-1)
//    0               1
// CS1 = 1         CS1 = 0
// CS2 = 0         CS2 = 0
void ChipSelect(bool chip)
{   
      if (chip == 0)
      {
            LCD_CS2_ClrVal();
            LCD_CS1_SetVal();
      }
      if (chip == 1)
      {
            LCD_CS1_ClrVal();
            LCD_CS2_SetVal();
      }
}

glcd output bitsThe result is to transmit the byte bit by bit distributing it on pins DB0-DB7. This is called normally parallel transmission. In addition to transmitting the bits we need also to tell the controller what type of operation we are doing. Leafing through the datasheet of the LCD I found all the information needed to drive the controller.

control bits e data bits
I removed from this pattern all the other functions, to show only the interesting ones: “Display on/off” to initialize the LCD and “Write data” to send a byte. I have also divided the first row by the color of the data bits and the control bits, respecting the colors of the wiring diagram. The “EN” enable pin is missing, because the latter is very simple: first you prepare the check bits and the data bits, then a small pulse through the EN bit, to say to the LCD “ok I’m ready, listen to me”.

In summary, to activate the display must be set the RW pin to 0, the DI pin to 0, and next thing, send the BYTE “3F” followed by an ENABLE pulse:

void InitDisplay(void)
{
	DATA_DIR_OUT();
	LCD_DI_ClrVal();
	LCD_RW_ClrVal();
	WR_DATA(0x3F);
        ChipSelect(0);
}

Now, if we want to turn on a pixel on the screen, it would be enough to send one byte of data. But a moment … one byte? And if I want to light up a single bit? Right, but we’ll talk about later. The question now is: where would appear this pixel? We have not created any function to set the “cursor” position. Let us return then to the datasheet and then add some detail to the functions table:

ks0108 goto xy istructions

So we have a command called set page that corresponds to the X axis, and a set address command that corresponds to the Y axis. Both seem to work with RW and DI to zero. Differently, set address is 0 to 63 while set page only goes from 0 to 7 (including zero, then only 8 positions). This is because on the X axis we write 8 bits at a time, our byte! Obviously, in this way we do not need 64 positions, but 64/8 or 8.

Now we can see our position functions and write function for a byte:

// Page select (x axis divided by eight positions for 8 bit blocks)
void PageSelect(unsigned char page)
{
        // RW e DI like suggested by table
	LCD_RW_ClrVal();
	LCD_DI_ClrVal();
        // joining "B8" or 10111 like suggested by table
        // with the 3 bits of the page number (0 to 7)
	WR_DATA(0xB8 | page);
	send_enable();
}

// row select (y axis divided by 64 positions for single bits)
void RowSelect(unsigned char row)
{
        // RW e DI like suggested by table
	LCD_RW_ClrVal();
	LCD_DI_ClrVal();
	WR_DATA(0x40 | row);
	send_enable();
}

Done that, whe need only to send a first byte to the screen, at the 0,0px position, simply changing the main.c file:

InitDisplay(void);  // LCD initialization
ChipSelect(0);      // obviously chip 0 selection
PageSelect(0);      // x = 0
RowSelect(0);       // y = 0
WriteByte(0xFF);    // lighting up 8 pixel 
while(1);           // infinite waiting loop

If you did everything correctly, you’ll see a 8px line. Changing 0xFF with for example 0x01 will switch on only one pixel, while 0xAA will show alternating pixels. You can also try changing the values of PageSelect and RowSelect, to see what effect does on the pixel positions.

glcd byte sent

From this initial result you can start to develop all graphics functions such as writing characters or displaying bitmap images, but I will talk about this in the next article!

Turn the freedom board KL25Z in a USBDM Debugger interface allows to program various Freescale MCU and other compatible ones (look here):

  • RS08
  • HCS08,
  • HC12,
  • Coldfire V1-4 microcontrollers
  • MC56F800xx Digital Signal Controllers (very limited range of devices).
  • Kinetis ARM-cortex

First of all it is necessary to prepare the hardware as shown in the previous article regarding the KL25Z as an OpenSDA programmer using the P&E Micro firmware (vedi qui). Prepare the board with the necessary hardware changes, but do not load the OpenSDA firmware, follow instead these steps:

Download the USBDM driver at this link:

opensda

Then, when the driver is installed, open this link (check for the last version) for the USBDM software:

download programs
Start the setup and during the procedure be sure to enable the installation of the components related to your development environment (in my case Codewarrior 10.6.4), and also the programmer Stand-alone, as I prefer simplicity, or as a plan B in case the development environment is not able to integrate the required plug-ins:

setup

When the setup is completed you just have to prepare your FRDM-KL25Z to proceed with the USBDM firmware update. Browse the default folder for installed software on your PC, you will findPGOand inside this folder the USBDM application one: inside this folder i will find “FlashImages” folder and then MKxx” referring to the micro board in the family. On my computer the full path is “C: \ Program Files (x86)\ pgo\USBDM 4.12.1.70\FlashImages\MKxx”.

Within this folder, we find the “OpenSDAvX.X.bin” file where X stands for the version available at the time. Keep this file handy!

usbdm flash application

It’s now time to connect the board to the computer with a USB cable, hold down the reset button a second or two, this will boot into bootloader mode and will appear as a USB mass storage device (Bootloader). If you have activated the internet, opening “sda_info.htm” file you can check the bootloader versions currently loaded in the flash app. However, we’re going to upgrade everything, to transform the board into a programmer “semi-universal” via SWD.

20160426_152446

So you just need to upload the file “OpenSDAvX.X.bin” in the mass storage device, wait a few seconds, then power cycle the device. At this point, as a confirmation of the successful firmware update, Windows will warn you that “new hardware is found and USBDM drivers will be automatically (probably) loaded, and the device will be recognized as a programmer from CodeWarrior and the stand-alone flash programmer.

Be careful: with Windows 7 and Windows 10 for still unknown reasons this process failed to update the firmware of the board as last step, however, I had here a computer with Windows XP and in that case it worked immediately. This step must be done only once, so I did not study in deep this strange problem.

To check if everything is working fine, you can connect the SWD connector to the target device, plug the board to the usb port and start the stand-alone flash programmer (with my setup in “C:\Program Files (x86)\pgo\USBDM 4.12.1.70\UsbdmFlashProgrammer.exe”):

stand alone usbdm flash programmer test

First of all, in the “Interface” tab via the “Detect” button I checked for a proper recognition of the KL25Z board detected as a SWD programmer. Next step, in the “Target” tab (rightmost image) using the “Detect Chip” function I do a quick check of the device that I have connected via SWD, in this example it is properly recognized as ID and correctly selected from the devices list.

However, initially it was not so simple, because the micro “MKV10” was not recognized, being present in the list but not fully configured. I tried to configure it manually by entering all parameters as per datasheet, but without success. I decided to contact the developer of USBDM, Peter O’Donoghue, who was by chance facing the same problem: so in less than 24 hours we have solved and now it works perfectly! Surely, with older micro or simply with more luck you will not have my same problem.

Stay tuned!

You can find more info at this link:
https://mcuoneclipse.com/2013/04/27/debug-external-processors-with-usbdm-and-freedom-board/