PTM – LCD

TESTY

Proste programy testowe LCD dla mikrokontrolera 8051
📝 Test 1 - Wyświetlenie pojedynczego znaku

assembly

;==============================================================
; TEST 1: Wyświetlenie jednego znaku 'X' na LCD
; Cel: Sprawdzenie czy LCD działa poprawnie
;==============================================================

ljmp start

LCDstatus equ 0FF2EH
LCDcontrol equ 0FF2CH
LCDdataWR equ 0FF2DH

#define INITDISP 0x38
#define LCDON 0x0e
#define CLEAR 0x01

org 0100H

; --- MAKRA ---
LCDcntrlWR MACRO x
LOCAL loop
loop: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,loop
MOV DPTR,#LCDcontrol
MOV A, x
MOVX @DPTR,A
ENDM

LCDcharWR MACRO
LOCAL tutu
PUSH ACC
tutu: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,tutu
MOV DPTR,#LCDdataWR
POP ACC
MOVX @DPTR,A
ENDM

init_LCD MACRO
LCDcntrlWR #INITDISP
LCDcntrlWR #CLEAR
LCDcntrlWR #LCDON
ENDM

; --- PROGRAM GŁÓWNY ---
start:
init_LCD ; Inicjalizacja LCD

mov a, #'X' ; Załaduj znak 'X' do akumulatora
LCDcharWR ; Wyświetl znak

jmp $ ; Zatrzymaj program
end start

Wynik na LCD:

text

┌────────────────┐
│X │
│ │
└────────────────┘

📝 Test 2 - Wyświetlenie tekstu w obu liniach

assembly

;==============================================================
; TEST 2: Tekst w linii 1 i linii 2
; Cel: Test przełączania między liniami LCD
;==============================================================

ljmp start

LCDstatus equ 0FF2EH
LCDcontrol equ 0FF2CH
LCDdataWR equ 0FF2DH

#define HOME 0x80
#define INITDISP 0x38
#define HOM2 0xc0
#define LCDON 0x0e
#define CLEAR 0x01

org 0100H

; --- TEKSTY ---
linia1: db "Linia 1 - gora",00
linia2: db "Linia 2 - dol",00

; --- MAKRA ---
LCDcntrlWR MACRO x
LOCAL loop
loop: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,loop
MOV DPTR,#LCDcontrol
MOV A, x
MOVX @DPTR,A
ENDM

LCDcharWR MACRO
LOCAL tutu
PUSH ACC
tutu: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,tutu
MOV DPTR,#LCDdataWR
POP ACC
MOVX @DPTR,A
ENDM

init_LCD MACRO
LCDcntrlWR #INITDISP
LCDcntrlWR #CLEAR
LCDcntrlWR #LCDON
ENDM

; --- FUNKCJE ---
putcharLCD:
LCDcharWR
ret

putstrLCD:
clr a
movc a, @a+dptr
jz koniec
push dph
push dpl
acall putcharLCD
pop dpl
pop dph
inc dptr
sjmp putstrLCD
koniec: ret

; --- PROGRAM GŁÓWNY ---
start:
init_LCD

; Wyświetl tekst w linii 1
LCDcntrlWR #HOME ; Kursor na początek linii 1
mov dptr, #linia1
acall putstrLCD

; Wyświetl tekst w linii 2
LCDcntrlWR #HOM2 ; Kursor na początek linii 2
mov dptr, #linia2
acall putstrLCD

jmp $
end start

Wynik na LCD:

text

┌────────────────┐
│Linia 1 - gora │
│Linia 2 - dol │
└────────────────┘

📝 Test 3 - Wypełnienie całego LCD

assembly

;==============================================================
; TEST 3: Wypełnienie całego wyświetlacza znakami
; Cel: Test wszystkich 32 pozycji (16x2)
;==============================================================

ljmp start

LCDstatus equ 0FF2EH
LCDcontrol equ 0FF2CH
LCDdataWR equ 0FF2DH

#define HOME 0x80
#define INITDISP 0x38
#define HOM2 0xc0
#define LCDON 0x0e
#define CLEAR 0x01

