Ovládání ST7920

Dobrý den,
Potřeboval bych poradit s ovládáním GLCD 128x64 ST7920 od firmy Digole (model 12864ZW).
Na tomto webu microchip.com/forums/m830183.aspx jsem našel potřebný kód k ovládání řadiče ST7920 - je to fórum Microchip, kde nakonec problém vyřeší a zveřejní funkční kód.
Ten jsem upravil pro potřeby PIC16F877A - tzn. LATB → PORTB.

Dále jsem musel v kódu “převrátit” bitové hodnoty posílané na data port, neboť mám GLCD k mikrokontroléru zapojený takto: RD0 (MC) = DB0, RD1 = DB1 atd.
Příklad: v kódu bylo (funkce Initialize):
Send_Command(0b00110000); (to má být podle autora nastavení 8-bitového módu)
Podle datasheetu má být na data portu toto
DB0 = 1
DB1 = 0
DB2 = 0
DB3 = 0
DB4 = 0
DB5 = 0
DB6 = 0
DB7 = 0

tzn. že když mám dataporty GLCD připojené s portem D na MCU přímo, tak musím na PORTD poslat hodnotu 0b10000000, uvažuji doufám správně :slight_smile:

Zde je tedy kód:

[code]#include <xc.h>

#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = OFF
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF

#define _XTAL_FREQ 20000000 //20 MHz oscilator

#define DATA_OUT PORTD
#define RW RA4
#define RS RA5
#define EN RA3
#define RST RA0
#define PSB RA2
#define NC RA1

/*

  • Funkce pinu GLCD podle datasheetu:
  • RST = kdyz je low, tak se GLCD resetuje
  • PSB = kdyz 0, tak seriova komunikace, kdyz 1, tak paralelni 8/4 bitova
  • RS =
  • Kdyz je paralelni mod (PSB = 1):
  •  0 - "select instruction register (write) or busy flag, address counter (read)"
    
  •  1 - "Select data register (write/read)"
    
  • Kdyz je seriovy mod (PSB = 0):
  •  0 - "Chip disabled - SID and SCLK should be set as 'H' or 'L'. Transcient of SID and SCLK is not allowed"
    
  •  1 - "chip enabled"
    
  • RW =
  • Paralelni mod: Read-Write control
  •  0 - Write
    
  •  1 - Read
    
  • Seriovy mod: Serial data input
  • E =
  • Paralelni mod:
  •  1 - Enable trigger
    
  • Seriovy mod: Serial clock
  • D4 - D7 = “Higher nibble data bus of 8-bit interface and data bus for 4-bit interface”
  • D0 - D3 = "Lower nibble data bus of 8-bit interface
    */

void Send_Data(unsigned char data);
void Send_Command(unsigned char command);
void Set_GraphicMode();
void Initialize();
void Clear_Graphics();
void Write_String( unsigned Y ,char * string );

char message[4] = “Ahoj”;

void main(void)
{
__delay_ms(1000); // Allow time for Vdc to settle on GLCD
TRISA = 0x00; //Set data port B as output
TRISD = 0x00; // Set control port D as output
PORTA = 0x00; // port B =0x00
PORTD = 0x00; // port D=0x00

RST = 0;                      // Set reset line to low
Initialize();                  //Initialise GLCD
Send_Command(0x00);    // Setting location to write characters. In this case 0,0 - Top Left Corner
Send_Data(0x03);             // Sending a PREDEFINED character as described in ST7920 Datasheet.
Send_Data(0x04);             // another one
Send_Data(0x05);             // another one
Send_Data(0x06);             // and another one.

Write_String(0x00, message);  // Calling a function to send a String of characters, as defined in 'message' string.
                              // In Extended mode there are four line to print your text. Each line is 16 characters long.                                                   // Line 1 starts at 0x80 , line 2 starts at 0x90, line 3 starts at 0x88, line 4 starts at 0x99.
Set_GraphicMode();                 // Set the display in Extended mode
Clear_Graphics();                     // Must send a Clear command otherwise display could be corrupt.

while(1) {}
return ;

}

//======================== All the command codes below can be found on the ST7920 datasheet ======================
void Initialize()
{
__delay_ms(100);
PSB = 1; //toto jsem pridal - v datasheetu se pise, ze tady musi byt 1 pro paralelni komunikaci
RS=0;
RW=0;
__delay_us(400);
RST = 1;
__delay_ms(10); // Short delay after resetting.
Send_Command(0b00001100); // 8-bit mode. OK
__delay_us(200);
Send_Command(0b00001100); // 8-bit mode again. OK
__delay_us(100);
Send_Command(0b00110000); // display on
__delay_us(200);
Send_Command(0b10000000); // Clears screen. OK
__delay_ms(20);
Send_Command(0b01100000); // Cursor moves right, no display shift.
__delay_us(200);
Send_Command(0b01000000); // Returns to home. Cursor moves to starting point.
}

//========= Setting the control lines to send a Command to the data bus ================
void Send_Command(unsigned char command)
{
RS = 0;
__delay_us(50);
EN = 1;
DATA_OUT = command;
__delay_us(80);
EN = 0;
}

//============= Setting the control lines to send Data to the data bus =====================
void Send_Data(unsigned char data)
{
RS = 1;
__delay_us(60);
DATA_OUT = data;
__delay_us(30);
EN = 1;
__delay_us(20);
EN = 0;
__delay_us(20);
}

//======================= Sent Command to set Extanded mode ====================
void Set_GraphicMode()
{
Send_Command(0b00110100); // Extended instuction set, 8bit
__delay_us(100);
Send_Command(0b00110110); // Repeat instrution with bit1 set
__delay_us(100);
}

//=========== This function set all the pixels to off in the graphic controller =================
void Clear_Graphics()
{
unsigned char x, y;
for(y = 0; y < 64; y++)
{
if(y < 32)
{
Send_Command(0x80 | y);
Send_Command(0x80);
}
else
{
Send_Command(0x80 | (y-32));
Send_Command(0x88);
}
for(x = 0; x < 16; x++)
{
Send_Data(0x00);
}
}
}

//==== Send one character at the time from the ‘message’ string ===========
void Write_String ( unsigned Y ,char * string )
{
Send_Command(Y);
while(*string!= ‘\0’) // Looking for code signigying ‘end of line’ .
{
Send_Data (*string++);
}
}[/code]

Displej však stále nepracuje. Zkrátka se na něm nic nezobrazuje.

Dlouho jsem také pročítal datasheet (který posílám v příloze), avšak bezvýsledně.

Nerad bych vedl polemiku o tom, že jsem kód zkopíroval. Myslím, že mu z 90% rozumím :slight_smile:

Velice by mi pomohlo, kdyby jste mi někdo s tímto problémem pomohl, neboť je to poslední záležitost, na které stojí můj projekt seismografu.

Mám na mysli např. funkci Write_String - v jakém intervalu se má dosazovat souřadnice Y - nejsem si jist, jestli se text nevykresluje někam jinam, než má.

PS.: Předem bych ale chtěl upozornit, že možnost rozbitého GLCD nechávám opravdu jako poslední možnou - GLCD je nový a nikdy nebyl použit.

Děkuji všem za konstruktivní názory!
Display 12864ZW.pdf (1010 KB)

Co takhle zkusit nějakou knihovnu na ovládání toho displaye, člověk se pak nemusí prokousávat registry a řídícími sekvencemi. Já pro tento LCD používám knihovnu u8glib a display s ní funguje. Ovšem tedy komunikuji s LCD seriově, 1xdata, 1xhodiny a 2 dráty napájení.

Že u8g neumí Microchip jsem si neuvědomil, to bohužel neporadím. Seriová kom. je složitější, ale pokud to udělá knihovna, tak je to jedno. Každopádně je pomalejší,tedy záleží zda pro danou aplikaci rychlost vyhovuje.

Řešil jsem podobný problém s displejem koupeným na ebay.Po odzkoušení x kihoven z netu jsem došel k závěru,že je potřeba knihovnu napsat svoji.V současnou dobu mám funkční knihovnu(v Pascalu) pro zapojení ST7920 v paralel módu.Inspirací pro mě byli příklady k desce PIC-EK prodávaný na eBay.
Příklady ke stažení zde.Doporučuju prozkoumat i další.

Strana 34. Mám doma kus, který potřebuje pauzu ne 72us, ale 186us. Jestli není chyba i v tom.
ST7920V40_E.pdf (697 KB)

Připadají mi v tom výše uvedeným kódu chyby.bylo by možný dát sem schéma zapojení MCU k displeji a pro jistotu foto displeje (poud jsou na něm popsaný piny jako je na tonto obrázku.Nekdy to bývá na spodní straně )?

Není chyba právě v tom?

Myslím, že právě toto je důvod, proč Ti to nefunguje. Čísluješ si bity obráceně : 0b00000001 posílá 1 na bit 0 a ne 7. Bity se totiž číslují takto : 0b76543210.

Jinak na první test displej nemusíš přepínat do grafického režimu a můžeš s ním komunikovat stejně, jako se znakovým.

Na odzkoušení funkčnosti displeje můžeš případně odzkoušet tohhle.Je to pro 16F877A /4MHz
Nastavené dle schématu co jsi poslal:
Rs RA5
RW RA4
E RA3
Psb RA2
Rst RA0
Dataport:
DB7 RD7
DB6 RD6
DB5 RD5
DB4 RD4
DB3 RD3
DB2 RD2
DB1 RD1
DB0 RD0
ST7920-12864-ENGLISH.hex (1.73 KB)

Kdyby jsi to schéma dal k tomu HEXu, tak by to nebylo asi moc na škodu.

Vždyť schéma sem dával Matyáš.Je to psaný na to schéma zapojení.
Případně:
download.php?id=2957
download.php?id=2956
Edit: Doplnil jsem popis zapojení

Škoda.Ten program funguje přesně s tímto displejem.
Trafopájkou rozhodně není dobře pájet tuto elektroniku.Jeden nový displej ,nikdy nepoužitý,ale nefunkční mám na stole.Stát se to asi může (že nefunguje jako nový,nebo se lehce odpálí).

Ještě jako další možnost můžeš zkusit s tímto zapojením:
Rs RB0
RW RB1
E RB2
Psb RB3
Rst RB5
Dataport:
DB7 RD7
DB6 RD6
DB5 RD5
DB4 RD4
DB3 RD3
DB2 RD2
DB1 RD1
DB0 RD0

Jestli ani tohle ,tak snad začít od začátku podle datasheetu.
ST7920-12864-ENGLISH.hex (1.73 KB)

Mohl bych poprosit o kontrolu:

Send_Command(0b00000110);  // Cursor moves right, no display shift.

Nějak mi ta binární hodnota nekoresponduje s datasheetem.
Díky.

Podle datasheetu by mělo být pro posun kurzoru S=H. Je-li to pravda ,mělo by bejt poslední číslo v pravo log. 1.
Pletu se ?

Já si právě nejsem jist, o kterou funkci se má jednat - jestli o “Entry mode set” (Datasheet str. 13), nebo “Cursor/Display Shift Control” (Datasheet str. 14). V obou se totiž pracuje s kurzorem.
Chápu to tak, že “Entry mode set” nastavuje, co se má stát po zapsání znaku na GLCD (to znamená že to se nastavuje 1x) a “Cursor/Display Shift Control” prostě hýbe s kurzorem.
Chápu to správně? Nevím totiž, jak přesně bylo myšleno “Cursor moves right, no display shift.”
Děkuji!

Pro ten můj dislej platí:
write_com(0x30); //set 8 bit operation and basic instruction set
write_com(0x0c); //display on cursor off and char blink off
write_com(0x06); //entry mode set
write_com(0x01); //display clear

tj 0x06 = 0B0000110
Takhle mám řešenou inicializaci displeje pro textový mód.

To Sender:
Mohl by jste mi poslat celý Váš kód (pokud ho máte v C)?
Děkuji.

Posláno v SZ.
Ještě mě napadlo,jestli není na tvém displeji naopak třeba reset (L->H nebo naopak)

Bohužel ne :frowning: