Page 1 of 1

ST7920 serial mode not working

Posted: Sat Aug 10, 2013 9:55 am
by honda4life
Hello.

I'm trying to get a ST7920 display (12864ZW) working in serial mode.
This is a 128x64 display, so quite a lot of information can be displayed.
I'm using serial mode, so number of GPIO's are limited to the minimum.
A fist try was with SPI, but that didn't work, so I'm trying to bitbang the serial data first, and after that I can try SPI.

I've found this example code for AVR as a starting point:
http://parenthetic.blogspot.be/2011/12/ ... 0-lcd.html

My code running on the Pi:

Code: Select all

#include <wiringPi.h>
#include <wiringShift.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define P_RS  8  //CE0
#define P_RW  10 //MOSI
#define P_E   11 //SCLK
#define P_RST 25 //GPIO25

#define D_SYNC          0b11111000
#define D_RW            0b00000100
#define D_RS            0b00000010

#define D_FSET		0b00100000
#define D_8BIT		0b00010000

#define D_DCONT		0b00001000
#define D_DON		0b00000100
#define D_CON		0b00000010
#define D_BON		0b00000001

#define D_ENMOD		0b00000100
#define D_INC		0b00000010

#define D_CLR		0b00000001

void initGPIO();
void initLCD();
void resetLCD();
void clearLCD();
void instrLCD(uint8_t);
void dataLCD(uint8_t);
void shiftOutH(uint8_t, uint8_t, uint8_t, uint8_t);

int main(int argc, char **argv)
{
	//if(wiringPiSetup() == -1)
	if(wiringPiSetupGpio() == -1)
	{
		printf("wiringPiSetupGpio() failed\n");
		return EXIT_FAILURE;
	}

	initGPIO();
	delay(40);
	initLCD();

	instrLCD(0x80);
	dataLCD('A');

	return EXIT_SUCCESS;
}

void initGPIO()
{
	pinMode(P_RS, OUTPUT);	//CE0
	digitalWrite(P_RS, LOW);
	delay(100);
	pinMode(P_RW, OUTPUT);	//MOSI
	digitalWrite(P_RW, LOW);
	delay(100);
	pinMode(P_E, OUTPUT);	//SCLK
	digitalWrite(P_E, HIGH);
	delay(100);
	pinMode(P_RST, OUTPUT);	//RST
	digitalWrite(P_RST, HIGH);
	delay(100);
}

void initLCD()
{
	delay(40); //Startup delay
	resetLCD();
}

void resetLCD()
{
	digitalWrite(P_RST, LOW);
	delay(100);
	digitalWrite(P_RST, HIGH);
	delay(100); //40?

	instrLCD(D_FSET | D_8BIT);
        delayMicroseconds(100 - 72); //Delay 100 us needed, 72 done already
        instrLCD(D_FSET | D_8BIT);
        instrLCD(D_DCONT | D_DON);
        delayMicroseconds(100 - 72); //Delay 100 us needed, 72 done already
        clearLCD();
        delayMicroseconds(10000 - 1600);
        instrLCD(D_ENMOD | D_INC);
}

void clearLCD()
{
	instrLCD(D_CLR);
	delayMicroseconds(1600 - 72); //Delay 1.6 ms needed, 72 us done already
}

void instrLCD(uint8_t byte){
	printf("instrLCD(0x%X): %u ms\n", byte, millis());
	digitalWrite(P_RS, HIGH);
	delay(100);
	shiftOutH(P_RW, P_E, MSBFIRST, D_SYNC);
	shiftOutH(P_RW, P_E, MSBFIRST, byte & 0xf0);
	shiftOutH(P_RW, P_E, MSBFIRST, (byte << 4));
	delay(100);
	digitalWrite(P_RS, LOW);
	delay(100);
	delayMicroseconds(72); //Delay for most instructions
}

void dataLCD(uint8_t byte){
        printf("dataLCD(0x%X): %u ms\n", byte, millis());
        digitalWrite(P_RS, HIGH);
	delay(100);
        shiftOutH(P_RW, P_E, MSBFIRST, D_SYNC | D_RS);
        shiftOutH(P_RW, P_E, MSBFIRST, byte & 0xf0);
        shiftOutH(P_RW, P_E, MSBFIRST, (byte << 4));
	delay(100);
        digitalWrite(P_RS, LOW);
	delay(100);
        delayMicroseconds(72); //Delay for most data
}

void shiftOutH(uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val)
{
	printf("shiftOutH(0x%X)\n", val);
	int8_t i;
	digitalWrite(cPin, HIGH); //To be shure idle = HIGH
	delay(100);
	if (order == MSBFIRST)
		for(i = 7; i >= 0; i--)
		{
			digitalWrite(dPin, val & (1 << i));
			delay(100);
			digitalWrite(cPin, LOW);
			delay(100);
			digitalWrite(cPin, HIGH);
			delay(100);
		}
	else
		for(i = 0; i < 8; i++)
		{
			digitalWrite(dPin, val & (1 << i));
			digitalWrite (cPin, LOW);
			digitalWrite (cPin, HIGH);
		}
}
Output:

Code: Select all

instrLCD(0x30): 680 ms
shiftOutH(0xF8)
shiftOutH(0x30)
shiftOutH(0x0)
instrLCD(0x30): 8492 ms
shiftOutH(0xF8)
shiftOutH(0x30)
shiftOutH(0x0)
instrLCD(0xC): 16302 ms
shiftOutH(0xF8)
shiftOutH(0x0)
shiftOutH(0xC0)
instrLCD(0x1): 24114 ms
shiftOutH(0xF8)
shiftOutH(0x0)
shiftOutH(0x10)
instrLCD(0x6): 31936 ms
shiftOutH(0xF8)
shiftOutH(0x0)
shiftOutH(0x60)
instrLCD(0x80): 39748 ms
shiftOutH(0xF8)
shiftOutH(0x80)
shiftOutH(0x0)
dataLCD(0x41): 47560 ms
shiftOutH(0xFA)
shiftOutH(0x40)
shiftOutH(0x10)
A lot of delays are added so I can monitor outputs with LED's.
Wiring should be OK, and everything seems to work.

The datasheet of the module:
http://www.dfrobot.com/image/data/fit0021/st7920.pdf

Who can help please?
I've spent almost two days on this LCD now.
Thank you