728x90

728x90

Thursday, January 29, 2026

ATMega644P Graphical LCD Interfacing

Interfacing a graphical LCD to a micro-controller is an interesting stuff beyond a character LCD or a LED matrix display. Most of graphical LCD has a built-in controller for example a well known KS0108 controller chip had been widely used for many years. A monochrome graphical LCD has various size and resolutions, 128x32, 128x64, 128x128, 128x160 and 240x128 etc.

TG12864A-04A 128x32 Dot-matrix and ATMega644P Interfacing 

 

ATMega644P Graphical LCD Interfacing
TG12864A-04A and ATMega644P Interfacing 

I bought an old graphical LCD TG12864A-04A that is a 128x32 dot-matrix display with its controller chips  SBN0064G (64-row x 64-column). So this 128x32 dot-matrix LCD needs two SBN0064G chip that will selecting via CS pin.

ATMega644P Graphical LCD Interfacing
TG12864A-04A LCM Module Spec
 

It controlling method is very similar to the KS0108 controller chip. I will not explain it here.

ATMega644P Graphical LCD Interfacing

ATMega644P Graphical LCD Interfacing

 I bought this LCD module nearly 20 years now since I was at high school writing code for the 8051 micro-controller.

This LCM  module use a parallel port interface, 8-bit data bus and a few control lines as shown in the picture above. It allow data read and write via R/W pin. Command and data is set by the D/I (Data/Instruction) pin. However for most text displaying application we just need to write data to this display.

The example below the ATMega644P send some texts to this LCM display.

