Interfacing 128x64 LCD display with ATmega8

Thread Starter

LinardsSmeiksts

Joined May 12, 2016
5
Hello!
I have recently got 128x64 grafical LCD display 12864ZW from kamami.com. I found datasheet on the Internet for the display and started to program it. I was able to initialize it and display text using various fonts. But my aim was to display grafical objects for example sinus curve. I explored all the datasheet and tried many ways, but I couldn't draw anything using individual pixels. I use ATmega 8 micrcontroller. I'm sure that my circuit is okay, because I can display characters. I hope that someone might help me. Here is also my code:

C:
[I]#define F_CPU 1000000UL  // 1 MHz
#include <avr/io.h>
#include <util/delay.h>

#define ControlREG         DDRB
#define RS                 0
#define RW                 1
#define E                 2

#define DataREG            DDRD

void Strobe(void);
void CheckBusyFlag(void);
void SendCommand(unsigned char command);
void SendChar(unsigned char character);
void SendChinese(unsigned int chinesechar);


int main(void)
{
    ControlREG |= (1<<RS) | (1<<RW) | (1<<E);
    /*
    // Initialization of LCD display [video tutorial version]
    _delay_ms(50);
    SendCommand(0x38);
    _delay_us(50);
    SendCommand(0b00001111);
    _delay_us(50);
    SendCommand(0b00000001);
    _delay_ms(2);
    // Initialization end
    */
   
    // Initialization of LCD display [datasheet version]
    _delay_ms(60);
    SendCommand(0x24); // 0b00110000
    _delay_us(50);
    SendCommand(0x24);
    _delay_us(50);
    SendCommand(0x0c);
    _delay_ms(150);
    SendCommand(0x01);
    _delay_ms(15);
    SendCommand(0x06);
    // Initalization end
   
    //SendCommand(0x82);  // Set character adress
    //SendChar(0xF7);
    //SendChar(0xA6);
    //SendChinese(0xF7A7);
   
    /*
    // Initialization of LCD display [grafic display mode]
    _delay_ms(60);
    SendCommand(0x36);
    _delay_ms(50);
    SendCommand(0x36);
    _delay_ms(50);
    SendCommand(0x0c);
    _delay_ms(150);
    SendCommand(0x01);
    _delay_ms(15);
    SendCommand(0x04);
    // End of initialization
    */
   
    SendCommand(0x0B);
    SendCommand(0x03);
    SendCommand(0x41);
    SendCommand(0x22);
    SendCommand(0x05);
    SendCommand(0x21);
    SendChinese(0x0007);
   
    while(1)
    {
    }
}

void CheckBusyFlag()
{
    DataREG = 0;
    PORTB &= ~(1<<RS);
    PORTB |= (1<<RW);
    while(PORTD >= 0x80)                // 0x80 = 0b10000000
    {
        Strobe();
    }
    DataREG = 0xFF;
}

void Strobe()
{
    PORTB |= (1<<E);
    asm volatile("nop");
    asm volatile("nop");
    PORTB &= ~(1<<E);
}
   

void SendCommand(unsigned char command)
{
    CheckBusyFlag();
    PORTD = command;
    PORTB &= ~(1<<RS | 1<<RW);
    Strobe();
    PORTD = 0;
}

void SendChar(unsigned char character)
{
    CheckBusyFlag();
    PORTD = character;
    PORTB |= (1<<RS);
    PORTB &= ~(1<<RW);
    Strobe();
    PORTD = 0;
}

void SendChinese(unsigned int chinesechar)
{
    CheckBusyFlag();
    PORTD |= ((chinesechar & 0xFF00) >> 8);
    PORTB |= (1<<RS);
    PORTB &= ~(1<<RW);
    Strobe();
    PORTD = 0;
    PORTD |= (chinesechar & 0x00FF);
    PORTB |= (1<<RS);
    PORTB &= ~(1<<RW);
    Strobe();
    PORTD = 0;
}
Moderators note: please use code tags for pieces of code
 
Last edited by a moderator:

ErnieM

Joined Apr 24, 2011
8,377
I browsed a data sheet for this device by Digole who I believe make this thing. Find it and look at the section on Graphic RAM or GDRAM. It explains how to access the device at a pixel level.

Seems you write 8 pixels at a time, so to change any particular pixel means you need read the byte, modify it, then write it back.

There is a command in the instructs set 2 that gets you access to this graphic data area. That command also includes vertical and horizontal address info. This address auto increments, which is not very handy as you need to set it, read the data, set it once more to write the data to the same address.
 

Thread Starter

LinardsSmeiksts

Joined May 12, 2016
5
I browsed a data sheet for this device by Digole who I believe make this thing. Find it and look at the section on Graphic RAM or GDRAM. It explains how to access the device at a pixel level.

Seems you write 8 pixels at a time, so to change any particular pixel means you need read the byte, modify it, then write it back.

There is a command in the instructs set 2 that gets you access to this graphic data area. That command also includes vertical and horizontal address info. This address auto increments, which is not very handy as you need to set it, read the data, set it once more to write the data to the same address.
I don't understand why I need to READ first and then WRITE. Why isn't working algorithm: 1) set vertical adress, 2) set horizontal adress, 3) write HIGH byte, 4) write LOW byte, which is written in datasheet? :(
 

ErnieM

Joined Apr 24, 2011
8,377
I don't understand why I need to READ first and then WRITE. Why isn't working algorithm: 1) set vertical adress, 2) set horizontal adress, 3) write HIGH byte, 4) write LOW byte, which is written in datasheet? :(
Because you asked how to access a specific pixel, not a group of 8 pixels.

To change one pixel you must find which byte it is in, read that byte, change the pixel, then write it back where it was.
 

Thread Starter

LinardsSmeiksts

Joined May 12, 2016
5
Thanks for replies! I have finally found the problem and solved it. Everything was working fine, I only had to clean all random pixels after initialization. :)
 
Top