org 0100H

; --- MAKRA ---
LCDcntrlWR MACRO x
LOCAL loop
loop: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,loop
MOV DPTR,#LCDcontrol
MOV A, x
MOVX @DPTR,A
ENDM

LCDcharWR MACRO
LOCAL tutu
PUSH ACC
tutu: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,tutu
MOV DPTR,#LCDdataWR
POP ACC
MOVX @DPTR,A
ENDM

init_LCD MACRO
LCDcntrlWR #INITDISP
LCDcntrlWR #CLEAR
LCDcntrlWR #LCDON
ENDM

; --- PROGRAM GŁÓWNY ---
start:
init_LCD

; Linia 1: 16 znaków 'A'
LCDcntrlWR #HOME
mov r0, #16 ; Licznik: 16 znaków
fill1:
mov a, #'A'
LCDcharWR
djnz r0, fill1

; Linia 2: 16 znaków 'B'
LCDcntrlWR #HOM2
mov r0, #16
fill2:
mov a, #'B'
LCDcharWR
djnz r0, fill2

jmp $
end start

Wynik na LCD:

text

┌────────────────┐
│AAAAAAAAAAAAAAAA│
│BBBBBBBBBBBBBBBB│
└────────────────┘

📝 Test 4 - Liczby i znaki specjalne

assembly

;==============================================================
; TEST 4: Wyświetlanie cyfr 0-9 i znaków specjalnych
; Cel: Test różnych kodów ASCII
;==============================================================

ljmp start

LCDstatus equ 0FF2EH
LCDcontrol equ 0FF2CH
LCDdataWR equ 0FF2DH

#define HOME 0x80
#define INITDISP 0x38
#define HOM2 0xc0
#define LCDON 0x0e
#define CLEAR 0x01

org 0100H

; --- MAKRA ---
LCDcntrlWR MACRO x
LOCAL loop
loop: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,loop
MOV DPTR,#LCDcontrol
MOV A, x
MOVX @DPTR,A
ENDM

LCDcharWR MACRO
LOCAL tutu
PUSH ACC
tutu: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,tutu
MOV DPTR,#LCDdataWR
POP ACC
MOVX @DPTR,A
ENDM

init_LCD MACRO
LCDcntrlWR #INITDISP
LCDcntrlWR #CLEAR
LCDcntrlWR #LCDON
ENDM

; --- PROGRAM GŁÓWNY ---
start:
init_LCD

; Linia 1: Cyfry 0-9
LCDcntrlWR #HOME
mov a, #'0' ; Kod ASCII '0' = 0x30
mov r0, #10 ; 10 cyfr
cyfry:
LCDcharWR
inc a ; Następna cyfra
djnz r0, cyfry

; Linia 2: Znaki specjalne
LCDcntrlWR #HOM2
mov a, #'!'
LCDcharWR
mov a, #'@'
LCDcharWR
mov a, #'#'
LCDcharWR
mov a, #'$'
LCDcharWR
mov a, #'%'
LCDcharWR
mov a, #'^'
LCDcharWR
mov a, #'&'
LCDcharWR
mov a, #'*'
LCDcharWR

jmp $
end start

Wynik na LCD:

text

┌────────────────┐
│0123456789 │
│!@#$%^&* │
└────────────────┘

📝 Test 5 - Test opóźnienia i czyszczenia

assembly

;==============================================================
; TEST 5: Naprzemienne wyświetlanie dwóch tekstów
; Cel: Test funkcji CLEAR i opóźnienia
;==============================================================

ljmp start

LCDstatus equ 0FF2EH
LCDcontrol equ 0FF2CH
LCDdataWR equ 0FF2DH

#define HOME 0x80
#define INITDISP 0x38
#define LCDON 0x0e
#define CLEAR 0x01

org 0100H

; --- TEKSTY ---
tekst_a: db "=== TEST A ===",00
tekst_b: db "=== TEST B ===",00

