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

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.
![]() |
| TG12864A-04A LCM Module Spec |
It controlling method is very similar to the KS0108 controller chip. I will not explain it here.
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
- /*
- * 8-TG12832A-04A _Text.c
- *
- * Created: 1/29/2026 5:51:25 PM
- * Author : Admin
- */
- #include <avr/io.h>
- #include <avr/pgmspace.h>
- #include "font5x8.h"
- #include <util/delay.h>
- #define F_CPU 16000000UL
- #define LCD_DATA PORTB
- #define LCD_CONT PORTD
- #define LCD_EN 0
- #define LCD_DI 1
- #define LCD_CS 2
- #define LCD_RET 3
- unsigned char dotCount=0;
- /*
- cs = 1 left screen area is selected
- cs = 0 right screen area is selected
- */
- void lcdCommand(unsigned char cmd,char cs){
- if(cs==1) LCD_CONT|=(1<<LCD_CS);
- else LCD_CONT&=~(1<<LCD_CS);
- LCD_CONT&=~(1<<LCD_DI);
- LCD_DATA=cmd;
- LCD_CONT|=(1<<LCD_EN);
- _delay_us(10);
- LCD_CONT&=~(1<<LCD_EN);
- //if(cs==1) LCD_CONT&=~(1<<LCD_CS);
- //else LCD_CONT&=~(1<<LCD_CS);
- }
- void lcdData(char data,char cs){
- if(cs==1) LCD_CONT|=(1<<LCD_CS);
- else LCD_CONT&=~(1<<LCD_CS);
- LCD_CONT|=(1<<LCD_DI);
- LCD_DATA=data;
- LCD_CONT|=(1<<LCD_EN);
- _delay_us(10);
- LCD_CONT&=~(1<<LCD_EN);
- //if(cs==1) LCD_CONT&=~(1<<LCD_CS1);
- //else if (cs==2) LCD_CONT&=~(1<<LCD_CS2);
- }
- void lcdHorizontal(unsigned char horizontal){
- lcdCommand(0x40+horizontal,1);
- lcdCommand(0x40+horizontal,0);
- }
- void lcdVerticalLine(unsigned char line){
- lcdCommand(0xB8+line,1);
- lcdCommand(0xB8+line,0);
- dotCount=0;
- }
- void lcdSetZ(unsigned char zAxis){
- lcdCommand(0xC0+zAxis,1);
- lcdCommand(0xC0+zAxis,0);
- }
- void lcdXy(unsigned char x,unsigned char y){
- if(x<64){
- lcdCommand(0x40+x,1);
- lcdCommand(0x40+0,0);
- }
- else{
- lcdCommand(0x40+0,1);
- lcdCommand(0x40+x-63,0);
- }
- lcdCommand(0xB8+y,1);
- lcdCommand(0xB8+y,0);
- dotCount=x;
- }
- void writeChar(unsigned char aph){
- for (int i=0;i<5;i++)
- {
- char font = pgm_read_byte(&font5x8[((aph-32)*5)+i]);
- if(dotCount<64) lcdData(font,1);
- else lcdData(font,0);
- dotCount++;
- }
- lcdData(0,(dotCount<64)?1:0);
- dotCount++;
- if (dotCount>127)
- {
- dotCount=0;
- }
- }
- void writeCharDelay(unsigned char aph,unsigned int dT){
- for (int i=0;i<5;i++)
- {
- char RomReader = pgm_read_byte(&font5x8[((aph-32)*5)+i]);
- if(dotCount<64) lcdData(RomReader,1);
- else lcdData(RomReader,0);
- if(dT!=0) for(int i=0;i<dT;i++) _delay_us(1000);
- dotCount++;
- }
- lcdData(0,(dotCount<64)?1:0);
- dotCount++;
- if (dotCount>127)
- {
- dotCount=0;
- }
- }
- void lcdString(char *str){
- while(*str)
- writeChar(*str++);
- if (dotCount>=127)
- {
- dotCount=0;
- }
- }
- void writeStringDelay(char *str,unsigned int dT){
- while(*str){
- if(dT!=0) writeCharDelay(*str++,dT);
- else writeChar(*str++);
- }
- }
- void lcdInit(void){
- DDRB=0xFF;
- DDRD=0xFF;
- /*Display On*/
- lcdCommand(0x3F,1);
- lcdCommand(0x3F,0);
- dotCount = 0;
- }
- void lcdClearScreen(){
- for (int i=0;i<4;i++)
- {
- lcdXy(0,i);
- for(int j=0;j<127;j++){
- lcdData(0,1);
- lcdData(0,0);
- }
- }
- dotCount=0;
- lcdXy(0,0);
- }
- void lcdClearSection(unsigned char x,unsigned char y,unsigned char dot){
- lcdXy(x,y);
- dotCount=x;
- for (int i=0;i<dot;i++)
- {
- if(dotCount<64) lcdData(0,1);
- else lcdData(0,0);
- dotCount++;
- }
- if (dotCount>128)
- {
- dotCount=0;
- }
- }
- int main(void)
- {
- //_delay_ms(500);
- lcdInit();
- lcdClearScreen();
- lcdString("ATMega644P AVR GLCD");
- lcdXy(0,1);
- lcdString("TG12864A-04A 128x32");
- lcdXy(0,2);
- lcdString("Programming With C in");
- lcdXy(0,3);
- lcdString("Microchip Studio IDE");
- while (1)
- {
- }
- }
font5x8.h
- //#ifdef __AVR__
- //#include <avr/pgmspace.h>
- //static const char PROGMEM font5x8[] = {
- //#else
- const char font5x8[] PROGMEM= {
- //#endif
- 0x00, 0x00, 0x00, 0x00, 0x00,// (spacja)
- 0x00, 0x00, 0x5F, 0x00, 0x00,// !
- 0x00, 0x07, 0x00, 0x07, 0x00,// "
- 0x14, 0x7F, 0x14, 0x7F, 0x14,// #
- 0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
- 0x23, 0x13, 0x08, 0x64, 0x62,// %
- 0x36, 0x49, 0x55, 0x22, 0x50,// &
- 0x00, 0x05, 0x03, 0x00, 0x00,// '
- 0x00, 0x1C, 0x22, 0x41, 0x00,// (
- 0x00, 0x41, 0x22, 0x1C, 0x00,// )
- 0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
- 0x08, 0x08, 0x3E, 0x08, 0x08,// +
- 0x00, 0x50, 0x30, 0x00, 0x00,// ,
- 0x08, 0x08, 0x08, 0x08, 0x08,// -
- 0x00, 0x30, 0x30, 0x00, 0x00,// .
- 0x20, 0x10, 0x08, 0x04, 0x02,// /
- 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
- 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
- 0x42, 0x61, 0x51, 0x49, 0x46,// 2
- 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
- 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
- 0x27, 0x45, 0x45, 0x45, 0x39,// 5
- 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
- 0x01, 0x71, 0x09, 0x05, 0x03,// 7
- 0x36, 0x49, 0x49, 0x49, 0x36,// 8
- 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
- 0x00, 0x36, 0x36, 0x00, 0x00,// :
- 0x00, 0x56, 0x36, 0x00, 0x00,// ;
- 0x00, 0x08, 0x14, 0x22, 0x41,// <
- 0x14, 0x14, 0x14, 0x14, 0x14,// =
- 0x41, 0x22, 0x14, 0x08, 0x00,// >
- 0x02, 0x01, 0x51, 0x09, 0x06,// ?
- 0x32, 0x49, 0x79, 0x41, 0x3E,// @
- 0x7E, 0x11, 0x11, 0x11, 0x7E,// A
- 0x7F, 0x49, 0x49, 0x49, 0x36,// B
- 0x3E, 0x41, 0x41, 0x41, 0x22,// C
- 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
- 0x7F, 0x49, 0x49, 0x49, 0x41,// E
- 0x7F, 0x09, 0x09, 0x01, 0x01,// F
- 0x3E, 0x41, 0x41, 0x51, 0x32,// G
- 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
- 0x00, 0x41, 0x7F, 0x41, 0x00,// I
- 0x20, 0x40, 0x41, 0x3F, 0x01,// J
- 0x7F, 0x08, 0x14, 0x22, 0x41,// K
- 0x7F, 0x40, 0x40, 0x40, 0x40,// L
- 0x7F, 0x02, 0x04, 0x02, 0x7F,// M
- 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
- 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
- 0x7F, 0x09, 0x09, 0x09, 0x06,// P
- 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
- 0x7F, 0x09, 0x19, 0x29, 0x46,// R
- 0x46, 0x49, 0x49, 0x49, 0x31,// S
- 0x01, 0x01, 0x7F, 0x01, 0x01,// T
- 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
- 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
- 0x7F, 0x20, 0x18, 0x20, 0x7F,// W
- 0x63, 0x14, 0x08, 0x14, 0x63,// X
- 0x03, 0x04, 0x78, 0x04, 0x03,// Y
- 0x61, 0x51, 0x49, 0x45, 0x43,// Z
- 0x00, 0x00, 0x7F, 0x41, 0x41,// [
- 0x02, 0x04, 0x08, 0x10, 0x20,// "\"
- 0x41, 0x41, 0x7F, 0x00, 0x00,// ]
- 0x04, 0x02, 0x01, 0x02, 0x04,// ^
- 0x40, 0x40, 0x40, 0x40, 0x40,// _
- 0x00, 0x01, 0x02, 0x04, 0x00,// `
- 0x20, 0x54, 0x54, 0x54, 0x78,// a
- 0x7F, 0x48, 0x44, 0x44, 0x38,// b
- 0x38, 0x44, 0x44, 0x44, 0x20,// c
- 0x38, 0x44, 0x44, 0x48, 0x7F,// d
- 0x38, 0x54, 0x54, 0x54, 0x18,// e
- 0x08, 0x7E, 0x09, 0x01, 0x02,// f
- 0x08, 0x14, 0x54, 0x54, 0x3C,// g
- 0x7F, 0x08, 0x04, 0x04, 0x78,// h
- 0x00, 0x44, 0x7D, 0x40, 0x00,// i
- 0x20, 0x40, 0x44, 0x3D, 0x00,// j
- 0x00, 0x7F, 0x10, 0x28, 0x44,// k
- 0x00, 0x41, 0x7F, 0x40, 0x00,// l
- 0x7C, 0x04, 0x18, 0x04, 0x78,// m
- 0x7C, 0x08, 0x04, 0x04, 0x78,// n
- 0x38, 0x44, 0x44, 0x44, 0x38,// o
- 0x7C, 0x14, 0x14, 0x14, 0x08,// p
- 0x08, 0x14, 0x14, 0x18, 0x7C,// q
- 0x7C, 0x08, 0x04, 0x04, 0x08,// r
- 0x48, 0x54, 0x54, 0x54, 0x20,// s
- 0x04, 0x3F, 0x44, 0x40, 0x20,// t
- 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
- 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
- 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
- 0x44, 0x28, 0x10, 0x28, 0x44,// x
- 0x0C, 0x50, 0x50, 0x50, 0x3C,// y
- 0x44, 0x64, 0x54, 0x4C, 0x44,// z
- 0x00, 0x08, 0x36, 0x41, 0x00,// {
- 0x00, 0x00, 0x7F, 0x00, 0x00,// |
- 0x00, 0x41, 0x36, 0x08, 0x00,// }
- 0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
- 0x08, 0x1C, 0x2A, 0x08, 0x08 // <-
- };
- //
Schematic:

Schematic

AVR Prototype Board Test:
![]() |
| 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.
![]() |
| 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.
![]() |
| PCBWay Instant Quote |
.png)



No comments:
Post a Comment