main.c

  1. /*
  2. * 8-TG12832A-04A _Text.c
  3. *
  4. * Created: 1/29/2026 5:51:25 PM
  5. * Author : Admin
  6. */
  7. #include <avr/io.h>
  8. #include <avr/pgmspace.h>
  9. #include "font5x8.h"

  10. #include <util/delay.h>
  11. #define F_CPU 16000000UL

  12. #define LCD_DATA PORTB
  13. #define LCD_CONT PORTD

  14. #define LCD_EN 0
  15. #define LCD_DI 1
  16. #define LCD_CS 2
  17. #define LCD_RET 3


  18. unsigned char dotCount=0;

  19. /*
  20. cs = 1 left screen area is selected
  21. cs = 0 right screen area is selected
  22. */
  23. void lcdCommand(unsigned char cmd,char cs){
  24. if(cs==1) LCD_CONT|=(1<<LCD_CS);
  25. else LCD_CONT&=~(1<<LCD_CS);
  26. LCD_CONT&=~(1<<LCD_DI);
  27. LCD_DATA=cmd;
  28. LCD_CONT|=(1<<LCD_EN);
  29. _delay_us(10);
  30. LCD_CONT&=~(1<<LCD_EN);
  31. //if(cs==1) LCD_CONT&=~(1<<LCD_CS);
  32. //else LCD_CONT&=~(1<<LCD_CS);
  33. }

  34. void lcdData(char data,char cs){
  35. if(cs==1) LCD_CONT|=(1<<LCD_CS);
  36. else LCD_CONT&=~(1<<LCD_CS);
  37. LCD_CONT|=(1<<LCD_DI);
  38. LCD_DATA=data;
  39. LCD_CONT|=(1<<LCD_EN);
  40. _delay_us(10);
  41. LCD_CONT&=~(1<<LCD_EN);
  42. //if(cs==1) LCD_CONT&=~(1<<LCD_CS1);
  43. //else if (cs==2) LCD_CONT&=~(1<<LCD_CS2);
  44. }

  45. void lcdHorizontal(unsigned char horizontal){
  46. lcdCommand(0x40+horizontal,1);
  47. lcdCommand(0x40+horizontal,0);
  48. }

  49. void lcdVerticalLine(unsigned char line){
  50. lcdCommand(0xB8+line,1);
  51. lcdCommand(0xB8+line,0);
  52. dotCount=0;
  53. }

  54. void lcdSetZ(unsigned char zAxis){
  55. lcdCommand(0xC0+zAxis,1);
  56. lcdCommand(0xC0+zAxis,0);
  57. }

  58. void lcdXy(unsigned char x,unsigned char y){
  59. if(x<64){
  60. lcdCommand(0x40+x,1);
  61. lcdCommand(0x40+0,0);
  62. }
  63. else{
  64. lcdCommand(0x40+0,1);
  65. lcdCommand(0x40+x-63,0);
  66. }
  67. lcdCommand(0xB8+y,1);
  68. lcdCommand(0xB8+y,0);
  69. dotCount=x;
  70. }

  71. void writeChar(unsigned char aph){
  72. for (int i=0;i<5;i++)
  73. {
  74. char font = pgm_read_byte(&font5x8[((aph-32)*5)+i]);
  75. if(dotCount<64) lcdData(font,1);
  76. else lcdData(font,0);
  77. dotCount++;
  78. }
  79. lcdData(0,(dotCount<64)?1:0);
  80. dotCount++;
  81. if (dotCount>127)
  82. {
  83. dotCount=0;
  84. }
  85. }

  86. void writeCharDelay(unsigned char aph,unsigned int dT){
  87. for (int i=0;i<5;i++)
  88. {
  89. char RomReader = pgm_read_byte(&font5x8[((aph-32)*5)+i]);
  90. if(dotCount<64) lcdData(RomReader,1);
  91. else lcdData(RomReader,0);
  92. if(dT!=0) for(int i=0;i<dT;i++) _delay_us(1000);
  93. dotCount++;
  94. }
  95. lcdData(0,(dotCount<64)?1:0);
  96. dotCount++;
  97. if (dotCount>127)
  98. {
  99. dotCount=0;
  100. }
  101. }

  102. void lcdString(char *str){
  103. while(*str)
  104. writeChar(*str++);
  105. if (dotCount>=127)
  106. {
  107. dotCount=0;
  108. }
  109. }

  110. void writeStringDelay(char *str,unsigned int dT){
  111. while(*str){
  112. if(dT!=0) writeCharDelay(*str++,dT);
  113. else writeChar(*str++);
  114. }
  115. }

  116. void lcdInit(void){
  117. DDRB=0xFF;
  118. DDRD=0xFF;
  119. /*Display On*/
  120. lcdCommand(0x3F,1);
  121. lcdCommand(0x3F,0);
  122. dotCount = 0;
  123. }

  124. void lcdClearScreen(){
  125. for (int i=0;i<4;i++)
  126. {
  127. lcdXy(0,i);
  128. for(int j=0;j<127;j++){
  129. lcdData(0,1);
  130. lcdData(0,0);
  131. }
  132. }
  133. dotCount=0;
  134. lcdXy(0,0);
  135. }

  136. void lcdClearSection(unsigned char x,unsigned char y,unsigned char dot){
  137. lcdXy(x,y);
  138. dotCount=x;
  139. for (int i=0;i<dot;i++)
  140. {
  141. if(dotCount<64) lcdData(0,1);
  142. else lcdData(0,0);
  143. dotCount++;
  144. }

  145. if (dotCount>128)
  146. {
  147. dotCount=0;
  148. }
  149. }



  150. int main(void)
  151. {
  152. //_delay_ms(500);
  153. lcdInit();
  154. lcdClearScreen();
  155. lcdString("ATMega644P AVR GLCD");
  156. lcdXy(0,1);
  157. lcdString("TG12864A-04A 128x32");
  158. lcdXy(0,2);
  159. lcdString("Programming With C in");
  160. lcdXy(0,3);
  161. lcdString("Microchip Studio IDE");
  162. while (1)
  163. {
  164. }
  165. }