; --- MAKRA ---
LCDcntrlWR MACRO x
LOCAL loop
loop: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,loop
MOV DPTR,#LCDcontrol
MOV A, x
MOVX @DPTR,A
ENDM

LCDcharWR MACRO
LOCAL tutu
PUSH ACC
tutu: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,tutu
MOV DPTR,#LCDdataWR
POP ACC
MOVX @DPTR,A
ENDM

init_LCD MACRO
LCDcntrlWR #INITDISP
LCDcntrlWR #CLEAR
LCDcntrlWR #LCDON
ENDM

; --- FUNKCJE ---
delay:
mov r0, #10H
d1: mov r1, #0FFH
d2: mov r2, #0FFH
d3: djnz r2, d3
djnz r1, d2
djnz r0, d1
ret

putcharLCD:
LCDcharWR
ret

putstrLCD:
clr a
movc a, @a+dptr
jz done
push dph
push dpl
acall putcharLCD
pop dpl
pop dph
inc dptr
sjmp putstrLCD
done: ret

; --- PROGRAM GŁÓWNY ---
start:
init_LCD

petla:
; Wyświetl tekst A
LCDcntrlWR #CLEAR
LCDcntrlWR #HOME
mov dptr, #tekst_a
acall putstrLCD
acall delay

; Wyświetl tekst B
LCDcntrlWR #CLEAR
LCDcntrlWR #HOME
mov dptr, #tekst_b
acall putstrLCD
acall delay

sjmp petla ; Powtarzaj w nieskończoność

end start

Wynik na LCD (animacja):

text

┌────────────────┐ ┌────────────────┐
│=== TEST A === │ ──► │=== TEST B === │ ──► (powtarza)
│ │ │ │
└────────────────┘ └────────────────┘

📝 Test 6 - Prosty licznik

assembly

;==============================================================
; TEST 6: Licznik 0-9 na LCD
; Cel: Test pętli i wyświetlania zmieniających się wartości
;==============================================================

ljmp start

LCDstatus equ 0FF2EH
LCDcontrol equ 0FF2CH
LCDdataWR equ 0FF2DH

#define HOME 0x80
#define INITDISP 0x38
#define LCDON 0x0e
#define CLEAR 0x01

org 0100H

tekst: db "Licznik: ",00

; --- MAKRA ---
LCDcntrlWR MACRO x
LOCAL loop
loop: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,loop
MOV DPTR,#LCDcontrol
MOV A, x
MOVX @DPTR,A
ENDM

LCDcharWR MACRO
LOCAL tutu
PUSH ACC
tutu: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,tutu
MOV DPTR,#LCDdataWR
POP ACC
MOVX @DPTR,A
ENDM

init_LCD MACRO
LCDcntrlWR #INITDISP
LCDcntrlWR #CLEAR
LCDcntrlWR #LCDON
ENDM

; --- FUNKCJE ---
delay:
mov r0, #0AH
d1: mov r1, #0FFH
d2: mov r2, #0FFH
d3: djnz r2, d3
djnz r1, d2
djnz r0, d1
ret

putcharLCD:
LCDcharWR
ret

putstrLCD:
clr a
movc a, @a+dptr
jz done
push dph
push dpl
acall putcharLCD
pop dpl
pop dph
inc dptr
sjmp putstrLCD
done: ret

; --- PROGRAM GŁÓWNY ---
start:
init_LCD

licznik_loop:
mov r3, #'0' ; Rozpocznij od '0'

next_digit:
LCDcntrlWR #HOME
mov dptr, #tekst
acall putstrLCD

mov a, r3 ; Aktualna cyfra
LCDcharWR

acall delay

inc r3 ; Następna cyfra
cjne r3, #'9'+1, next_digit ; Jeśli nie przekroczono '9'

sjmp licznik_loop ; Zacznij od nowa

end start

Wynik na LCD (animacja):

text

Licznik: 0 → Licznik: 1 → ... → Licznik: 9 → Licznik: 0 (powtarza)

📝 Test 7 - Biegający znak

assembly

;==============================================================
; TEST 7: Animacja - znak przesuwający się po LCD
; Cel: Test pozycjonowania kursora
;==============================================================

ljmp start

LCDstatus equ 0FF2EH
LCDcontrol equ 0FF2CH
LCDdataWR equ 0FF2DH

#define HOME 0x80
#define INITDISP 0x38
#define HOM2 0xc0
#define LCDON 0x0e
#define CLEAR 0x01

org 0100H

; --- MAKRA ---
LCDcntrlWR MACRO x
LOCAL loop
loop: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,loop
MOV DPTR,#LCDcontrol
MOV A, x
MOVX @DPTR,A
ENDM

LCDcharWR MACRO
LOCAL tutu
PUSH ACC
tutu: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,tutu
MOV DPTR,#LCDdataWR
POP ACC
MOVX @DPTR,A
ENDM

init_LCD MACRO
LCDcntrlWR #INITDISP
LCDcntrlWR #CLEAR
LCDcntrlWR #LCDON
ENDM

; --- FUNKCJE ---
delay:
mov r0, #05H
d1: mov r1, #0FFH
d2: mov r2, #0FFH
d3: djnz r2, d3
djnz r1, d2
djnz r0, d1
ret

; --- PROGRAM GŁÓWNY ---
start:
init_LCD

animacja:
; Linia 1: ruch w prawo
mov r3, #HOME ; Pozycja startowa = 0x80
mov r4, #16 ; 16 pozycji

linia1_prawo:
LCDcntrlWR #CLEAR
mov a, r3
LCDcntrlWR a ; Ustaw kursor na pozycji r3
mov a, #'>' ; Znak strzałki w prawo
LCDcharWR
acall delay
inc r3
djnz r4, linia1_prawo

; Linia 2: ruch w prawo
mov r3, #HOM2 ; Pozycja = 0xC0 (linia 2)
mov r4, #16

linia2_prawo:
LCDcntrlWR #CLEAR
mov a, r3
LCDcntrlWR a
mov a, #'>'
LCDcharWR
acall delay
inc r3
djnz r4, linia2_prawo

sjmp animacja ; Powtarzaj

end start

Wynik na LCD (animacja):

text

Linia 1: >............... → .>.............. → ..>............. → ...
Linia 2: >............... → .>.............. → ...

📊 Podsumowanie testów
Test Opis Testowana funkcja
1 Pojedynczy znak Podstawowa komunikacja z LCD
2 Dwie linie Przełączanie HOME/HOM2
3 Wypełnienie Pętla i liczniki
4 Cyfry i znaki Kody ASCII
5 Czyszczenie CLEAR + delay
6 Licznik Zmienne wyświetlanie
7 Animacja Pozycjonowanie kursora
MATRIX
;==============================================================
; PROGRAM: "Matrix Hacker" - Animacja + Zabawny tekst
; Efekt: Symulacja "deszczu matrixa" + żartobliwe komunikaty
;==============================================================

ljmp start

LCDstatus equ 0FF2EH
LCDcontrol equ 0FF2CH
LCDdataWR equ 0FF2DH

#define HOME 0x80
#define INITDISP 0x38
#define HOM2 0xc0
#define LCDON 0x0e
#define CLEAR 0x01

org 0100H

; --- TEKSTY ---
intro1: db ">>> HACKING <<<",00
intro2: db "Please wait...",00
loading: db "||||||||||||||||",00 ; Pasek postępu
hack1: db "ACCESS DENIED!",00
hack2: db "Just kidding ;)",00
joke1: db "Kawa > Kod",00
joke2: db "Debuguj to! XD",00
final1: db "*** PTM LAB ***",00
final2: db "Ocena: 5.0 ? :D",00

; Znaki do animacji (pseudo-matrix)
matrix_chars: db "|/-\|/-\",00

;==============================================================
; MAKRA (takie same jak poprzednio)
;==============================================================

LCDcntrlWR MACRO x
LOCAL loop
loop: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,loop
MOV DPTR,#LCDcontrol
MOV A, x
MOVX @DPTR,A
ENDM

LCDcharWR MACRO
LOCAL tutu
PUSH ACC
tutu: MOV DPTR,#LCDstatus
MOVX A,@DPTR
JB ACC.7,tutu
MOV DPTR,#LCDdataWR
POP ACC
MOVX @DPTR,A
ENDM

init_LCD MACRO
LCDcntrlWR #INITDISP
LCDcntrlWR #CLEAR
LCDcntrlWR #LCDON
ENDM

;==============================================================
; FUNKCJE
;==============================================================

; Krótkie opóźnienie
delay_short:
mov r0, #08H
ds1: mov r1, #0FFH
ds2: mov r2, #080H
ds3: djnz r2, ds3
djnz r1, ds2
djnz r0, ds1
ret

; Długie opóźnienie
delay_long:
mov r0, #20H
dl1: mov r1, #0FFH
dl2: mov r2, #0FFH
dl3: djnz r2, dl3
djnz r1, dl2
djnz r0, dl1
ret

; Wypisanie znaku
putcharLCD:
LCDcharWR
ret

; Wypisanie łańcucha
putstrLCD:
clr a
movc a, @a+dptr
jz str_end
push dph
push dpl
acall putcharLCD
pop dpl
pop dph
inc dptr
sjmp putstrLCD
str_end: ret

; Animacja spinnera (kręcące się kółko)
spinner:
mov r3, #08H ; 8 obrotów
spin_loop:
mov r4, #00H ; Indeks znaku
spin_char:
LCDcntrlWR #HOME ; Kursor na początek
mov a, r4
mov dptr, #matrix_chars
movc a, @a+dptr
jz spin_reset
acall putcharLCD
acall delay_short
inc r4
sjmp spin_char
spin_reset:
djnz r3, spin_loop
ret

; Animacja paska ładowania
progress_bar:
LCDcntrlWR #HOM2
mov r3, #10H ; 16 znaków
pb_loop:
mov a, #0FFH ; Pełny blok (lub użyj '#')
acall putcharLCD
acall delay_short
djnz r3, pb_loop
ret

; Efekt "migania" tekstu
blink_text:
mov r3, #03H ; 3 mignięcia
blink_loop:
LCDcntrlWR #CLEAR
acall delay_short
mov dptr, #hack1
LCDcntrlWR #HOME
acall putstrLCD
acall delay_short
djnz r3, blink_loop
ret

;==============================================================
; PROGRAM GŁÓWNY
;==============================================================

start:
init_LCD

;--- SCENA 1: Intro "Hacking" ---
mov dptr, #intro1
acall putstrLCD
LCDcntrlWR #HOM2
mov dptr, #intro2
acall putstrLCD
acall delay_long

;--- SCENA 2: Pasek ładowania ---
LCDcntrlWR #CLEAR
mov a, #'['
acall putcharLCD
mov dptr, #loading
acall putstrLCD ; Symulacja ładowania
mov a, #']'
acall putcharLCD

; Animowany pasek
LCDcntrlWR #HOM2
acall progress_bar
acall delay_long

;--- SCENA 3: "Błąd" + żart ---
acall blink_text
acall delay_short

LCDcntrlWR #HOM2
mov dptr, #hack2
acall putstrLCD
acall delay_long

;--- SCENA 4: Żarty programistyczne ---
LCDcntrlWR #CLEAR
LCDcntrlWR #HOME
mov dptr, #joke1
acall putstrLCD
LCDcntrlWR #HOM2
mov dptr, #joke2
acall putstrLCD
acall delay_long

;--- SCENA 5: Końcowy komunikat ---
LCDcntrlWR #CLEAR
LCDcntrlWR #HOME
mov dptr, #final1
acall putstrLCD
LCDcntrlWR #HOM2
mov dptr, #final2
acall putstrLCD

; Pętla nieskończona
nop
nop
jmp $

end start
ZAD1
ljmp start

LCDstatus  equ 0FF2EH       ; adres do odczytu gotowosci LCD
LCDcontrol equ 0FF2CH       ; adres do podania bajtu sterujacego LCD
LCDdataWR  equ 0FF2DH       ; adres do podania kodu ASCII na LCD

// bajty sterujace LCD, inne dostepne w opisie LCD na stronie WWW
#define  HOME     0x80     // put cursor to second line  
#define  INITDISP 0x38     // LCD init (8-bit mode)  
#define  HOM2     0xc0     // put cursor to second line  
#define  LCDON    0x0e     // LCD nn, cursor off, blinking off
#define  CLEAR    0x01     // LCD display clear

org 0100H
	
// deklaracje tekstów
	text1:  db "dwa",00
	text2:	db "jeden",00
	text3:	db "trzy",00
	text4:	db "siedem",00
		
// macro do wprowadzenia bajtu sterujacego na LCD
LCDcntrlWR MACRO x          ; x – parametr wywolania macra – bajt sterujacy
           LOCAL loop       ; LOCAL oznacza ze etykieta loop moze sie powtórzyc w programie
loop: MOV  DPTR,#LCDstatus  ; DPTR zaladowany adresem statusu
      MOVX A,@DPTR          ; pobranie bajtu z biezacym statusem LCD
      JB   ACC.7,loop       ; testowanie najstarszego bitu akumulatora
                            ; – wskazuje gotowosc LCD
      MOV  DPTR,#LCDcontrol ; DPTR zaladowany adresem do podania bajtu sterujacego
      MOV  A, x             ; do akumulatora trafia argument wywolania macra–bajt sterujacy
      MOVX @DPTR,A          ; bajt sterujacy podany do LCD – zadana akcja widoczna na LCD
      ENDM
	  
// macro do wypisania znaku ASCII na LCD, znak ASCII przed wywolaniem macra ma byc w A
LCDcharWR MACRO
      LOCAL tutu            ; LOCAL oznacza ze etykieta tutu moze sie powtórzyc w programie
      PUSH ACC              ; odlozenie biezacej zawartosci akumulatora na stos
tutu: MOV  DPTR,#LCDstatus  ; DPTR zaladowany adresem statusu
      MOVX A,@DPTR          ; pobranie bajtu z biezacym statusem LCD
      JB   ACC.7,tutu       ; testowanie najstarszego bitu akumulatora
                            ; – wskazuje gotowosc LCD
      MOV  DPTR,#LCDdataWR  ; DPTR zaladowany adresem do podania bajtu sterujacego
      POP  ACC              ; w akumulatorze ponownie kod ASCII znaku na LCD
      MOVX @DPTR,A          ; kod ASCII podany do LCD – znak widoczny na LCD
      ENDM
	  
// macro do inicjalizacji wyswietlacza – bez parametrów
init_LCD MACRO
         LCDcntrlWR #INITDISP ; wywolanie macra LCDcntrlWR – inicjalizacja LCD
         LCDcntrlWR #CLEAR    ; wywolanie macra LCDcntrlWR – czyszczenie LCD
         LCDcntrlWR #LCDON    ; wywolanie macra LCDcntrlWR – konfiguracja kursora
         ENDM

// funkcja opóznienia
	delay:	mov r0, #15H
	one:	mov r1, #0FFH
	dwa:	mov r2, #0FFH
    trzy:	djnz r2, trzy
			djnz r1, dwa
			djnz r0, one
			ret
			
// funkcja wypisania znaku
putcharLCD:	LCDcharWR
			ret
			
//funkcja wypisania lancucha znaków		
putstrLCD:  clr a
			movc a, @a+dptr
			jz koniec
			push dph
			push dpl
			acall putcharLCD
			pop dpl
			pop dph
			inc dptr
			sjmp putstrLCD
	koniec: ret

przycisk1:	LCDcntrlWR #CLEAR
		LCDcntrlWR #HOME
		mov dptr, #text1
		acall putstrLCD
		acall delay
		ljmp begin

przycisk2:	LCDcntrlWR #CLEAR
		LCDcntrlWR #HOME
		mov dptr, #text2
		acall putstrLCD
		acall delay
		ljmp begin

przycisk3:	LCDcntrlWR #CLEAR
		LCDcntrlWR #HOME
		mov dptr, #text3
		acall putstrLCD
		ljmp begin

przycisk4:	LCDcntrlWR #CLEAR
		LCDcntrlWR #HOME
		mov dptr, #text4
		acall putstrLCD
		acall delay
		ljmp begin

// program glówny
	start:	init_LCD
	
		begin: clr c
		mov a, p3
		subb a, #0cfh ; 1100 1111 - koniec
		jz finito
		mov a, p3
		subb a, #0dfh ; 1101 1111
		jnz omin1
	skok1:
		ljmp przycisk1
	omin1:
		mov a, p3
		subb a, #0efh ; 1110 1111
		jnz omin2
	skok2:
		ljmp przycisk2
	omin2:
		mov a, p3
		subb a, #0f7h ; 1111 0111
		jnz omin3
	skok3:
		ljmp przycisk3
	omin3:
		mov a, p3
		subb a, #0fbh ; 1111 1011
		jnz omin4
	skok4:
		ljmp przycisk4
	omin4:
		sjmp begin		
	
	finito: LCDcntrlWR #CLEAR				
	nop
	nop
	nop
	jmp $
	end start
ZAD2

            ljmp start

LCDstatus   equ 0FF2EH      ; adres do odczytu gotowosci LCD
LCDcontrol  equ 0FF2CH      ; adres do podania bajtu sterujacego LCD
LCDdataWR   equ 0FF2DH      ; adres do podania kodu ASCII na LCD

; bajty sterujace LCD
#define  HOME     0x80      ; kursor na poczatek linii 1
#define  INITDISP 0x38      ; LCD init (8-bit mode)
#define  HOM2     0xc0      ; kursor na poczatek linii 2
#define  LCDON    0x0e      ; LCD on, cursor off, blinking off
#define  CLEAR    0x01      ; LCD display clear

            org 0100H

; Dlugi lancuch znakow (znacznie wiecej niz 16 znakow)
long_text:  db "Witamy w laboratorium systemow mikroprocesorowych. "
            db "Pracujemy z mikrokontrolerem 80C537 firmy Siemens. "
            db "Wyswietlacz LCD HD44780 posiada dwie linie po 16 znakow. "
            db "Program demonstruje przewijanie dlugiego tekstu stronami. "
            db "To jest koniec wiadomosci - dziekujemy za uwage!",0

; Teksty koncowe
end_msg1:   db "=== KONIEC ===",0
end_msg2:   db "Tekst wyswietl.",0

; Zmienne w pamieci RAM
text_ptr_l  equ 30H         ; mlodszy bajt wskaznika tekstu
text_ptr_h  equ 31H         ; starszy bajt wskaznika tekstu

; macro do wprowadzenia bajtu sterujacego na LCD
LCDcntrlWR MACRO x
           LOCAL loop
loop:      MOV  DPTR,#LCDstatus
           MOVX A,@DPTR
           JB   ACC.7,loop
           MOV  DPTR,#LCDcontrol
           MOV  A, x
           MOVX @DPTR,A
           ENDM

; macro do wypisania znaku ASCII na LCD
LCDcharWR MACRO
          LOCAL tutu
          PUSH ACC
tutu:     MOV  DPTR,#LCDstatus
          MOVX A,@DPTR
          JB   ACC.7,tutu
          MOV  DPTR,#LCDdataWR
          POP  ACC
          MOVX @DPTR,A
          ENDM

; macro do inicjalizacji wyswietlacza
init_LCD MACRO
         LCDcntrlWR #INITDISP
         LCDcntrlWR #CLEAR
         LCDcntrlWR #LCDON
         ENDM

; funkcja opoznienia (pauza miedzy stronami - ok. 2 sekundy)
delay_long:
            mov r0, #30H        ; dluzsza pauza
long_one:   mov r1, #0FFH
long_two:   mov r2, #0FFH
long_three: djnz r2, long_three
            djnz r1, long_two
            djnz r0, long_one
            ret

; funkcja opoznienia (krotka - koncowa)
delay:      mov r0, #15H
one:        mov r1, #0FFH
dwa:        mov r2, #0FFH
trzy:       djnz r2, trzy
            djnz r1, dwa
            djnz r0, one
            ret

; funkcja wypisania znaku
putcharLCD: LCDcharWR
            ret

; funkcja wypisania lancucha znakow (zwykla)
putstrLCD:  clr a
            movc a, @a+dptr
            jz str_end
            push dph
            push dpl
            acall putcharLCD
            pop dpl
            pop dph
            inc dptr
            sjmp putstrLCD
str_end:    ret

;===============================================================================
; Funkcja wypisania dokladnie 16 znakow (lub mniej jesli koniec tekstu)
; Wejscie: DPTR = wskaznik na tekst
; Wyjscie: DPTR = wskaznik na nastepny znak po wypisanych
;          A = ostatni pobrany znak (0 jesli koniec tekstu)
;          R7 = liczba wypisanych znakow
;===============================================================================
put16chars:
            mov r7, #16         ; licznik 16 znakow
put16_loop:
            clr a
            movc a, @a+dptr     ; pobierz znak
            jz put16_end        ; jesli 0, koniec tekstu
            push dph
            push dpl
            acall putcharLCD    ; wypisz znak
            pop dpl
            pop dph
            inc dptr            ; nastepny znak
            djnz r7, put16_loop ; powtorz 16 razy
put16_end:
            ret

;===============================================================================
; PROGRAM GLOWNY
;===============================================================================
start:
            init_LCD

            ; Inicjalizacja wskaznika tekstu
            mov text_ptr_l, #LOW(long_text)
            mov text_ptr_h, #HIGH(long_text)

;-------------------------------------------------------------------------------
; Glowna petla wyswietlania stron
;-------------------------------------------------------------------------------
display_loop:
            ; Czyszczenie LCD i ustawienie kursora na linie 1
            LCDcntrlWR #CLEAR
            LCDcntrlWR #HOME

            ; Zaladuj wskaznik z pamieci RAM do DPTR
            mov dph, text_ptr_h
            mov dpl, text_ptr_l

            ;-------------------------------------------------------------------
            ; Wyswietlanie pierwszej linii (16 znakow)
            ;-------------------------------------------------------------------
            acall put16chars
            
            ; Sprawdz czy koniec tekstu
            clr a
            movc a, @a+dptr
            jz end_of_text

            ; Zapisz biezacy wskaznik
            mov text_ptr_l, dpl
            mov text_ptr_h, dph

            ;-------------------------------------------------------------------
            ; Przejscie do drugiej linii LCD
            ;-------------------------------------------------------------------
            LCDcntrlWR #HOM2

            ; Zaladuj wskaznik
            mov dph, text_ptr_h
            mov dpl, text_ptr_l

            ;-------------------------------------------------------------------
            ; Wyswietlanie drugiej linii (16 znakow)
            ;-------------------------------------------------------------------
            acall put16chars

            ; Zapisz biezacy wskaznik
            mov text_ptr_l, dpl
            mov text_ptr_h, dph

            ; Sprawdz czy koniec tekstu
            clr a
            movc a, @a+dptr
            jz end_of_text

            ;-------------------------------------------------------------------
            ; Pauza miedzy stronami
            ;-------------------------------------------------------------------
            acall delay_long

            ; Kontynuuj z nastepna strona
            sjmp display_loop

;-------------------------------------------------------------------------------
; Koniec tekstu - wyswietl komunikat koncowy
;-------------------------------------------------------------------------------
end_of_text:
            ; Pauza koncowa (zeby zobaczyc ostatnia strone)
            acall delay_long

            ; Wyswietl komunikat koncowy
            LCDcntrlWR #CLEAR
            LCDcntrlWR #HOME
            mov dptr, #end_msg1
            acall putstrLCD

            LCDcntrlWR #HOM2
            mov dptr, #end_msg2
            acall putstrLCD

            acall delay_long

            ; Zatrzymanie programu
            nop
            nop
            nop
            jmp $

            end start