⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd8.asm

📁 实现对ADE7759电能芯片的读写和校准,AVR单片机源码与电路图,单相电能表读写程序和初始化程序
💻 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 + -