Podrobnější informace o LCD display s řadičem HD44780 najdete na:
www.hw.cz/docs/lcd_iq_displaye/lcd_iq_dip.html
,
ouwehand.net/~peter/lcd/lcd.shtml nebo
www.cmail.cz/doveda/lcd/
Katalogový list lze stáhnout z: www.cmail.cz/doveda/lcd/hd44780u.pdf
- Vývojová deska PIC + XILINX s obvody PIC16F877A a XC9572XL nebo XC95144XL.
- Můžete si LCD display připojit i na LPT port počítače.
První kód je napsán v assembleru ve vývojovém prostředí MPLAB pro jednočipový mikrořadič PIC16F84. Druhý program pro ovládání LCD displaye s řadičem HD44780 je taktéž napsán ve stejném vývojovém prostředí ale je použit jazyk C. Jednočipový mikrořadič je použit PIC16F877A. Jako kompilátor céčka je použit HI-TECH PICC, který se dá jako demo stáhnout z: www.htsoft.com demo je u některých PICu omezena jen na 2KB kódu.
Zdrojové kódy pro PIC16F877A v céčku si můžete stáhnout z: Vyvojova deska PIC + XILINX zdrojak pro PIC
Kód v assembleru...
; ; Čtyřbitová komunikace LCD display s radičem HD44780 a mikrořadiče PIC16F84.
;
; Dne 19.5.2001
;
; Pavel Procházka
; hacesoft@mujmail.cz
; www.prochazka.zde.cz
#include "P16F84.INC"
list p=16F84, f=INHX8M, r=DEC
; Z portu B je volný pouze bit 0. Ostatní vývody portu B používá LCD display.
;Port A je celý volný.
;K ovládání Portu B bitu 0 používejte instrukce BCF PORTB,0 a BSF PORTB,0.
;K nastavení tohoto bitu jako vstupní/výstupní použijte následující sekvenci:
; BCF nebo BSF reg_trisb,0
; MOVf reg_trisb,w
; TRIS PORTB
; Za podmínky že poběží v přerušení.
; Pokud nebudete používat přerušení stačí, aby bity co používá LCD display
;byli nastavenu jako výstupní. Ale musíte konfiguraci zapsat i do registru
;'reg_trisb' jinak po provedení jakéhokoliv příkazu s LCD displayem bude
;bit 0 porty B nastaven jako výstupní (základní nastavení). Pokud Vám
;bude stačit, aby bit 0 portu B byl jen výstupní, tak nic nemusíte
;konfigurovat.
; S portem A můžete nakládat jakkoliv.
;
; Zapojeni LCD displae: vývod PICu vývod LCD
; PORTB 1 RS - vyber reg.
; PORTB 2 RW - read/write
; PORTB 3 E - enable
; PORTB 4 DB4
; PORTB 5 DB5
; PORTB 6 DB6
; PORTB 7 DB7
; Vývody DB0 až DB3 z LCD displaye připojit na 0V.
LCD_TEMP equ 0x020 ; hodnota, která se ma poslat do LCD
reg_trisb equ 0x021 ; hodnota, která se vyšle na TRISB
DELAY equ 0x022 ; Used in DELAYxxx routines
X_DELAY equ 0x023 ; Used in X_DELAYxxx routines
#define e PORTB,3
#define rw PORTB,2
#define rs PORTB,1
start ORG 0x0000
DEMO
call LCDINIT ;inicializace LCD display
movlw 35h
call LCDPUTCHAR
movlw 36h
call LCDPUTCHAR
movlw 37h
call LCDPUTCHAR
movlw 38h
call LCDPUTCHAR
DEMO1 goto DEMO1
; inicializace LCD displae.
LCDINIT
clrf reg_trisb
MOVLW 0x01E
CALL X_DELAY500 ; 30 * 0.5mS = 15mS
;***************** Nastaveni 8-bitové komunikace ***************************
MOVLW 0x030 ; 8-bit-interface
call SENDPRIKAZ
;*************** Nastaveni 4-bitové komunikace *****************************
MOVLW 0x020 ; 4-bit-interface
call SENDPRIKAZ
;***************************************************************************
MOVLW 0x028 ; 4-bit-interface, 2-lines
CALL LCDPUTCMD
MOVLW 0x008 ; disp.off, curs.off, no-blink
CALL LCDPUTCMD
MOVLW 0x001 ;lcd smazat
CALL LCDPUTCMD
MOVLW 0x00C ; disp.on, curs.off
CALL LCDPUTCMD
MOVLW 0x006 ; Inkrementace, normální mód.
CALL LCDPUTCMD
RETURN
SENDPRIKAZ
CALL LCDBUSY ; Wait for LCD to be ready
BCF rw
BCF rs
BSF e
call Zapis_w ; Zápis reg. W na PortB.
BCF e
return
; Čeká až Display dodělá příkaz. Obsah reg. W se touto rutinou nemění!
LCDBUSY
movwf LCD_TEMP ; Ulož reg. W do LCD_TEMP
movf reg_trisb,w
andlw b'00001111'
iorlw b'11110000' ; Byty 4 až 7 brány B jsou vstupní.
movwf reg_trisb
tris PORTB
lcd_busy
BCF rs
BSF rw
BSF e
movf PORTB,w ; Read busy flag + DDram address
BCF e
BSF e
BCF e
andlw b'10000000' ; Test na BF příznak.
BTFSS STATUS,Z
goto lcd_busy
bcf rw
movf reg_trisb,w
andlw b'00001111' ; Byty 4 az 7 brány B jsou výstupní.
movwf reg_trisb
tris PORTB
movf LCD_TEMP,w ; Obnov reg. W
return
; Pošle znak na Display.
LCDPUTCHAR
CALL LCDBUSY ; Wait for LCD to be ready
BCF rw
BSF rs
BSF e
call Zapis_w ; Zapíše reg. W na PortB.
BCF e
BSF e
swapf LCD_TEMP,f
call Zapis_w ; Zapíše reg. W na PortB.
BCF e
RETURN
; Pošle příkaz na Display.
LCDPUTCMD
call SENDPRIKAZ
BSF e
swapf LCD_TEMP,f
call Zapis_w ; Zapise reg. W na PortB.
BCF e
return
; Prekopiruje obsah reg. LED_TEMP bity 4 až 7 na PORTB bity 4 až 7.
Zápis_w
movlw b'00001111'
andwf PORTB,f
; Vynuluje bity 4 az 7 portub, výsledek uloží do portb.
movlw b'11110000'
andwf LCD_TEMP,w
; Vynuluje bity 0 az 3 lcd_temp, výsledek uloží do w.
iorwf PORTB,f
; OR mezi w a potrb, výsledek uloží do portb.
return
;*********************************** a 500uS delay @ 4MHz X-tal
DELAY500
MOVLW D'165' ; +1 1 cycle
MOVWF DELAY ; +2 1 cycle
DELAY500_LOOP
DECFSZ DELAY, F ; step1 1 cycle
GOTO DELAY500_LOOP ; step2 2 cycles
DELAY500_END
RETURN ; +3 2 cycles
;*********************************** a delay of 'W' * 500mS
X_DELAY500
MOVWF X_DELAY ; +1 1 cycle
X_DELAY500_LOOP
CALL DELAY500 ; step1 wait 500uSec
DECFSZ X_DELAY, F ; step2 1 cycle
GOTO X_DELAY500_LOOP ; step3 2 cycles
X_DELAY500_END
RETURN ; +2 2 cycles
end
Kód v Céčku...
//hacesoft
//www.prochazka.zde.cz
//6.11.2005
//Ovládaní LCD DISPLAYe ve vývojové desce PIC + XILINX
//Která se nachází na www.prochazka.zde.cz
//Fyzické zapojeni LCD k PICu 16F877A
//RE0 ...RS -> vyber reg.
//RE1 ...RW -> read/write
//RB3 ...EN1 -> ENABLE LCD
//RB1 ...DB4
//RB2 ...DB5
//RB4 ...DB6
//RB5 ...DB7
#include "pic.h"
#include "pic168xa.h"
#include "LCD_vyvojova_deska.h"
#define XTAL_FREQ 20MHZ
#include "delay.c"
#include "stdio.h"
#include "ctype.h"
#include "string.h"
__CONFIG (HS & WDTDIS & BORDIS & LVPDIS); //Konfiguracni slovo
__IDLOC (1); //verze SW
#define BF_FLAG (false); //FALSE=Cekaci smyska. TRUE=Cekani na prinzak BF z displye.
static bit EN @ ((unsigned)&PORTE*8+2);
static bit LCD_RW @ ((unsigned)&PORTE*8+1);
static bit LCD_RS @ ((unsigned)&PORTE*8+0);
static bit LCD_EN @ ((unsigned)&PORTB*8+3);
static bit LCD_BF @ ((unsigned)&PORTB*8+5);
static bit DB4 @ ((unsigned)&PORTB*8+1);
static bit DB5 @ ((unsigned)&PORTB*8+2);
static bit DB6 @ ((unsigned)&PORTB*8+4);
static bit DB7 @ ((unsigned)&PORTB*8+5);
unsigned char lcd_data = 0;
//----------------------------------------------------------------
void lcd_busy (void){
#if _BF_FLAG==true //Nektere displaye neposilaji informaci o dokonceni
TRISB1 = 1; //Nastavani RB1 na vstupni PIN
TRISB2 = 1; //Nastavani RB2 na vstupni PIN
TRISB4 = 1; //Nastavani RB4 na vstupni PIN
TRISB5 = 1; //Nastavani RB5 na vstupni PIN
asm ("xxx: nop");
//for(;;) {
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
asm ("movf _PORTB,w");
LCD_EN = 0;
LCD_EN = 1;
LCD_EN = 0;
asm ("andlw _LCD_BF"); //Test na BF příznak.
asm ("btfsc _STATUS,2"); //TEST na ZERO
asm ("goto xxx"); //TEST na ZERO
// }
LCD_RW = 0;
TRISB1 = 0; //Nastavani RB1 na vystupní PIN
TRISB2 = 0; //Nastavani RB2 na vystupní PIN
TRISB4 = 0; //Nastavani RB4 na vystupní PIN
TRISB5 = 0; //Nastavani RB5 na vystupní PIN
#else
DelayMs(9);
#endif
}
//----------------------------------------------------------------
void send_prikaz (unsigned char bCommand){
lcd_data = bCommand;
lcd_busy();
LCD_RW = 0;
LCD_RS = 0;
LCD_EN = 1;
zapis_w();
LCD_EN = 0;
}
//----------------------------------------------------------------
void lcd_init(void){
//Pro jistotu se provede několikrát inicializace
DelayMs(255);
lcd_init1();
DelayMs(255);
lcd_init1();
DelayMs(255);
lcd_init1();
DelayMs(255);
lcd_init1();
DelayMs(255);
lcd_init1();
}
void lcd_init1(void){
//inicializace LCD displye
//unsigned trisb;
TRISB = (0b11000001 & TRISB) | 0b00000000;
//nastaveni portu B bity 3 až 7 na výstupní
//ostatní nechá nezměněny.
TRISE0 = 0; //RS -> data ven
TRISE1 = 0; //RW -> data ven
ADCON1 = 12;
//PortA je nastaven jako vstup analog a
//RE0 až 2 jsou nastaveny datové piny.
DelayMs(100);
//***************** Nastaveni 8-bitové komunikace ***************************
//8-bit-interface
send_prikaz(0x03);
DelayMs(100);
//*************** Nastaveni 4-bitové komunikace *****************************
//4-bit-interface
send_prikaz(0x02);
DelayMs(100);
//***************************************************************************
//4-bit-interface, 2-lines
lcd_put_cmd (0x28);
//lcd_put_cmd (0b00100000);
//disp.off, curs.off, no-blink
lcd_put_cmd (0x08);
//lcd smazat
lcd_put_cmd (0x01);
//disp.on, curs.off
lcd_put_cmd (0x0c);
//Inkrementace, normalni mod.
lcd_put_cmd (0x06);
}
//----------------------------------------------------------------
void zapis_w(void){
//zkopirovat 4 az 7 bity z registru lcd_data na porty B.
//RB1 ...DB4 ... bit4 registru lcd_data
//RB2 ...DB5 ... bit5 registru lcd_data
//RB4 ...DB6 ... bit6 registru lcd_data
//RB5 ...DB7 ... bit7 registru lcd_data
#asm
bcf _PORTB,1
bcf _PORTB,2
bcf _PORTB,4
bcf _PORTB,5
btfsc _lcd_data,4
bsf _PORTB,1
btfsc _lcd_data,5
bsf _PORTB,2
btfsc _lcd_data,6
bsf _PORTB,4
btfsc _lcd_data,7
bsf _PORTB,5
#endasm
}
//----------------------------------------------------------------
void lcd_put_char (unsigned char sString)
{
//Pošle znak na Display.
lcd_data = sString;
lcd_busy();
LCD_RW = 0;
LCD_RS = 1;
LCD_EN = 1;
zapis_w();
LCD_EN = 0;
LCD_EN = 1;
asm ("swapf _lcd_data , f");
zapis_w();
LCD_EN = 0;
}
//----------------------------------------------------------------
void lcd_scroll(char Direction)
//Pohybuje celým displayem. Toto je funkce LCD (HW)
{
if(Direction==SCROLL_LEFT)
{
lcd_put_cmd(0b00011000); //Scroll LEFT
}
else
{
lcd_put_cmd(0b00011100); //Scroll RIGHT
}
}
//----------------------------------------------------------------
void ScrollMessage(unsigned char pozice, unsigned char radek,const char Message[])
//Pohybuje textem na zvoleném řádku od zadané pozice.
{
char TempS[20];
unsigned int MHead=0,Done=0,count;
while(Done==0)
{
for(count=0;count<20;count++)
{
TempS[count]=Message[MHead+count];
if(Message[MHead+count+1]==0) Done=1;
}
MHead++;
lcd_goto(pozice, radek);
lcd_string(TempS);
DelayMs(250);
}
}
//----------------------------------------------------------------
void lcd_goto(unsigned char pozice, unsigned char radek)
{
if(radek >1) radek=1;
lcd_put_cmd(((radek * 40) + 0x80)+ pozice);
}
//----------------------------------------------------------------
void lcd_string(const char * s)
{
while(*s)
lcd_put_char(*s++);
}
//----------------------------------------------------------------
void lcd_put_cmd (unsigned char bCommand)
{
//Posle prikaz na Display.
//asm ("movwf _lcd_data");
send_prikaz (bCommand);
LCD_EN = 1;
asm ("swapf _lcd_data , f");
zapis_w();
LCD_EN = 0;
}
//----------------------------------------------------------------
main(void){
unsigned char loop;
lcd_init();
for(;;) {
ScrollMessage(0,0," Vita Vas Vyvojova deska PIC+XILINX ");
lcd_cls;
lcd_goto(0,1);
lcd_string("Verze SW: 1.0.4.");
ScrollMessage(0,0," Ze dne: 6. listopadu, 2005. ");
ScrollMessage(0,0," Veskera dokumentace teto demonstracni desky se da stahnout z: ");
for (loop = 0; loop < 10; loop++){
lcd_goto(0,1);
lcd_string("prochazka.zde.cz");
DelayMs(250);
DelayMs(250);
DelayMs(250);
lcd_goto(0,1);
lcd_string(" ");
DelayMs(250);
DelayMs(250);
DelayMs(250);
}
lcd_goto(0,0);
lcd_string("prochazka.zde.cz");
lcd_goto(0,1);
lcd_string(" ----ahoj---- ");
for (loop = 0; loop < 5; loop++){
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
lcd_scroll(SCROLL_LEFT);
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
}
for (loop = 0; loop < 5; loop++){
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
lcd_scroll(SCROLL_RIGHT);
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
}
lcd_cursor_home;
lcd_string("prochazka.zde.cz");
ScrollMessage(0,1," Uvitaci program vyvojoveho kitu PIC16F887A + XILINX XC9572XL. Zelenim tlacitkem se zvysuje hodnota na LED display a Modrim se hodnota Na LED display zmensuje. Zluta tlacitka ovladaji LED diody. Prepinace zapinaji a vypinaji blikani LED diod. Pokud je zapnuto blikani a stisknuto zlute tlacitko, tak LED dioda nesviti ale blika!!! ");
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
lcd_cls;
}
}
Komentáře
Nebyly přidány žádné komentáře.