Transformators.lv


 
 
 
 
 
 
 
Sākums » Ar Mikrokontrolieru Vadību, DIY Raksti, Elektronikas Pamācības, Iesācējiem - ar ko sākt, PIC

Mācamies vadīt simbolu LCD

05.08.2011 | Ievietoja: Maarchels | Kategorija: Ar Mikrokontrolieru Vadību, DIY Raksti, Elektronikas Pamācības, Iesācējiem - ar ko sākt, PIC | 9 komentāri

Piedalīties diskusijā par šo rakstu

Sveiki!!

Paskatījos iepriekšējos rakstus – bija projektiņi, kuru sastāvā ir displeji, bet nebij sīkāk apraktīts – kā tad notiek paša vadība? Tad nu neliels rakstiņs no manis par šo tēmu. :)

Raksts būs par vienkāršāko un populārāko no lcd displejiem – simbolu lcd displeju, kurā ir jau iebūvēts kontrolieris, lai mums nebūtu jāuztraucas par atsevišku pikseļu kontroli. Atliek tikai nosūtīt pareizās komandas un datus ASCII formātā.

Aprakstīshu populārāko no kontrolieriem -HD44780 (Hitachi)
Datasheet – http://www.sparkfun.com/datasheets/LCD/HD44780.pdf

Pastaav arii citi shii kontroliera atvasinaajumi, piemeeram, S6A009 un KS0066U no Samsung. Visi vairaak vai mazaak ir savstarpeeji liidziigi – atliek saprast vienu un sapratiisi visus.

Neliels standarta izvadu apraksts:

VSS – negatīvā barošana, jeb lielākajā gadījumā masa vai 0V

VDD – poitiivaa barošana, jeb lielākajā gadiiijumaa +5V

VEE – kontrasta ieejas spriegums. Parasti piesleedz potenciometru un ieregulē vajadzīgo kontrastu

RS – Izveelas instrukciju vai datu reģistrus. Ja gribat nosūtīt instrukciju,RS=0, ja datus, RS=1

RW-Ja 0 tad rakstīšanas reziims, ja 1 tad lasīšanas reziims

E- Saak rakstīšanu/lasīšanu

D0-D7 – datu ieejas/izejas. Ja izmanto 4-bit reziimu, vajadiigi tikai D4-D7.

Veel ir apgaismojuma/backlight pini – atceries,ka izmantojot backlight, teereesies lielaaka straava. Bet buus smuki.

Par to 4-bit reziimu: Var izvēlēties datu joslas platumu – 4-bit, vai 8-bit. 8bit buus ātrāks, bet izmantos vairāk vadus un vairāk MCU i/o pinus. 4-bit reziimaa dati/instrukcijas jāsūta pa pusbaitam – papriekshu Jaunaakais pusbaits*, un peec tam vecākais. Deelj taa shis reziims ir nedaudz lēnāks, bet ieguvumi ir lielāki nekaa zaudējumi – tu ietaupi veselas 4 MCU kaajas! Taapeec aprakstīšu 4-bit reiziimu.

*lai nebūtu nezinja – baits sastāv no 8 bitiem B7:B6:B5:B4:B3:B2:B1:B0. Jaunaakais pusbaits ir B7-B4, vecākais B3-B0

Veel kas jāpiemin, saakot – Ir jaazin, kad HD44780 ir gatavs nolasiit ienākošos datus. Tu nevari suutiit instrukcijas/datus , ja vinjs nav paspējis apstrādāt iepriekšējo.

Kaa zinaat, kad drīkst suutiit nākamo komandu? Nu visvienkāršāk ir vienkārši pagaidiit noteiktu laiku un cereet, ka HD44780 buus gatavs lasiit. Bet tas nav efektīvi, jo shie izpildes laiki nav konstanti, kas nozīme, ka biezhi vien sanaaks lieki teereet daargo laiku. Taapeec ir taada fiicha kaa Busy Flag, jeb BF.

Ja BF=1, HD44780 ir aizņemts, ja BF=0, HD44780 ir gatavs pieņemt nākamo komandu. Citiem vārdiem sakot, ir jaapuulo, jeb jāpārbauda , kad BF nometīsies uz 0, pirms suuta nākamo komandu. Siikaak turpinājumā….