font5x8.h

  1. //#ifdef __AVR__
  2. //#include <avr/pgmspace.h>
  3. //static const char PROGMEM font5x8[] = {
  4. //#else
  5. const char font5x8[] PROGMEM= {
  6. //#endif
  7. 0x00, 0x00, 0x00, 0x00, 0x00,// (spacja)
  8. 0x00, 0x00, 0x5F, 0x00, 0x00,// !
  9. 0x00, 0x07, 0x00, 0x07, 0x00,// "
  10. 0x14, 0x7F, 0x14, 0x7F, 0x14,// #
  11. 0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
  12. 0x23, 0x13, 0x08, 0x64, 0x62,// %
  13. 0x36, 0x49, 0x55, 0x22, 0x50,// &
  14. 0x00, 0x05, 0x03, 0x00, 0x00,// '
  15. 0x00, 0x1C, 0x22, 0x41, 0x00,// (
  16. 0x00, 0x41, 0x22, 0x1C, 0x00,// )
  17. 0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
  18. 0x08, 0x08, 0x3E, 0x08, 0x08,// +
  19. 0x00, 0x50, 0x30, 0x00, 0x00,// ,
  20. 0x08, 0x08, 0x08, 0x08, 0x08,// -
  21. 0x00, 0x30, 0x30, 0x00, 0x00,// .
  22. 0x20, 0x10, 0x08, 0x04, 0x02,// /
  23. 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
  24. 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
  25. 0x42, 0x61, 0x51, 0x49, 0x46,// 2
  26. 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
  27. 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
  28. 0x27, 0x45, 0x45, 0x45, 0x39,// 5
  29. 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
  30. 0x01, 0x71, 0x09, 0x05, 0x03,// 7
  31. 0x36, 0x49, 0x49, 0x49, 0x36,// 8
  32. 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
  33. 0x00, 0x36, 0x36, 0x00, 0x00,// :
  34. 0x00, 0x56, 0x36, 0x00, 0x00,// ;
  35. 0x00, 0x08, 0x14, 0x22, 0x41,// <
  36. 0x14, 0x14, 0x14, 0x14, 0x14,// =
  37. 0x41, 0x22, 0x14, 0x08, 0x00,// >
  38. 0x02, 0x01, 0x51, 0x09, 0x06,// ?
  39. 0x32, 0x49, 0x79, 0x41, 0x3E,// @
  40. 0x7E, 0x11, 0x11, 0x11, 0x7E,// A
  41. 0x7F, 0x49, 0x49, 0x49, 0x36,// B
  42. 0x3E, 0x41, 0x41, 0x41, 0x22,// C
  43. 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
  44. 0x7F, 0x49, 0x49, 0x49, 0x41,// E
  45. 0x7F, 0x09, 0x09, 0x01, 0x01,// F
  46. 0x3E, 0x41, 0x41, 0x51, 0x32,// G
  47. 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
  48. 0x00, 0x41, 0x7F, 0x41, 0x00,// I
  49. 0x20, 0x40, 0x41, 0x3F, 0x01,// J
  50. 0x7F, 0x08, 0x14, 0x22, 0x41,// K
  51. 0x7F, 0x40, 0x40, 0x40, 0x40,// L
  52. 0x7F, 0x02, 0x04, 0x02, 0x7F,// M
  53. 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
  54. 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
  55. 0x7F, 0x09, 0x09, 0x09, 0x06,// P
  56. 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
  57. 0x7F, 0x09, 0x19, 0x29, 0x46,// R
  58. 0x46, 0x49, 0x49, 0x49, 0x31,// S
  59. 0x01, 0x01, 0x7F, 0x01, 0x01,// T
  60. 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
  61. 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
  62. 0x7F, 0x20, 0x18, 0x20, 0x7F,// W
  63. 0x63, 0x14, 0x08, 0x14, 0x63,// X
  64. 0x03, 0x04, 0x78, 0x04, 0x03,// Y
  65. 0x61, 0x51, 0x49, 0x45, 0x43,// Z
  66. 0x00, 0x00, 0x7F, 0x41, 0x41,// [
  67. 0x02, 0x04, 0x08, 0x10, 0x20,// "\"
  68. 0x41, 0x41, 0x7F, 0x00, 0x00,// ]
  69. 0x04, 0x02, 0x01, 0x02, 0x04,// ^
  70. 0x40, 0x40, 0x40, 0x40, 0x40,// _
  71. 0x00, 0x01, 0x02, 0x04, 0x00,// `
  72. 0x20, 0x54, 0x54, 0x54, 0x78,// a
  73. 0x7F, 0x48, 0x44, 0x44, 0x38,// b
  74. 0x38, 0x44, 0x44, 0x44, 0x20,// c
  75. 0x38, 0x44, 0x44, 0x48, 0x7F,// d
  76. 0x38, 0x54, 0x54, 0x54, 0x18,// e
  77. 0x08, 0x7E, 0x09, 0x01, 0x02,// f
  78. 0x08, 0x14, 0x54, 0x54, 0x3C,// g
  79. 0x7F, 0x08, 0x04, 0x04, 0x78,// h
  80. 0x00, 0x44, 0x7D, 0x40, 0x00,// i
  81. 0x20, 0x40, 0x44, 0x3D, 0x00,// j
  82. 0x00, 0x7F, 0x10, 0x28, 0x44,// k
  83. 0x00, 0x41, 0x7F, 0x40, 0x00,// l
  84. 0x7C, 0x04, 0x18, 0x04, 0x78,// m
  85. 0x7C, 0x08, 0x04, 0x04, 0x78,// n
  86. 0x38, 0x44, 0x44, 0x44, 0x38,// o
  87. 0x7C, 0x14, 0x14, 0x14, 0x08,// p
  88. 0x08, 0x14, 0x14, 0x18, 0x7C,// q
  89. 0x7C, 0x08, 0x04, 0x04, 0x08,// r
  90. 0x48, 0x54, 0x54, 0x54, 0x20,// s
  91. 0x04, 0x3F, 0x44, 0x40, 0x20,// t
  92. 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
  93. 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
  94. 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
  95. 0x44, 0x28, 0x10, 0x28, 0x44,// x
  96. 0x0C, 0x50, 0x50, 0x50, 0x3C,// y
  97. 0x44, 0x64, 0x54, 0x4C, 0x44,// z
  98. 0x00, 0x08, 0x36, 0x41, 0x00,// {
  99. 0x00, 0x00, 0x7F, 0x00, 0x00,// |
  100. 0x00, 0x41, 0x36, 0x08, 0x00,// }
  101. 0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
  102. 0x08, 0x1C, 0x2A, 0x08, 0x08 // <-
  103. };
  104. //

Schematic:

ATMega644P Graphical LCD Interfacing
Schematic 


AVR Prototype Board Test:

  

ATMega644P Graphical LCD Interfacing
AVR Prototype Board Test

This PCB was offered from PCBWay. 

I have been using PCBWay for many years now. PCBWay fabricate PCBs at low cost, fast processing time for only 24 hours, and fast delivery time using any carrier options. This double side 10cmx10cm can be fabricate at only 5USD for 5 to 10pcs by PCBWay. It's a standard PCB with silk screen and solder mask.

A DIY dsPIC30F2010 and dsPIC30F1010 Prototype Board with Programmer
10 PCBs for only 5USD
 

For different size of PCB we can instantly quote on PCBWay website using a zip PCB Gerber file without account.

A DIY dsPIC30F2010 and dsPIC30F1010 Prototype Board with Programmer
PCBWay Instant Quote


RT12864J-1 KS0108 128x64 Dot-matrix and ATMega644P Interfacing 

The KS0108 is a popular dot matrix display driver many years now. Currently there are a lot of low power, low cost display driver controllers that are equivalent to this chip. They have many interfaces beyond the parallel port such as SPI and I2C that implements only a few wires.

ATMega644P Graphical LCD Interfacing
RT12864J-1 KS0108 128x64 Dot-matrix - TOP
ATMega644P Graphical LCD Interfacing
RT12864J-1 KS0108 128x64 Dot-matrix - BOTTOM

 

I have an RT12864J-1 128x64 Graphical Display I bought I from Ebay many years now. But it has some defect due to aging.

ATMega644P Graphical LCD Interfacing
A Tested Program Using ATMega32
ATMega644P Graphical LCD Interfacing
A Tested Program Using ATMega32

 

ATMega644P Graphical LCD Interfacing 

However this large display use an 8-bit parallel port with some control pins that is very boring for newer electronic hobbyists. There are some wiring issue when installing this display on breadboard that needed to make sure all wires connection. 

To display a graphic we need to create a 128x64 monochrome bitmap image using a PC software for example Adobe Photoshop. Then save it a a monochrome bitmap file. 

ATMega644P Graphical LCD Interfacing
LCD Assistance

 

The LCDAssistant.exe tool convert any monochrome bitmap image to a C graphical data that works with any C compilers.

Source Code:

  1. /*
  2. * 8-RT12864J-1.c
  3. *
  4. * Created: 1/30/2026 9:13:54 AM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include "font5x8.h"
  9. #include "diy-logo.h"

  10. #include <util/delay.h>
  11. #define F_CPU 16000000UL

  12. #define LCD_DATA PORTB
  13. #define LCD_CONT PORTD

  14. #define LCD_EN 0
  15. #define LCD_RS 1
  16. #define LCD_CS1 3
  17. #define LCD_CS2 2
  18. #define LCD_RST 4

  19. unsigned char dotCount=0;

  20. void lcdCommand(unsigned char cmd,char cs){
  21. if(cs==1) LCD_CONT|=(1<<LCD_CS1);
  22. else if(cs==2) LCD_CONT|=(1<<LCD_CS2);
  23. LCD_CONT&=~(1<<LCD_RS);
  24. LCD_CONT|=(1<<LCD_EN);
  25. LCD_DATA=cmd;
  26. LCD_CONT&=~(1<<LCD_EN);
  27. _delay_us(10);
  28. if(cs==1) LCD_CONT&=~(1<<LCD_CS1);
  29. else if(cs==2) LCD_CONT&=~(1<<LCD_CS2);
  30. }

  31. void lcdData(char data,char cs){
  32. if(cs==1) LCD_CONT|=(1<<LCD_CS1);
  33. else if(cs==2) LCD_CONT|=(1<<LCD_CS2);
  34. LCD_CONT|=(1<<LCD_RS);
  35. LCD_CONT|=(1<<LCD_EN);
  36. LCD_DATA=data;
  37. LCD_CONT&=~(1<<LCD_EN);
  38. _delay_us(10);
  39. if(cs==1) LCD_CONT&=~(1<<LCD_CS1);
  40. else if (cs==2) LCD_CONT&=~(1<<LCD_CS2);
  41. }

  42. void lcdHorizontal(unsigned char horizontal){
  43. lcdCommand(0x40+horizontal,1);
  44. lcdCommand(0x40+horizontal,2);
  45. }

  46. void lcdVerticalLine(unsigned char line){
  47. lcdCommand(0xB8+line,1);
  48. lcdCommand(0xB8+line,2);
  49. dotCount=0;
  50. }

  51. void lcdSetZ(unsigned char zAxis){
  52. lcdCommand(0xC0+zAxis,1);
  53. lcdCommand(0xC0+zAxis,2);
  54. }

  55. void lcdXy(unsigned char x,unsigned char y){
  56. if(x<64){
  57. lcdCommand(0x40+x,1);
  58. lcdCommand(0x40+0,2);
  59. }
  60. else{
  61. lcdCommand(0x40+0,1);
  62. lcdCommand(0x40+x-63,2);
  63. }
  64. lcdCommand(0xB8+y,1);
  65. lcdCommand(0xB8+y,2);
  66. dotCount=x;
  67. }

  68. void writeChar(unsigned char aph){
  69. for (int i=0;i<5;i++)
  70. {
  71. if(dotCount<64) lcdData(font5x8[((aph-32)*5)+i],1);
  72. else lcdData(font5x8[((aph-32)*5)+i],2);
  73. dotCount++;
  74. }
  75. lcdData(0,(dotCount<64)?1:2);
  76. dotCount++;
  77. if (dotCount>127)
  78. {
  79. dotCount=0;
  80. }
  81. }

  82. void writeCharDelay(unsigned char aph,unsigned int dT){
  83. for (int i=0;i<5;i++)
  84. {
  85. if(dotCount<64) lcdData(font5x8[((aph-32)*5)+i],1);
  86. else lcdData(font5x8[((aph-32)*5)+i],2);
  87. if(dT!=0) for(int i=0;i<dT;i++) _delay_us(1000);
  88. dotCount++;
  89. }
  90. lcdData(0,(dotCount<64)?1:2);
  91. dotCount++;
  92. if (dotCount>127)
  93. {
  94. dotCount=0;
  95. }
  96. }

  97. void lcdString(char *str){
  98. while(*str)
  99. writeChar(*str++);
  100. }

  101. void writeStringDelay(char *str,unsigned int dT){
  102. while(*str){
  103. if(dT!=0) writeCharDelay(*str++,dT);
  104. else writeChar(*str++);
  105. }
  106. }

  107. void lcdInit(void){
  108. DDRB=0xFF;
  109. DDRD=0xFF;
  110. /*Display On*/
  111. lcdCommand(0x3F,1);
  112. lcdCommand(0x3F,2);
  113. dotCount = 0;
  114. }

  115. void lcdClearScreen(){
  116. for (int i=0;i<8;i++)
  117. {
  118. lcdXy(0,i);
  119. for(int j=0;j<128;j++){
  120. lcdData(0,1);
  121. lcdData(0,2);
  122. }
  123. }
  124. dotCount=0;
  125. lcdXy(0,0);
  126. }

  127. void lcdClearSection(unsigned char x,unsigned char y,unsigned char dot){
  128. lcdXy(x,y);
  129. dotCount=x;
  130. for (int i=0;i<dot;i++)
  131. {
  132. if(dotCount<64) lcdData(0,1);
  133. else lcdData(0,2);
  134. dotCount++;
  135. }

  136. if (dotCount>127)
  137. {
  138. dotCount=0;
  139. }
  140. }

  141. void showGraphic(void){
  142. unsigned int kCount=0;
  143. for (int i=0;i<8;i++)
  144. {
  145. dotCount=0;
  146. lcdXy(0,i);
  147. for (int j=kCount;j<kCount+128;j++)
  148. {
  149. if(dotCount<64) lcdData(logo[j],1);
  150. else lcdData(logo[j],2);
  151. dotCount++;
  152. }
  153. kCount+=128;
  154. }
  155. }

  156. int main(void)
  157. {
  158. _delay_ms(100);
  159. lcdInit();
  160. lcdClearScreen();
  161. while (1)
  162. {
  163. lcdXy(25,0);
  164. lcdString("HELLO WORLD!");
  165. lcdXy(0,1);
  166. lcdString("ATMEGA644P Graphic");
  167. lcdXy(0,2);
  168. lcdString("Programming in C With");
  169. lcdXy(0,3);
  170. lcdString("Microchip Studio");
  171. lcdXy(0,4);
  172. lcdString("DIY-Instruments");
  173. lcdXy(0,5);
  174. lcdString("KS0108 LCD Controller");
  175. lcdXy(0,6);
  176. lcdString("RT12864J-1 128x64");
  177. lcdXy(0,7);
  178. lcdString("Graphical LCD Module");
  179. _delay_ms(5000);
  180. lcdClearScreen();
  181. lcdXy(0,0);
  182. showGraphic();
  183. _delay_ms(5000);
  184. lcdClearScreen();
  185. }
  186. }



 

Schematic and Simulation: 

ATMega644P Graphical LCD Interfacing
Simulation Using Proteus 

 

ATMega644P Graphical LCD Interfacing
Simulation Using Proteus 

 

In software it worked fine. But in hardware experiment it has problem due to device defect. I need to fix it later.

For more detail about using this display please see this post. CCS PICC also has a C driver of this LCD. It's very easy to use. This example the PIC16F877A interfaces with a 128x64 KS0108 graphical display.

Click here to download this example. 

 


No comments:

Post a Comment

320x50

Search This Blog

tyro-728x90