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

📄 menu.asm

📁 实现对ADE7759电能芯片的读写和校准,AVR单片机源码与电路图,单相电能表读写程序和初始化程序
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;==============================================================================
;  Obsluga menu
;  Projekt:	Miernik energii i mocy na ADE7759
;==============================================================================

; 1) wiersz menu 8-bajtowy
; 2) flaga T sygnalizuje wykonanie dodatkowej akcji w calym danym podmenu
;    na podstawie adresu A1:A0 w opisie wiersza z bitem podmenu, jesli (A1:A0) <> 0
; 3) AD1:AD0 = 0xFFFF i BIT_PODMENU=1 to oznacza powrot do (pod)menu nadrzednego
;    (AD1:AD0 jest ustawiane w MENU_LEWO) - nalezy odczytac menu nadrzedne w stosunku do biezacego
;    aby pobrac adres funkcji dodatkowej

.equ	BIT_PODMENU		=7	; BIT_PODMENU na najstarszym bicie N (menu_numer)
.def	k0		=r0
.def	k1		=r1	; r1:r0 -adres komunikatu
.def	a0		=r2
.def	a1		=r3	; r3:r2 -adres akcji
.def	par0		=r4
.def	par1		=r5	; r5:r4 -parametry
.def	ad0		=r6
.def	ad1		=r7	; r7:r6 -adres dodatkowej akcji

.def	menu_poziom		=r18
.def	menu_numer		=r19

;rejestr Y zawiera biezacy adres w obszarze menu
;rejestr Z sluzy do wyswietlania tekstow na lcd

;    \/ -chyba jednak niekoniecznie, bo wyjscie z menu zaczyna proces (petle) od poczatku
; REJESTRY SA (musza byc) CHRONIONE (oprocz temp)
; temp i SREG jest juz chroniony w obsludze przerwania T0 (inne.asm)
.cseg
;==============================================================================
MENU:	; wejscie w menu - inicjalizacja
	push	k0
	push	k1
	push	a0
	push	a1
	push	par0
	push	par1
	push	ad0
	push	ad1
	push	yl
	push	yh
	push	zl
	push	zh
	clt
	clr	ad0
	clr	ad1

	rcall	LCD_CLEAR
	ldi	menu_poziom, 1	; menu_poziom = 1
	ldi	yl,  low(2*menu_kalibr)
	ldi	yh, high(2*menu_kalibr)
	sbrc	flagi, fKAL
	rjmp	M_KAL
	ldi	yl,  low(2*menu_start)
	ldi	yh, high(2*menu_start)
M_KAL:	sbiw	yl, 8		; (adres menu)-8 bo w MENU_DOL jest zwiekszany
	rjmp	MENU_DOL		; wyswietl

KLMN:	; detekcja, czy jest to pierwsze wejscie do procedury obslugi klawisza
	; zakladam, ze klawisze sa wciskane pojedynczo, z jakas przerwa miedzy jednym a drugim nacisnieciem
	wdr
	sbrc	flagi, fKLAW_WCIS	; przeskocz, jesli flaga wyzerowana
	rjmp	KLMN		; na poczatek petli

	lds	temp, Klawisze	; laduj zmienna o stanie klawiszy
	tst	temp
	breq	KLMN		; brak nacisniecia

	; rozpoznanie wcisnietego klawisza
	KLAWISZ_WCISNIETY		; ustaw bit wcisniecia klawisza
	sbrc	temp, KLAW_TAK	; przeskocz, jesli to nie klawisz TAK
	rjmp	MENU_TAK		; klawisz TAK wcisniety - zatwierdzenie
	sbrc	temp, KLAW_NIE
	rjmp	MENU_NIE		; wyjscie z (pod)menu
	sbrc	temp, KLAW_G
	rjmp	MENU_GORA
	sbrc	temp, KLAW_D
	rjmp	MENU_DOL
	sbrc	temp, KLAW_L
	rjmp	MENU_LEWO
	rjmp	MENU_PRAWO

KLMN_RET:	rcall	LCD_CLEAR
	clt
	pop	zh
	pop	zl
	pop	yh
	pop	yl
	pop	ad1
	pop	ad0
	pop	par1
	pop	par0
	pop	a1
	pop	a0
	pop	k1
	pop	k0
	ret


;------------------------------------------------------------------------------
MENU_DOL:	; strzalka w dol
	movw	zl, yl		; kopia biezacego adresu wiersza do Z
	; operacje musza byc na kopii (lpm Rd, Z)