Kaa notiek 4-bit rakstīšana/komandu sūtīšana(Sauksim sho par lcd_write):

1.Jauzstaada RS. Ja suuti instrukciju RS=0, ja suuti datus RS=1

2. RW=0 – Rakstiishanas reziims

3.Gaida kad BF nometīsies uz 0. Kaa to izdariit – turpinājumā.

4. Izvada uz D4-D7 jaunaako pusbaitu

5. E=1, pagaidi 1 us un E=0, jeb saakt rakstiishanu

6. Izvada uz D4-D7 vecaako pusbaitu

7. Atkal – E=1, pagaidi 1 us un E=0

Kaa pārbaudīt Busy Flag:

1.Uzstaada MCU datu pinus (tos, kas pieslēgti D4-D7)kaa ieejas – jo šoreiz jādara otrādi – nevis HD44780 lasiis, bet tev buus jālasa.

2. RS=0 -instrukciju reziims

3.RW=1 – Lasiishanas reziims

5. E=1

6.Nolasa un saglabaa jaunāko pusbaitu (satur BF)

7.E=0

8. Pagaidi kaadu 1 us (nop)

9. E=1 ,pagaidi 1 us un E=0.Sho vajag,lai HD44780 atsuuta vecāko pusbaitu. Saglabaat vinju nevajag.

10.Paarbaudi D7,jeb BF ko nolasīji un saglabaaji pirmajaa piegājienā – ja D7=1, tad iet uz punktu #5, ja 0, tad HD44780 gatavs pieņemt komandas. Turpinaat…

11. RW=0 un MCU datu pinus uzstaadi atkal kaa izejas.

Pirmais kas mums jādara ir jāinicializē kontrolieris un jauzstaada nepiechieshamie uzstādījumi. Kaa tas jādara – ir apraktiits datasheet 45-46lpp

Taakaa izmantojam 4-bit joslas platumu…..

…4-bitu init sekvence:

1. Pagaidi vismaz 15ms, lai spriegums nostabilizētos un kaa saka viss “uzsiltu” :)

2. Aizsuuti instrukciju (RS=0, atceries?) 0×03. Pagaidaam veel ir 8-bit reziims (peec noklusējuma) un BF pagaidām nevar tikt chekots, taapeec izmanto shaadu sekvenci:

INIT 8bit sekv

a.RS=0, RW=0

b.Instrukcija uz D4-D7

c.E=1,pagaidi kaadu 1us un E=0

3.Pagaidi vismaz 4.1ms

4.Atkal aizsuuti 0×03, izmantojot INIT 8bit sekv.

5. Shoreiz pagaidi vismaz 100us

6.Atkaarto punktu #4 :)

7.Aizsuuti 0×02 , joprojām imantojot INIT 8bit sekv. Shii instrukcija uzstāda 4bit reziimu,kaa arii BF tagad var tikt chekots. Turpmaak izmantojam pirmstam aprakstīto lcd_write

8.Suuti izstrukciju (Atgaadinu-RS=0!) 0×28 .Shii instrukcija saucaas Function set. Uztaada rindu skaitu, fontu. Peec tam shos uzstādījumus nedrīkstēs mainiit.(datasheet – saakot ar 23lpp ir apraksts).

9.Suuti instrukciju 0×08

10. Suuti instrukciju 0×01 (shii instrukcija notīra displeju. Izmanto,ja peec tam vajag J)

11. Suuti instrukciju 0×6. Saucaas – Entry Mode Set. Neapraktiishu, ko uzstāda shii instrukcija – to varat izlasiit datasheet saakot no 23lpp.

12. Suuti instrukciju 0x0f. Saucaas – Display on/off cointrol. Iisumaa – ieslēdz displeju, kursoru, un mirgojošu kursora simbolu.

Ja esi visu pareizi izdarījis,uz displeja vajadzētu parādīties mirgojošs kursors.

Nu grūtākā dalja ir garaam!! Tagad vari saakt suutiit datus(simbolus).

