Dobrý den,
Chtěl bych se naučit pracovat jednak s LCD 16x2, ale také s grafickým 128x64.
Našel jsem různé návody, ze kterých bych vyšel, ale nemám displej 128x64.
Našel jsem nejlevnější na e-bay: ebay.com/itm/New-12864-128x64-Dots-Graphic-LCD-Display-New-Module-Blue-Backlight-/141593061911?pt=LH_DefaultDomain_15&hash=item20f79aaa17
Vůbec nevím, jestli je velký rozdíl v ovládání těchto displejů s rozdílnými čipy.
Zajímalo by mě tedy, jestli nic nepokazím tím, když si koupím výše zmíněný LCD, který je vzhledově stejný, jako ty, které jsou v tutoriálech.
Děkuji za Vaše názory.
Nejjednodušší je začít se znakovým LCD. Pošleš jednoduchou inicializační sekvenci a pak už vlastně jenom posíláš ASCII kódy znaků, které chceš zobrazit. Nevýhodou je, že máš jenom 8 uživatelsky definovaných znaků a tím pádem je třeba použití české diakritiky velmi složité, až nemožné. Výhodou je, že displeje s řadičem HD44780 a kompatiibilním jsou natolik rozšířené, že návodů, jak na jeho ovládání je plný Internet. Situace kolem grafických LCD displejů je trošku složitější. U těchto modulů existuje celá řada různých řadičů s různým ovládáním. Některé umí i znakovou sadu, takže na ně lze psát podobně jako na textový displej. Ale i pokud ne, tak si vlastní znakovou sadu můžeš nadefinovat přímo v MCU a můžeš použít v pohodě i diakritiku a spoustu dalších věcí. Na začátek by asi bylo nejlepší koupit LCD modul s řadičem KS0108 kompatibilním (to ten, co na něj máš odkaz není, ten má řadič ST7920). V textovém režimu je prakticky totožný se znakovým displejem 16x4 znaky, v grafickém režimu je ale organizace jeho paměti trochu divoká. Pro KS0108 existuje na Internetu spousta informací az mého pohledu bych řekl, že je asi nejjednodušší.
Java simulátory LCD displejů :
Textový 16x2 s HD44780 - dinceraydin.com/djlcdsim/djlcdsim.html
Grafický 128x64 s KS0108 - dinceraydin.com/djgfxlcdsim/djgfxlcdsim.html
Dělám ted taky s tímto 64x128 LCD. Ve výsledku je celkem jedno jaký display zvolíš, protože i pro tenhle existují knihovny, které udělají všecku práci za tebe(používám u8glib), v knihovnách jsou definované fonty, takže si jen vybereš který a dál už posíláš ASCII znaky.
Tenhle typ displaye(řadič ST7920, s řadičem KS0108 jsem ještě neměl tu čest) umí jak seriovou, tak i parallelní komunikaci. Používám seriovou, na to stačí 4dráty(plus 3-5V,gnd, hodiny,data).
Konkrétně u tohoto displaye ale nezapomen započítat i dopravu, takže cena je kolem 170kč. Zelené typy stojí kolem 210kč.
Pokud budeš chtít, můžu ti poslat pár tipů nebo kus zdrojáku pro Arduino.
rob.brno : Neporadil bys mi, jak přepnout tento LCD do sériového režimu ? Řadič to umí, ale mám pocit, že signály, kterými je možné jej přepnout nejsou vyvedeny na piny. DPS jsem zatím blíž nezkoumal, ale žádné jumpery jsem tam nenašel. Nebo se to dá přepnout nějakým nastavením datových a ovládacích pinů ? Dík.
Dobrý večer,
Teď se asi ptám mimo téma, ale mám doma LCD 16X2 (Lumex LCM-S01602 DSR/A)
Pracuji s procesorem PIC16F877A.
Našel jsem následující návod na ovládání těchto LCD: electrosome.com/lcd-pic-mplab-xc8/
Ovšem s některými porty, které jsou v kódu definovány:
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
Si nejsem jist se zapojením.
RS a EN chápu jako register select a enable bit.
Chápu to správně (podle datasheetu), že D4 odpovídá pinu 11, D5 pak portu 12?
Předem se omlouvám za neznalost - s PIC to dělám poprvé.
LCM-S01602DSRA.pdf (235 KB)
Podle datasheetu to chápeš správně, nicméně mě napadá otázka, jak souvisí rozmístění signálů na pinech displeje s použitým procesorem ? V odkazu je naprosto přehledné schéma a pokud chceš dělat něco kolem elektroniky (to se netýká jenom procesorů, ale obecně), tak přinejmenším číst schémata je základní věc, kterou bys měl ovládat. A pokud chceš něco i postavit, tak musíš umět schémata nejenom číst, ale i vytvářet.
Ale vraťme se k dotazu :
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
Když porovnáš schéma s definicema jmen signálů v programu, tak zjistíš, že vlastně definice jmen pro program MCU odpovídá připojení signálů LCD displeje, tedy že signál EN na displeji je připojen na bránu D, bit 3 procesoru. Ostatní signály také, takže vlastně jsi programu popsal připojení displeje k MCU.
Balů:
Volba režimu u ST7920 se provede stahnutím pinu PSB na zem, zároven vytahuju pin RS na Ucc(výběr displaye)
Popis seriové komunikace ST7920 je např. tady: lcd-module.de/eng/pdf/zubeho … hinese.pdf - str 26.
U zelených LCD to bylo OK, ale pak jsem koupil jeden modrý a tam bylo PSB natvrdo vytažené na Vcc, psal čínanovi - poslal mi nový a stejně “nefunkční”. Nakonec jsem zjistil, že u některých LCD(asi jen modrých) je PSB vytažen na Vcc propojkou na PCB, R9 vytahuje na Vcc, R10 stahuje na gnd. Takže bylo nutno pro seriový režim propojku z R9 přehodit na R10.
Jinak ta seriová kom. je hodně neúsporná - přenesení jednoho byte zabere 3byte.
To rob.brno : Děkuju. Jak jsem psal výše, signál PSB na konektor vytažený není. Včera jsem na DPS toho displeje koukal a jsou tam na 3 místech odpory 0R a DPS vypadá, že jsou tam jako jumpery. Neměl jsem po ruce měřák, abych zjistil, co kam jde (o to se pokusím dneska) a uvidíme. Na DPS nejsou IO, ale jenom 3 asfaltový kaňky, tak snad z toho něco vykoukám. Na komunikaci jsem se do datasheetu díval, tak se ještě rozmyslím, jestli použít SPI komunikaci vestavěnou, nebo jestli připojit LCD pomocí 74595-ky. Zapojení mám udělané tak, že pomocí 3 komunikačních drátů umím poslat jak 8 bitů dat, tak signály RS a E. Zabere to v nejhorší variantě 2 byty přenosu, v nejlepší kombinaci stačí 1 byte. Ještě jednou děkuju.
To Balů:
Schématům samozřejmě rozumím, snažím se
“Problém” je v tom, že já mám PIC na vývojové desce s konektorem pro LCD 16x2 v trochu jiném spojení s procesorem:
Číslo pinu konektoru | Název pinu v LCD | odpovídající pin procesoru
1 | Vss | GND
2 | VDD | +5V
3 | V0 | pro regulaci jasu…
4 | RS | RA5
5 | R/W | RA4
6 | E | RA3
7 | DB0 | RD0
8 | DB1 | RD1
…
14 | DB7 | RD7
15 | Anode | RA2 //Nepotřebuji, nemám podsvícení
16 | Cathode | RA1 //Nepotřebuji, nemám podsvícení
Takže musím definici portů v kódu trochu změnit;
Podle zapojení na obrázku v návodu jsem pochopil, že DB0 až DB3 jsou spojeny se zemí, takže jsem odpovídající porty procesoru na mé desce (RD0 až RD3) spojil také se zemí a zbývající DATA BUSy (DB4 až DB7) jsou tedy spojeny s porty procesoru (RD4 až RD7)
Kód jsem tedy upravil následovně;
[code]#define _XTAL_FREQ 20000000
#define RS RA5
#define EN RA3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
#include <xc.h>
#include “lcd.h”;
// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//END CONFIG
int main()
{
unsigned int a;
TRISD = 0x00;
TRISA = 0x00;
Lcd_Init();
while(1)
{
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String(“LCD Library for”);
Lcd_Set_Cursor(2,1);
Lcd_Write_String(“MPLAB XC8”);
__delay_ms(2000);
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String(“Developed By”);
Lcd_Set_Cursor(2,1);
Lcd_Write_String(“electroSome”);
__delay_ms(2000);
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String(“www.electroSome.com”);
for(a=0;a<15;a++)
{
__delay_ms(300);
Lcd_Shift_Left();
}
for(a=0;a<15;a++)
{
__delay_ms(300);
Lcd_Shift_Right();
}
Lcd_Clear();
Lcd_Set_Cursor(2,1);
Lcd_Write_Char('e');
Lcd_Write_Char('S');
__delay_ms(2000);
}
return 0;
}[/code]
Jenže po zapnutí cca po 2 sekundách se objeví 16 plných políček na prvním řádku a po 2 sec. zase zmizí. Potom je chvíli pauza a pak se zase na 2 sekundy objeví plný 1. řádek.
Nevíte, kde je chyba?
Tak snaha je základ a pokud rozumíš schématům, tak je to správně.
-
D0-D3 nemusíš přepojovat. Jenom na RD0-RD3 nastav 0 nebo přenastav komunikaci s LCD na 8-bitovou. Komunikace je 2x rychlejší, protože každý byte je Nastavit data->Nastavit RS->Kmitnout E. 4-bitová komunikace tohle celé dělá pro každý byte 2x. Pokud teda knihovna umí použít 8-bitový přenos…
-
Anodu a katodu podsvícení (pokud bys měl) nepřipojuj přímo k MCU. Anodu připoj na VCC, katodu přes tranzistor na GND, bázi tranzistoru na pin MCU (samozřejmě přes odpor…). Přímé připojení by pin případně celý MCU nemusel proudově ustát. Doporučuji do série s podsvícením přidat odpor (nebo na něj alespoň rezervovat místo na DPS).
-
Displej potřebuje po zapnutí čas na vnitřní inicializaci. Pro začátek po zapnutí zinicializuj piny MCU a počkej cca 500ms, než zavoláš inicializaci LCD. Proto ta řada čtverečků - LCD po zapnutí “prošvihnul” inicializační sekvenci z MCU. Za předpokladu, že zapojení odpovídá nastavení v programu, by to mělo naskočit, pokud MCU zrestartuješ resetem (bez vypnutí napájení).
Bohužel, nic se nezměnilo
Tady je upravený kód:
[code]#define _XTAL_FREQ 20000000
#define RS RA5
#define EN RA3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
#include <xc.h>
#include “lcd.h”;
// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//END CONFIG
int main()
{
unsigned int a;
TRISD = 0x00;
TRISA5 = 0;
TRISA3 = 0;
RD0 = 0;
RD1 = 0;
RD2 = 0;
RD3 = 0;
__delay_ms(3000);
Lcd_Init();
while(1)
{
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String(“LCD Library for”);
Lcd_Set_Cursor(2,1);
Lcd_Write_String(“MPLAB XC8”);
__delay_ms(2000);
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String(“Developed By”);
Lcd_Set_Cursor(2,1);
Lcd_Write_String(“electroSome”);
__delay_ms(2000);
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String(“www.electroSome.com”);
for(a=0;a<15;a++)
{
__delay_ms(300);
Lcd_Shift_Left();
}
for(a=0;a<15;a++)
{
__delay_ms(300);
Lcd_Shift_Right();
}
Lcd_Clear();
Lcd_Set_Cursor(2,1);
Lcd_Write_Char('e');
Lcd_Write_Char('S');
__delay_ms(2000);
}
}[/code]
Po sestavení dostanu následující varování, co s váže k
Lcd_Write_String("LCD Library for");
Lcd_Write_String("MPLAB XC8");
Lcd_Write_String("Developed By");
Lcd_Write_String("electroSome");
Lcd_Write_String("www.electroSome.com");
warning: (359) illegal conversion between pointer types
Které se zřejmě zobrazovalo už předtím, ale já si myslel, že varování “nejsou důležitá” jako errory - procesor přes ně jede dál.
ano to si pochopil dobre
tady si trochu prestrelil, je tam jasne napsano DB0-DB3 tzn piny na LCD ne na procesoru ! DBx a RDx je neco jinyho ! a je to tam vydet i na obrazku …
a proc toho tam mas tolik ?
tohle snad staci na vyskouseni … ne?
.
.
Lcd_Init();
Lcd_Clear();
while(1)
{
Lcd_Set_Cursor(1,1);
Lcd_Write_Char('e');
__delay_ms(500);
Lcd_Set_Cursor(1,1);
Lcd_Write_Char('E');
__delay_ms(500);
}
Jak jsem napsal výše:
Tudíž DB0 až DB3 = RD0 až RD3.
Asi jsem to napsal špatně, ale je jedno jestli řeknu, že uzemňuji DB0, nebo RD0, protože jsou spojené.
Nicméně, stále to nefunguje.
[code]#define _XTAL_FREQ 20000000
#define RS RA5
#define EN RA3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
#include <xc.h>
#include “lcd.h”;
// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//END CONFIG
int main()
{
TRISD = 0;
TRISA5 = 0;
TRISA3 = 0;
__delay_ms(3000);
Lcd_Init();
Lcd_Clear();
while(1)
{
Lcd_Set_Cursor(1,1);
Lcd_Write_Char(‘e’);
__delay_ms(500);
Lcd_Set_Cursor(1,1);
Lcd_Write_Char(‘E’);
__delay_ms(500);
}
}[/code]
To Balů:
8-bitové ovládání je zajímavé, jenže mně zatím ještě nefunguje ani 4-bitová Pokud by jste věděl jak na to, bylo by to skvělé. Třeba to bude fungovat.
pulldown na RS-E-R/W mas?
skus : DB0-DB7 pripojeny pouze k portu D ,vsechno na log 0, pockej sekundu(2,3) , zapis na port D 0xf, E=log1 , 1ms, E=log0 // 8bit ovladani
prave, nikde v kodu nevidim definici jak budes komunikovat z lcd, takze piny procesoru natvrdo uzemneni pri 8bit komunikaci … (treba)
Aha, pardon, úplně jsem zapomněl sem hodit lcd.h
Jenom netuším, co myslíte tím pulldown - pulldown rezistor?
Software a hardware jsem převzal z webu.
Pokud tedy myslíte pulldown rezistor, tak žádného rezistoru jsem si na schématu nevšiml.
Jak jsem napsal, RS je přímo spojen s RA5, E je spojen s RA3 a R/W je spojen se zemí a portem RA4.
Zde je lcd.h:
[code]void Lcd_Port(char a)
{
if(a & 1)
D4 = 1;
else
D4 = 0;
if(a & 2)
D5 = 1;
else
D5 = 0;
if(a & 4)
D6 = 1;
else
D6 = 0;
if(a & 8)
D7 = 1;
else
D7 = 0;
}
void Lcd_Cmd(char a)
{
RS = 0; // => RS = 0
Lcd_Port(a);
EN = 1; // => E = 1
__delay_ms(4);
EN = 0; // => E = 0
}
Lcd_Clear()
{
Lcd_Cmd(0);
Lcd_Cmd(1);
}
void Lcd_Set_Cursor(char a, char b)
{
char temp,z,y;
if(a == 1)
{
temp = 0x80 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
else if(a == 2)
{
temp = 0xC0 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
}
void Lcd_Init()
{
Lcd_Port(0x00);
__delay_ms(20);
Lcd_Cmd(0x03);
__delay_ms(5);
Lcd_Cmd(0x03);
__delay_ms(11);
Lcd_Cmd(0x03);
/////////////////////////////////////////////////////
Lcd_Cmd(0x02);
Lcd_Cmd(0x02);
Lcd_Cmd(0x08);
Lcd_Cmd(0x00);
Lcd_Cmd(0x0C);
Lcd_Cmd(0x00);
Lcd_Cmd(0x06);
}
void Lcd_Write_Char(char a)
{
char temp,y;
temp = a&0x0F;
y = a&0xF0;
RS = 1; // => RS = 1
Lcd_Port(y>>4); //Data transfer
EN = 1;
__delay_us(40);
EN = 0;
Lcd_Port(temp);
EN = 1;
__delay_us(40);
EN = 0;
}
void Lcd_Write_String(char a)
{
int i;
for(i=0;a!=’\0’;i++)
Lcd_Write_Char(a*);
}
void Lcd_Shift_Right()
{
Lcd_Cmd(0x01);
Lcd_Cmd(0x0C);
}
void Lcd_Shift_Left()
{
Lcd_Cmd(0x01);
Lcd_Cmd(0x08);
}[/code]**
a ten test dopad jak ?
ty pulldowny nech bejt poznas pozdejc…
Ahoj. Tak bohužel, s touhle “knihovnou” na 8-bitovou komunikaci zapomeň. Upřímně řečeno, takhle napsaný kód bych se styděl dát do vlastního domácího rychloprojektu, natož, abych ho dal k dispozici na net …
V *.h mají být prototypy funkcí, vlastní kód se píše do *.c souborů. Tohle je prasárna a ne knihovna.
V každém případě : Klidně nech datový port LCD s procesorem propojený celý (všech 8 bitů) a na začátku programu na celý port pošli 0. Knihovna na portu pro LCD hýbe jenom bitama 4-7, takže nevadí, že má bity 0-3 připojené. Každopádně “knihovna” není ani napsaná správně podle datasheetu :
[code]void Lcd_Init()
{
Lcd_Port(0x00);
__delay_ms(20); // Nehýbalo se řídícími signály, tak proč tady ten delay ???
Lcd_Cmd(0x03); // Nastavení na 8 bitů
__delay_ms(5); // Stačí 2 ms, ale proč ne …
Lcd_Cmd(0x03); // Nastavení na 8 bitů
__delay_ms(11); // Nechápu, proč je tady 11 ms
Lcd_Cmd(0x03); // Nastavení na 8 bitů
// tady už delay chybí (min. 1,53 ms)
/////////////////////////////////////////////////////
Lcd_Cmd(0x02); // Nastavení na 4 bity
// tady opět delay chybí (min. 1,53 ms)
// Dál už běží komunikace po 4 bitech
Lcd_Cmd(0x02); // Nastavení na 4 bity, 2 řádky, Font 5x7
Lcd_Cmd(0x08); // Nastavení na 4 bity, 2 řádky, Font 5x7
// tady opět delay chybí (min. 1,53 ms)
Lcd_Cmd(0x00); // Display ON, Cursor OFF, Blinkání kurzoru OFF
Lcd_Cmd(0x0C); // Display ON, Cursor OFF, Blinkání kurzoru OFF
// tady opět delay chybí (min. 39 us)
Lcd_Cmd(0x00); // Kurzor se bude posouvat doprava, Obraz se posouvat nebude
Lcd_Cmd(0x06); // Kurzor se bude posouvat doprava, Obraz se posouvat nebude
// tady opět delay chybí (min. 39 us)
}[/code]
Po každém zápisu do RAM displeje (a je jedno, jestli je to do RAMky znakové nebo generátoru znaků) je třeba počkat 43 us. Mezi jednotlivými polovinami bytu není potřeba čekat.
void Lcd_Write_Char(char a)
{
char temp,y;
temp = a&0x0F;
y = a&0xF0;
RS = 1; // => RS = 1
Lcd_Port(y>>4); //Data transfer
EN = 1;
__delay_us(40); // Tady stačí 1-2 us
EN = 0;
Lcd_Port(temp);
EN = 1;
__delay_us(40); // Tady stačí 1-2 us
EN = 0;
// tady delay chybí (min. 43 us)
}
A jsou tam další chyby, ale až to upravíš alespoň podle mých poznámek, mohlo by to již fungovat. Pokud tomu, kdo knihovnu psal, displej fungoval, pak měl buď obrovskou kliku nebo pekelně rychlý displej. Bral jsem časy z datasheetu od 16x2 znaků LCD od Display Electronic GmbH. Jiné displeje budou mít časy jiné. Měl jsem tady displeje rychlejší, ale i pomalejší. Ve svojí knihovně mám tedy časy delší, aby pokud možno pokryly maximum displejů. Jakmile narazím na LCD, který to nestíhá, tak časy zase podloužím, ale dával jsem trochu rezervu (místo 43 us jsem dával 60 us apod.), takže by snad měly stíhat všechny displeje.
Kdyby sis vzal k ruce datasheet, tak by sis program pro ovládání napsal sám a možná i líp, než tenhle paskvil, a ještě by ses něco přiučil.
A ještě k té inicializaci. To přepnutí do 8-bitového režimu je tam sice 3x (na první pohled zbytečně), ale je k tomu dobrý důvod. Nechci to tu znova rozepisovat, ale když použiješ vyhledávání, určitě to tady na serveru najdeš, už jsem to tu vysvětloval.
Prozatím Vám děkuji, budu hledat další návody.