MD_W:	adiw	zl, 8		; 8 bajtow dalej - nastepny wiersz
	lpm	temp, z		; pobierz Poziom
	cp	temp, menu_poziom	; porownanie z obecnym poziomem
	breq	MS_WYSW		;    rowny
	brlo	KLMN		;    mniejszy -> koniec (pod)menu
	rjmp	MD_W		;    wiekszy -> powtorz raz jeszcze

;------------------------------------------------------------------------------
MENU_GORA:	; strzalka w gore
	movw	zl, yl		; kopia biezacego adresu wiersza do Z
	movw	k0, menu_poziom	; kopia menu_*

	ldi	temp, 1<<BIT_PODMENU
	com	temp
	and	k1, temp		; czyszczenie bitu podmenu w kopii
	dec	k1		; jesli menu_numer-1 = 0 to oznacza
	breq	MG_SPR_P		; ...poczatek (pod)menu -> spr menu_poziom
	rjmp	MG_W
MG_SPR_P:	dec	k0		; dodatkowo jesli menu_poziom-1 = 0 to oznacza
	breq	KLMN		; ...poczatek menu

MG_W:	sbiw	zl, 8		; 8 bajtow wczesniej - poprzedni wiersz
	lpm	temp, z		; pobierz P
	cp	temp, menu_poziom	; porownanie z obecnym poziomem
	breq	MS_WYSW		;    rowny
	brlo	KLMN		;    mniejszy -> koniec (pod)menu
	rjmp	MG_W		;    wiekszy -> powtorz raz jeszcze

;----- wspolne dla DOL i GORA  --------
MS_WYSW:	; przejscie i wyswietlenie komunikatu
	movw	yl, zl		; nowy adres wiersza w menu
	adiw	zl, 1
	lpm	menu_numer, z+	; zmiana numeru
	lpm	k0, z+		; .
	lpm	k1, z+		; adres komunikatu
	lpm	a0, z+		; .
	lpm	a1, z+		; adres procedury (akcji)
	lpm	par0, z+		; .
	lpm	par1, z+		; parametry

	movw	zl, k0		; laduj adres komunikatu do Z
	rcall	LCD_CLEAR
	rcall	LCD_STR_FLASH	; wyswietl

	sbrc	menu_numer, BIT_PODMENU	; sprawdzenie bitu podmenu
	rjmp	MSW_P		; (bit podmenu)=1 --> jest podmenu
	; brak podmenu - sprawdzenie flagi dodatkowej akcji
	brtc	MSW_K		; flaga wyzerowana -> nie ma akcji
	movw	zl, ad0
	icall			; akcja wykonana
MSW_K:	rjmp	KLMN		; na poczatek petli
	; jest podmenu
MSW_P:	ldi	temp, LCD_LINE_2 | 13	; ustaw kursor na 14-tym znaku drugiej linii
	rcall	LCD_COMMAND
	ldi	temp, '>'		; symbol podmenu ">>>"
	rcall	LCD_CHAR
	rcall	LCD_CHAR
	rcall	LCD_CHAR

	ser	temp
	cp	ad0, temp
	cpc	ad1, temp		; czy AD1:AD0 = 0xFF ?
	breq	ML_AD		; ...tak -> powrot do MENU_LEWO
	rjmp	KLMN		; na poczatek petli


;------------------------------------------------------------------------------
MENU_LEWO:	; strzalka w lewo
	movw	k0, menu_poziom	; kopia menu_*
	dec	k0		; jesli menu_poziom-1 = 0 to oznacza
	breq	ML_M		; ...najwyzszy poziom

	dec	menu_poziom		; wchodzimy poziom wy縠j
	ldi	menu_numer, 2	; menu_numer wiekszy od 1 (nieistotne jaki numer)
	ser	temp
	mov	ad0, temp
	mov	ad1, temp		; AD1:AD0 = 0xFF --> oznacza powrot poziom wyzej
	rjmp	MENU_GORA		; i szukamy wiersza na wyzszym poziomie

ML_AD:	; pobieranie adresu akcji dodatkowej
	movw	k0, menu_poziom
	dec	k0
	breq	ML_AD_B		; najwyzszy poziom -> brak akcji dodatkowej

	; szukanie (pod)menu nadrzednego
	movw	zl, yl		; kopia biezacego adresu wiersza do Z
MLG_W:	sbiw	zl, 8		; 8 bajtow wczesniej - poprzedni wiersz
	lpm	temp, z		; pobierz P
	cp	temp, k0		; porownanie
	brne	MLG_W		;    nierowny (wiekszy)

	adiw	zl, 4		; ustaw na A0
	lpm	k0, z+		; adres procedury (akcji)
	lpm	k1, z		; ...wczytaj do K1:K0 (bo A1:A0 nie moze sie zmienic)
	clr	temp
	cp	k0, temp
	cpc	k1, temp		; czy k1:k0 <> 0 ?
	breq	ML_AD_B		; ...nie, =0
	set			; ...tak -> ustaw flage wykonania dodatkowej akcji po wyswietleniu wiersza menu
	movw	ad0, k0		; kopiuj adres akcji dodatkowej
	rjmp	KLMN		; na poczatek petli

ML_AD_B:	clt
	clr	ad0
	clr	ad1
ML_M:	rjmp	KLMN		; na poczatek petli

;------------------------------------------------------------------------------
MENU_PRAWO:	; strzalka w prawo
	sbrs	menu_numer, BIT_PODMENU
	rjmp	KLMN		; (bit podmenu)=0 --> brak podmenu
	; jest podmenu
	rjmp	MT_P

;------------------------------------------------------------------------------
MENU_TAK:	; klawisz TAK
	sbrs	menu_numer, BIT_PODMENU
	rjmp	MT_A		; (bit podmenu)=0 --> brak podmenu
	; jest podmenu
MT_P:	inc	menu_poziom		; poziom ni縠j...
	clr	temp
	cp	a0, temp
	cpc	a1, temp		; czy A1:A0 <> 0 ?
	breq	MT_Z		; ...nie
	set			; ...tak -> ustaw flage wykonania dodatkowej akcji po wyswietleniu wiersza menu
	movw	ad0, a0		; kopiuj adres akcji dodatkowej
	rjmp	MENU_DOL		; i szukamy wiersza na nizszym poziomie
MT_Z:	clt			; kasuj flage wykonania dodatkowej akcji
	rjmp	MENU_DOL		; i szukamy wiersza na nizszym poziomie
	; wykonanie akcji
MT_A:	clr	temp
	cp	a0, temp
	cpc	a1, temp		; czy A1:A0 <> 0 ?
	breq	MT_K		; ...nie, =0
	movw	zl, a0		; zaladowanie adresu
	icall			; WYWOLANIE PROCEDURY OBSLUGI
MT_K:	rjmp	KLMN		; na poczatek petli


;------------------------------------------------------------------------------
MENU_NIE:	; klawisz NIE
	; calkowite wyjscie z MENU
	rjmp	KLMN_RET		; koniec






;==============================================================================
;   PROCEDURY OBSLUGI POSZCZEGOLNYCH WIERSZY MENU i PODMENU
; r1:r0 i zh:zl moga byc zmieniane, bo przechowuja adres komunikatu, ktory jest wyswietlany
; tylko raz po zmianie wiersza menu; inne trzeba chronic
;==============================================================================
M_ARM_W:	; ADE rejestr MODE -wyswietlanie biezacego stanu bitu
	; ZE ZMIENNYCH (nie z ADE7759)
	ldi	zl,  low(2*txt_ze)
	ldi	zh, high(2*txt_ze)
	lds	r0, Ade_mode
	lds	r1, Ade_mode+1
	and	r0, par0		; maska na odpowiedni bit
	and	r1, par1		; ...
	clr	temp
	cp	r0, temp
	cpc	r1, temp
	breq	MX_WYSW		; bit wyzerowany
	; bit ustawiony
	ldi	zl,  low(2*txt_us)
	ldi	zh, high(2*txt_us)

;------- wyswietlanie komunikatu - wspolne ------
MX_WYSW:	rcall	LCD_STR_FLASH	; wyswietl linie
	ret


;--------------------------------------
M_ARM:	; ADE rejestr MODE -zmiana bitow i wysylanie do ADE7759
	; par1:par0 -maska bitowa do zmiany [0-65535]
	push	r2
	push	r3
	push	xl
	push	xh
	lds	r0, Ade_mode
	lds	r1, Ade_mode+1
	movw	r2, r0		; kopia
	and	r2, par0		; maska na odpowiedni bit
	and	r3, par1		; ...
	clr	temp
	cp	r2, temp
	cpc	r3, temp
	breq	MARM_US		; bit wyzerowany -> ustaw
	; bit ustawiony -> zeruj
	movw	r2, par0		; kopia maski
	com	r2
	com	r3		; odwroc maski
	and	r0, r2
	and	r1, r3
	ldi	zl,  low(2*txt_ze)
	ldi	zh, high(2*txt_ze)
	rjmp	MARM_D
MARM_US:	or	r0, par0
	or	r1, par1
	ldi	zl,  low(2*txt_us)
	ldi	zh, high(2*txt_us)
MARM_D:
	push	r0
	push	r1		; zachowaj Ade_mode
	; rejestr MODE zmieniany w trybie kalibracji
	movw	xl, r0
	sbr	xl, 1<<M_DISSAG	; wylacz linie SAG
	sbr	xh, 1<<M_DTRT1
	cbr	xh, 1<<M_DTRT0	; ustaw zbieranie probek na 7kHz (140 na okres 50Hz)
	movw	r0, xl
	sts	Ade_mode, r0
	sts	Ade_mode+1, r1	; zapisz Ade_mode dla trybu kalibracji
	cli
	ldi	temp, ADE_MODE_ADR
	rcall	SPI_ADE_WRITE_2B	; temp -komenda; r1:r0 -2 bajty danych
	sei
	rcall	OIP		; przeliczenie ilosci: Probek_ile
	pop	r1
	pop	r0		; przywroc oryginal
	sts	Ade_mode, r0
	sts	Ade_mode+1, r1	; zapisz oryginal Ade_mode
	pop	xh
	pop	xl
	pop	r3
	pop	r2
	rjmp	MX_WYSW



;------------------------------------------------------------------------------
M_AOR_W:	; odczyt rejestrow ADE w drugiej linii LCD (nie trzeba zatwierdzac TAK)
	; par0 -adres rejestru, par1 -ilu bajtowy
	ldi	temp, LCD_LINE_2
	rcall	LCD_COMMAND
	mov	temp, par1
	cpi	temp, 2
	breq	MAORW_2B		; rejestr dwubajtowy
	mov	temp, par0
	cli
	rcall	SPI_ADE_READ_1B	; temp -komenda; r0 -1 bajt danych
	sei
	ldi	temp, 'h'
	rcall	HEX_1B
	ret
MAORW_2B:	mov	temp, par0
	cli
	rcall	SPI_ADE_READ_2B	; temp -komenda; r1:r0 -2 bajty danych
	sei
	ldi	temp, 'h'
	rcall	HEX_2B
	ret


;==============================================================================
M_AZR_W:	; podglad zmiennych (powiazane z M_AZR)
	; par1:par0 -adres danych
	rcall	ZE_HIST_ZERA
	in	r0, SREG
	push	r0
	movw	zl, par0
	lpm	r0, z+		; .
	lpm	r1, z+		; adres zmiennej do edycji
	adiw	zl, 5
	lpm	temp, z+		; liczba wysylanych bajtow
	movw	zl, r0		; adres zmiennej do z
	; sprawdzenie czy liczba w kodzie U2
	clt			; czysc flage liczby ze znakiem
	sbrc	temp, 7		; jesli r7(7)=1 to zmienna U2
	set			; ustaw flage liczby ze znakiem
	sbrc	temp, 1		; jesli r7(1)=1 to zmienna 2-bajtowa
	rjmp	MAZRW_2B
	; 1bajt
	ld	r0, z		; wczytaj wartosc zmiennej
	clr	r1
	brtc	MAZRW_PL		; jesli liczba w kodzie U2 to powiel bity znaku
	sbrs	r0, 7		; bit 7 informuje o liczbie ze znakiem
	rjmp	MAZRW_PL
	ser	temp
	mov	r1, temp		; bity znaku
	; 2bajty
MAZRW_2B:	ld	r0, z		; wczytaj wartosc zmiennej
	ldd	r1, z+1
MAZRW_PL:	rcall	WYSW_HEX_DEC_2B
	rcall	US_HIST_ZERA
	pop	r0
	out	SREG, r0
	ret


ZE_HIST_ZERA:
	lds	temp, Hist_zera_ile
	andi	temp, 0b01111111	; aby zmienna byla wyswietlana od 1
	sts	Hist_zera_ile, temp
	ret

US_HIST_ZERA:
	lds	temp, Hist_zera_ile
	ori	temp, 0x80
	sts	Hist_zera_ile, temp
	ret

;--------------------------------------
M_AZR:	; zmiana rejestrow ADE (oraz zmiennych) - odczyt ze zmiennej i wyslanie do ADE7759
	; par1:par0 -adres danych
	push	r2
	push	r3
	push	r4
	push	r5
	push	r6
	push	r7
	in	r0, SREG
	push	r0

	rcall	ZE_HIST_ZERA

	movw	zl, par0
	lpm	r0, z+		; .
	lpm	r1, z+		; adres zmiennej do edycji
	lpm	r2, z+		; .
	lpm	r3, z+		; min
	lpm	r4, z+		; .
	lpm	r5, z+		; max
	lpm	r6, z+		; adres rejestru w ADE
	lpm	r7, z+		; liczba wysylanych bajtow
	movw	zl, r0		; adres zmiennej do z
	; sprawdzenie czy liczba w kodzie U2
	clt			; czysc flage liczby ze znakiem
	sbrc	r7, 7		; jesli r7(7)=1 to zmienna U2
	set			; ustaw flage liczby ze znakiem

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -