I start to working with LCD ST7920
// define pins here #define DATA_PORT PORTD #define DATA_IN PIND #define COMMAND_PORT PORTC #define DATAPORT_DIR DDRD #define COMMAND_DIR DDRC #define RS 0b00000001; // PC0 binary equivalent of pin number #define RW 0b00000010; // PC1 #define E 0b00000100; // PC2 #define RST 0b00001000; // PC3 #define delay_time 80 void highRS() { COMMAND_PORT |= RS; _delay_us(delay_time); } void lowRS() { COMMAND_PORT &= ~RS; _delay_us(delay_time); } void highRW() { COMMAND_PORT |= RW; _delay_us(delay_time); } void lowRW() { COMMAND_PORT &= ~RW; _delay_us(delay_time); } void highE() { COMMAND_PORT |= E; _delay_us(delay_time); } void lowE() { COMMAND_PORT &= ~E; _delay_us(delay_time); } void toggleE() { highE(); lowE(); } void highRST() { COMMAND_PORT |= RST; _delay_us(delay_time); } void lowRST() { COMMAND_PORT &= ~RST; _delay_us(delay_time); } // start graphic mode void ST7920_graphicEnable(void) { DATAPORT_DIR = 0xff; _delay_ms(110); lowE(); lowRS(); lowRW(); highRST(); DATA_PORT = 0x30; // set 8-bit interface delay_ms(110); toggleE(); _delay_ms(1); DATA_PORT = 0x36; // Repeat with graphics bit set to on. _delay_ms(110); toggleE(); DATA_PORT = 0x0c; // display ON, cursor and blink OFF _delay_ms(110); toggleE(); DATA_PORT = 0x01; // clear display, reset address _delay_ms(110); toggleE(); DATA_PORT = 0x06; // display ON, no cursor _delay_ms(110); toggleE(); } void ST7920_graphicFill(uint16_t value) { uint8_t i, j; for (i = 0; i < 64; i++) { for (j = 0; j < 8; j++) { ST7920_write2BytesXY(j, i, value); } } } void ST7920_write2BytesXY(int x, int y, uint16_t data) { DATAPORT_DIR = 0xff; // set data port for output lowE(); lowRS(); lowRW(); // convert coordinates to weirdly-arranged 128x64 screen (the ST7920 is mapped for 256x32 displays). if (y > 31) { y -= 32; // because there are only 31 addressable lines in the ST7920 x += 8; // so we overflow x (7 visible bytes per line) to reach the bottom half } x |= 0x80; // bit 7 signals that this is a data address write y |= 0x80; DATA_PORT = y; // set vertical DDRAM address toggleE(); DATA_PORT = x; // set horizontal DDRAM address toggleE(); highRS(); // signal for WRITE DATA_PORT = (data >> 8); // set horizontal DDRAM address toggleE(); DATA_PORT = data; // set vertical DDRAM address toggleE(); } uint16_t ST7920_read2Bytes(uint8_t type) { uint8_t i, j = 0; uint16_t temp; DATAPORT_DIR = 0x00; // set data port for input DATA_PORT = 0x00; lowE(); if (type == 0) { lowRS(); } else { highRS(); } highRW(); highE(); // toggle byte in i = DATA_IN; // need I read this twice? lowE(); highE(); i = DATA_IN; lowE(); _delay_ms(1); highE(); j = DATA_IN; lowE(); temp = j; temp = temp | (i << 8); return(temp); // return byte read } void ST7920_gotoXY(uint8_t x, uint8_t y) { DATAPORT_DIR = 0xff; // set data port for output lowE(); lowRS(); lowRW(); // convert coordinates to weirdly-arranged 128x64 screen (the ST7920 is mapped for 256x32 displays). if (y > 31) { y -= 32; // because there are only 31 addressable lines in the ST7920 x += 8; // so we overflow x (7 visible bytes per line) to reach the bottom half } x |= 0x80; // bit 7 signals that this is a data address write y |= 0x80; DATA_PORT = y; // Set vertical DDRAM address toggleE(); DATA_PORT = x; // Set horizontal DDRAM address toggleE(); } void ST7920_setPixel(uint8_t x, uint8_t y) { uint8_t x_wd, x_pixel; uint16_t temp; uint16_t dot = 0x8000; // this will be rotated into it's correct position in the word x_wd = x / 16; // find address of word with our pixel (x; 0-7) x_pixel = x - (x_wd * 16); // get the modulo remainder; that's our pixel's position in the word ST7920_gotoXY(x_wd, y); temp = ST7920_read2Bytes(1); // read word from screen at that position temp = (temp | (dot >> x_pixel)); // convert x_pixel into a bit position, 0-16 ST7920_write2BytesXY(x_wd, y, temp); } void ST7920_clearPixel(uint8_t x, uint8_t y) { uint8_t x_wd, x_pixel; uint16_t temp; uint16_t dot = 0x7fff; // this will be rotated into it's correct position in the word x_wd = x / 16; // find address of word with our pixel (x; 0-7) x_pixel = x - (x_wd * 16); // get the modulo remainder; that's our pixel's position in the word ST7920_gotoXY(x_wd, y); temp = ST7920_read2Bytes(1); // read word from screen at that position temp = (temp & (dot >> x_pixel)); // convert x_pixel into a bit position, 0-16 ST7920_write2BytesXY(x_wd, y, temp); } int main(void) { DATAPORT_DIR = 0xff; // set DATAPORT to output DATA_PORT = 0x00; // set outputs to 0 initially COMMAND_DIR = 0x07; // set command port to output COMMAND_PORT = 0x00; // set outputs to 0 initially ST7920_graphicEnable(); ST7920_graphicFill(0x0000); ST7920_setPixel(0, 0); ST7920_setPixel(0, 63); ST7920_setPixel(127, 0); ST7920_setPixel(127, 127); while (1) { } }
When I switch power OFF/ON after LCD initializing, LCD displaing not correct view. I guess something wrong with init sequence. I can't find where I am make mistake)