Piemeeram,ja gribi suutiit burtu ‘X’ izmanto lcd_write, tikai šoreiz uzstādi RS=1, jo gribi tachu suutiit datus. Parasti kompilatori un asembleri automātiski pārveidos ASCII kodaa.

Tu vari arii, piemēram, uzstādīt, kursoru jenkuraa displeja vietaa(lai saaktu rakstiit, piemēram, displeja viduu.) Katram displeja simbolu “kluciitim” ir sava adrese. Ja tev ir 2*xx(2*16 piemeeram) simbolu displejs, tad shiis adreses ir 0×00-0×27 pirmajai rindai un 0×40-0×67 otrajai rindai. Vienkaarshi ieraksti vajadzīgo adresi izmantojot instrukciju “Set DDRAM Address“.

Piemeeram – gribi tikt otraas rindas saakumaa – DDRAM adrese ir 0×40,bet taa kaa “Set DDRAM Address” instrukcijai bits#7 ir 1 tad intrukcija, kas jaasuuta sanaak 0xC0 (11000000, jo 0×40 ir 1000000,bet priekshaa jaaliek 1)

Viena laba lieta,ko varu piemineet – peec nokluseejuma(Entry mode set instrukcija), aizsuutot datus/simbolu, DDRAM adrese automaatiski palielinaas par 1.tas noziimee, ka, uzrakstot vienu simbolu, vareesi rakstiit jau naakamo, jo kursors pats jau buus pabiidiijies.

Pievienoju savu versiju prieksh PIC MCU. Gan C,gan ASM :

ASM…:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
;|||||||||||||||||||||||| LCD vadiibas rutiinas ||||||||||||||||||||||||||||||||||||||||||||||||
;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
clear_display
movlw 0x01
call write_command
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

write_data
bcf lcdE

movwf hi_nibble
movwf lo_nibble

movlw b'00001111'
andwf lo_nibble,f ;saglabaa lower nibble(pusbaits)

movlw b'11110000'
andwf hi_nibble,f ;saglabaa high nibble
swapf hi_nibble,f; pusbaits porta pin0-pin3

call read_BF

bsf lcdRS;dati
movf lcd_port,w
andlw b'11110000'; notiira TIKAI lcd datu i/o pinus
iorwf hi_nibble,w
movwf lcd_port

bsf lcdE
nop
nop
bcf lcdE

movf lcd_port,w
andlw b'11110000'; notiira TIKAI lcd datu i/o pinus
iorwf lo_nibble,w
movwf lcd_port

bsf lcdE
nop
nop
bcf lcdE
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
read_BF; lasa busy flag
bcf lcdRS;komanda
bsf status,rp0                          ;uz bank1
bsf lcd_tris,3
bsf lcd_tris,2
bsf lcd_tris,1
bsf lcd_tris,0
bcf status,rp0

bf_loop
bcf lcdRS
bsf lcdRW ;R=1, W=0/lasiishanas reziims

bsf lcdE
movf lcd_port,w
movwf lcd_status
bcf lcdE;sanjem lo nibble

nop
nop

bsf lcdE

nop
nop

bcf lcdE;sanjem hi_nibble (satur BF )

btfss lcd_status,3; Ja BF=1 - aiznjemts. Gaidiit, kad BF=0
goto gatavs
goto bf_loop

gatavs
bcf lcdRW;R=1, W=0/rakstiishanas reziims

bsf status,rp0                        ;uz bank1
bcf lcd_tris,3
bcf lcd_tris,2
bcf lcd_tris,1
bcf lcd_tris,0
bcf status,rp0
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
write_command
bcf lcdE
bcf lcdRS;komanda

movwf hi_nibble
movwf lo_nibble

movlw b'00001111'
andwf lo_nibble,f ;saglabaa lower nibble(pusbaits)

movlw b'11110000'
andwf hi_nibble,f ;saglabaa high nibble
swapf hi_nibble,f ;pusbaits vienmeer porta bit0-bit3

call read_BF

movf lcd_port,w
andlw b'11110000'; notiira TIKAI lcd datu i/o pinus
iorwf hi_nibble,w
movwf lcd_port

bsf lcdE
nop
nop
bcf lcdE

movf lcd_port,w
andlw b'11110000'; notiira TIKAI lcd datu i/o pinus
iorwf lo_nibble,w
movwf lcd_port

bsf lcdE
nop
nop
bcf lcdE
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LCD_init ; 4 bit mode
bcf lcdRW

call delay_5ms ;pagaida, lai LCD iesleedzas
call delay_5ms
call delay_5ms
call delay_5ms

movlw b'00000011'
call write8bit

movlw b'00000011'
call write8bit

movlw b'00000011'
call write8bit

movlw b'00000010';Function set (Set interface to be 4 bits long.)
call write8bit

movlw b'00101000' ; ;4-bit interface, 2-line displ, 5*8 punkti
call write_command

movlw	B'00001000'	; Display off
call write_command

movlw	B'00000001'	;Display clear
call write_command

;entry mode set
movlw b'00000110' ;clear display
call write_command

;display on/off control
movlw b'00001100' ; kursors -off,displejs-on, blinking-off
call write_command

return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
write8bit
bcf lcdE
bcf lcdRS
movwf lcd_port
bsf lcdE
nop
nop
bcf lcdE
call delay_5ms
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
delay_5ms
;4998 cycles
movlw	0xE7
movwf	d1
movlw	0x04
movwf	d2
Delay_2
decfsz	d1, f
goto	$+2
decfsz	d2, f
goto	Delay_2
;2 cycles
goto	$+1
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

un C…

#define lcdE RD5 //edge trigered. 1-->0
#define lcdRW RD7 //0-write, 1-read
#define lcdRS RD6 //0-command, 1-data
#define lcd_port PORTD
#define lcd_tris PORTD
#define asm_comm_hi &comm_hi

void write8bit( char lcd8bit_comm );
void write_lcd( char lcd_command,char data_command);//ja data_command=1, dati, ja 0 tad komanda
void test_BF(void);
void delay_5ms(void);
void izvadiit(char virkne[]);
//----------------------------------------------------------------------------------------
void init(void)
{

TRISD = 0b00000000;
TRISB = 0b00011111;
}
//---------------------------------------------------------------------------------
void lcd_init(void)//lcd inicializaacija
{
lcdRW=0;

delay_5ms();
delay_5ms();
delay_5ms();
delay_5ms();

write8bit(0b00000011);
write8bit(0b00000011);
write8bit(0b00000011);
write8bit(0b00000010);
write_lcd(0b00101000,0);
write_lcd(0b00001000,0);
write_lcd(0b00000001,0);
write_lcd(0b00000110,0);
write_lcd(0b00001101,0);
}
//--------------------------------------------------------------------------------------------------------------
void write8bit( char lcd8bit_comm )//init laikaa,kad veel ir 8bit mode, un nevar BF paarbaudiit, komandas jaaraksta ar sho
{
lcdE=0;
lcdRS=0;
lcd_port=lcd8bit_comm;
lcdE=1;
NOP();
lcdE=0;
delay_5ms();
}
//---------------------------------------------------------------------------------------------------------------------------------

void write_lcd(char lcd_comm,char data_command) //suuta datus/komanndas uz lcd
{
char comm_lo,comm_hi,comm_temp;
if (data_command==1)//ja data_command=1, dati, ja 0 tad komanda
{
test_BF();//shaadi vajag,jo test_BF nomet lcsRS. vajg ustaadiit peec tam
lcdRS=1;
}
else
{
test_BF();
}
lcdE=0;

comm_lo=lcd_comm;
comm_hi=lcd_comm;
comm_lo&=0b00001111; //and
comm_hi&=0b11110000;
//comm_hi=(comm_hi<<4) | (comm_hi>>4);//swapf comm_hi,f
asm("SWAPF 0x76,F");
comm_temp=lcd_port;//izvada pusbaitus,saglabaajot paareejos bitus
comm_temp&=0b11110000;
comm_hi=comm_hi|comm_temp;
lcd_port=comm_hi;

lcdE=1;
NOP();
lcdE=0;

comm_temp=lcd_port;
comm_temp&=0b11110000;
comm_lo=comm_lo|comm_temp;
lcd_port=comm_lo;

lcdE=1;
NOP();
lcdE=0;

}
//----------------------------------------------------------------------------------------------
void test_BF(void)//gaida, kad lcd gatavs pienjemt naakamo komandu
{
char bf_temp;
lcdRS=0;
TRISD=0b00001111;//paarsleedz uz ieejaam
lcdRW=1;//lasiishanas rezh
while(1)//gaida kameer BF nometiisies
{
lcdE=1;
bf_temp=PORTD;
lcdE=0;

NOP();

lcdE=1;
NOP();
lcdE=0;
NOP();
bf_temp&=0b00001000;
if (bf_temp==0)
break;
}

lcdRW=0;//atpakalj uz raktiishanas rezh.
TRISD=0b00000000;
}
//----------------------------------------------------------------------------------------
void delay_5ms(void)//vajag kaa atsevisku funkciju, jo ja lietotu pliku dalay macro, tad katrreiz tiktu gjenereets pilns kods
{
__delay_ms(5);
}
//----------------------------------------------------------------------------------------
void izvadiit(char virkne[])//izvada masiivus uz LCD
{
char i=0;
while(virkne[i]!=0)//kameer masiiva elements nav 0,izvadiit
{
write_lcd(virkne[i],1);
i++;
}
}

3 rating, 3 votes3 rating, 3 votes (+3 punkti, 3 vērtējumi)
Loading ... Loading ...

9 komentāri »

  • marts4 said:

    Kā var tā rakstīt? Katrs teikums savā stilā, kopēji pa teikumam?
    Veidojot rakstu varēji jau pacensties normāli visu sarakstīt.

  • Maarchels (author) said:

    Atshkiriibaa no 90% shejienes rakstu shis nav ne no kaa kopeets.
    Stils taapeec, ka dalju rakstiiju Wordaa (automaatiski labo aa sh utt…) un dalju seit pat!

  • marts4 said:

    tapatvareeejiiemaaciitiesrakstiiitnormaaali.

  • Maarchels (author) said:

    Pieradu taa rakstiit, kad saaku taa pamatiigi programmeet. Pirms tam raktiiju “normaali” :)
    Nu ko padariisi…:)

  • ATmega0 said:

    Vai par grafiskajiem ekrāniem zini tikpat labi? Es vēl tikai mācos. Bet uz 16×2 esmu PRO. Esmu pat sataisījis spēlīti uz 16×2. Būtu labi, ja kāds varētu paskaidrot, kā vadīt grafisko. Māku tādu vadīt tikai virtuāli uz Proteus ISIS. (Tev pirmā bilde no ISIS :D) Vienkāršāk ir ar Arduino. Tur ir jau gatavas bibliotekas, bet šitā arī var.

  • Maarchels (author) said:

    Diemzheel pats arii tikai maacos. :)
    Ir doma nopirkt ebajaa grafisko par ~7ls un iemaaciities. Man patiik,ka vinjiem ir seriaalais interfeiss – veel mazaak vadi!
    Jaa, Proteus – ljoti noderiiga programma. :)

    Nu raksta info var izmantot un implementeet ar jebkuru mikro. Panjemt gatavu nav interesanti :D

  • ATmega0 said:

    Lūk arī piemērs ar GLCD:

  • Maarchels (author) said:

    Jauki!

    Izskataas, ka paraleelais interfeiss tavam. Un peec kaada instrukciju/komandu apraksta programmeeji?
    Pats driizumaa paspeeleeshos ar 128*64 grafisko.

  • KasparsL said:

    Šeit vēl var pasmelties kā pieslēgt un vadīt, izmantojot Arduino vidi. http://www.ladyada.net/learn/l…..arlcd.html

Leave your response!

You must be logged in to post a comment.


Sākums | Visi Raksti | DIY Raksti | Pasākumi | Noteikumi | Forums
© 2010 Argus Radiodetaļu Tirdzniecība SIA | Web izstrāde Kārlis Baumanis