📄 lcd8.asm
字号:
;==============================================================================
; Obsluga LCD zgodnego z HD44780 dla 8-bitowej szyny danych v1.0
; Nie obsluguje BUSY flag ani odczytu adresu z LCD
;!!! Znak lub komenda do wyslania do LCD przekazywane sa przez rejestr "temp"
;!!! Ciag znakow przeznaczonych do wyslania wskazuje rejestr Z
;!!! - ciag znakow musi byc zakonczony zerem (znakiem o kodzie 0)
; Jesli ktos zamierza korzystac z CGRAM, to z drugiej polowki - adres 0b00001xxx
; Dodatkowo nalezy zdefiniowac procedury opoznien: DELAY_44us i DELAY_1_7ms
;--------------------------------------
; przyklady: [WIECEJ SZCZEGOLOW W KOMENTARZACH]
;
; call LCD_INIT ; inicjalizacja (min 15ms po starcie)
;
; ldi temp, "A" ; znak "A" przekazany przez "temp"
; call LCD_CHAR ; i wyslany na wyswietlacz
;
; ldi temp, LCD_LINE_2
; call LCD_COMMAND ; polecenie przejscia do drugiej linii
;
; ldi ZL, low(Bufor) ; komunikat z RAM
; ldi ZH, high(Bufor) ; adres bufora w rejetrze Z
; call LCD_STR_RAM
;
; ldi ZH, high(2*string)
; ldi ZL, low(2*string)
; call LCD_STR_FLASH ; wyswietlenie komunikatu pobranego z Flash
;
; call LCD_CLEAR ; czysci ekran
;
; ldi temp, LCD_LINE_2 | 9 ; ustaw adres na dziesiaty znak w drugiej linii
; call LCD_COMMAND
;
; string: .db "Witaj!", 0
; txt_1: .db 1,"Tekst 1", 2," Linia2", 0
;==============================================================================
; pozmianiac dla swojego podpiecia do procesora
.equ LCD_PORT =PORTA ; port dla szyny danych
.equ LCD_RS =5 ; numer pinu
.equ LCD_RS_PORT =PORTD ; port
.equ LCD_RW =4
.equ LCD_RW_PORT =PORTD
.equ LCD_E =7
.equ LCD_E_PORT =PORTD
; wybrac jedna opcje:
;.equ LCD_DISPLAY_MODE =0b00110000 ; 1-wierszowy wyswietlacz
.equ LCD_DISPLAY_MODE =0b00111000 ; 2-wierszowy wyswietlacz
;--------------------------------------
; definicje komend
.equ LCD_LINE_1 =0b10000000
.equ LCD_LINE_2 =0b11000000
.equ LCD_CURSOR_LEFT =0b00010000 ; przesuwa kursor (i adres danych) o znak w lewo
.equ LCD_CURSOR_RIGHT =0b00010100 ; -||- o znak w prawo
.equ LCD_INCREMENT =0b00000110 ; zwieksza adres przy wpisywaniu znakow
.equ LCD_DECREMENT =0b00000100
.equ LCD_D1_C0_B0 =0b00001100 ; display ON, cursor OFF, blink OFF
.equ LCD_D1_C0_B1 =0b00001101 ; display ON, cursor OFF, blink ON
.equ LCD_D1_C1_B0 =0b00001110 ; display ON, cursor ON, blink OFF
.equ LCD_D1_C1_B1 =0b00001111 ; display ON, cursor ON, blink ON
.equ LCD_D0_C0_B0 =0b00001000 ; display OFF
;.listmac
;==============================================================================
.macro LCD_E_PULSE
sbi LCD_E_PORT, LCD_E ; 2 cykle
;nop ; dla zegara > 8MHz potrzebne jest opoznienie, bo Fmax(E)=2MHz
cbi LCD_E_PORT, LCD_E ; 2 cykle
;nop
.endm
.cseg
;==============================================================================
LCD_INIT: ; !!! inicjalizacja wyswietlacza - wykonac 15ms po zalaczeniu zasilania
sbi LCD_E_PORT-1, LCD_E ; E jako wyjscie
sbi LCD_RW_PORT-1, LCD_RW ; RW -||-
sbi LCD_RS_PORT-1, LCD_RS
push temp
ser temp
out LCD_PORT-1, temp ; LCD dane jako wyjscie
ldi temp, LCD_DISPLAY_MODE
rcall LCD_COMMAND
rcall DELAY_5_1ms
rcall LCD_COMMAND
rcall DELAY_1_7ms
rcall LCD_COMMAND
rcall DELAY_1_7ms
rcall LCD_COMMAND
rcall LCD_CLEAR ; czyszczenie
ldi temp, LCD_D1_C1_B1 ; wlaczenie wyswietlacza i kursora
rcall LCD_COMMAND
ldi temp, LCD_INCREMENT ; ustawienie zwiekszania adresu
rcall LCD_COMMAND
rcall DELAY_44us
pop temp
ret
;--------------------------------------
LCD_COMMAND: ; wyslanie komendy z rejestru "temp"
cbi LCD_RS_PORT, LCD_RS
rcall LCD_CHAR
sbi LCD_RS_PORT, LCD_RS
ret
;--------------------------------------
LCD_CLEAR: ; czysci ekran i ustawia kursor na pierwsza linie, adres 0
push temp
ldi temp, 1
rcall LCD_COMMAND
rcall DELAY_1_7ms
pop temp
ret
;--------------------------------------
LCD_CHAR: ; wyslanie znaku z "temp" pod biezacy adres wyswietlacza
out LCD_PORT, temp
LCD_E_PULSE
rcall DELAY_44us
ret
;--------------------------------------
LCD_STR_RAM: ; wyslanie ciagu znakow pobranych z RAM
push temp
LSR_NEXT: ld temp, Z+ ; pobranie kolejnego znaku z bufora
cpi temp, 8 ; sprawdzanie czy znak<8
brlo LSR_END ; jesli tak, to koniec
rcall LCD_CHAR
rjmp LSR_NEXT
LSR_END: pop temp
ret
;--------------------------------------
LCD_STR_FLASH: ; wyslanie ciagu znakow pobranych z Flash
; adres komunikatu przekazywany przez rejestr Z
; ciag znakow moze zawierac rowniez numer linii np.:
; txt_1: .db 1,"Tekst 1", 2," Linia2", 0
push temp
LSF_NEXT: lpm temp, Z+ ; pobranie kolejnego znaku z bufora
cpi temp, 8 ; sprawdzanie czy znak<8
brlo LSF_CMM
rcall LCD_CHAR
rjmp LSF_NEXT
LSF_CMM: cpi temp, 1 ; spr. czy znak=1 ?
breq LSF_CMM_1
cpi temp, 2 ; znak=2 ?
breq LSF_CMM_2
pop temp ; inny znak -> koniec
ret
LSF_CMM_2: ldi temp, LCD_LINE_2 ; linia druga
rjmp LSF_CMM_C
LSF_CMM_1: ldi temp, LCD_LINE_1 ; linia pierwsza
LSF_CMM_C: rcall LCD_COMMAND
rjmp LSF_NEXT
;======================================
; programowanie znakow w CGRAM
; znaki_CGRAM: <-- etykieta adresu definicji znakow (gdzies w listingu)
; - pierwszy bajt: zawiera numer znaku w CGRAM (0-7), jednak znaki musza byc
; odczytywane (wyswietlane) z drugiej polowki CGRAM (8-15)
; - drugi bajt: ilosc znakow do pobrania z definicji i zaprogramowania w CGRAM (1-8)
; - nastepne 5 bajtow to jeden znak: bajt opisuje stan kolumn znaku
; od lewej strony (poczytac w pdf HD44780) i LSB oznacza najwyzszy wiersz
; - jesli ilosc znakow jest wieksza niz 1 to nastepne znaki sa programowane po kolei
;--------------------------------------
LCD_CGRAM:
ldi zl, low(2*znaki_CGRAM)
ldi zh, high(2*znaki_CGRAM)
lpm r18, z+ ; numer znaku w CGRAM
lpm r19, z+ ; ilosc znakow
LCG_ZN_o: lsl r18
lsl r18
lsl r18 ; numer znaku w komendzie adresu CGRAM
ldi temp, 0b01000000 ; komenda adresu w CGRAM
or temp, r18 ; dodaj numer znaku
rcall LCD_COMMAND
LCG_ZN: lpm r4, z+
lpm r3, z+
lpm r2, z+
lpm r1, z+
lpm r0, z+ ; definicja znaku
ldi r20, 8 ; 8 wierszy ma znak
LCG_WRS: clr temp
lsr r4
rol temp
lsr r3
rol temp
lsr r2
rol temp
lsr r1
rol temp
lsr r0
rol temp
rcall LCD_CHAR
dec r20
brne LCG_WRS
dec r19
brne LCG_ZN ; kolejny znak jesli r19<>0
ret
; przyklad:
;znaki_CGRAM: ; osiem polskich literek (malych): a, c, e, l, n, o, s, z
;.db 0, 8, 0x20,0x54,0x54,0x54,0xF8, 0x38,0x44,0x46,0x45,0x20, 0x38,0x54,0x54,0xD4,0x18, 0,0x49,0x7F,0x44,0, 0x7C,0x8,0x6,0x5,0x78, 0x38,0x44,0x46,0x45,0x38, 0x48,0x54,0x56,0x55,0x20, 0x44,0x64,0x55,0x4C,0x44
;==============================================================================
; Procedury opoznien czasowych
;
;------------------------------------------------------------------------------
;.equ F_zegara =8000000 ; czestotliwosc kwarcu taktujacego procesor [MHz]
;==============================================================================
; DELAY_44us
; petla = 4 takty
; stala = 12 takty (lacznie z wywolaniem procedury CALL)
; czas [us] = (D44us * 4 + 12) / F_zegara [MHz]
; D44us = (czas * F_zegara - 12) / 4
;------------------------------------------------------------------------------
;.equ D44us =85 ; ilosc petli dla 44us
;.equ D40us = (40*F_zegara/1000000-12)/4
;.equ D42us = (42*F_zegara/1000000-12)/4
.equ D44us = (44*F_zegara/1000000-12)/4
DELAY_44us: ; 4 clk (CALL)
push r16 ; 2
ldi r16, D44us ; 1
D44_1: dec r16 ; 1
tst r16 ; 1
brne D44_1 ; 2
pop r16 ; 2
ret ; 4
;==============================================================================
; DELAY_1_7ms (zalezna od DELAY_44us)
; petla = 4 takty + 44us
; stala = 12 takty (lacznie z wywolaniem procedury CALL)
; czas [us] = (D1_7ms * 4 + 12) / F_zegara [MHz] + D1_7ms * 44us
; D1_7ms = czas [us] / 44 [us] (w przyblizeniu)
;------------------------------------------------------------------------------
;.equ D1_6ms =36 ; ilosc petli dla 1600us
.equ D1_7ms =39 ; ilosc petli dla ~1700us
DELAY_1_7ms: ; 4
push r16 ; 2
ldi r16, D1_7ms ; 1
D1_6_1: rcall DELAY_44us ; 44us
dec r16 ; 1
tst r16 ; 1
brne D1_6_1 ; 2
pop r16 ; 2
ret ; 4
;==============================================================================
; DELAY_5_1ms (zalezna od DELAY_1_7us)
;------------------------------------------------------------------------------
DELAY_5_1ms:
rcall DELAY_1_7ms
rcall DELAY_1_7ms
rcall DELAY_1_7ms
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -