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

📄 int2.asm

📁 实现对ADE7759电能芯片的读写和校准,AVR单片机源码与电路图,单相电能表读写程序和初始化程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;==============================================================================
;  Przerwanie INT2 wywolywane z ADE7759 (probki lub SAG)
;  Projekt:	Miernik energii i mocy na ADE7759
;  optymalizacja na szybkosc
;  !!! rejestry nie sa chronione, temp nie jest wykorzystywany
;==============================================================================
;.listmac

; r0, r1, r2 -rejestry operacyjne, r2=0
.def	sreg_kopia	=r3	; r3 wykorzystywany jako kopia SREG

.def	i_suma0	=r4
.def	i_suma1	=r5
.def	i_suma2	=r6
.def	i_suma3	=r7
.def	i_suma4	=r8
.def	i_suma5	=r9	; akumulator kwadratow probek pradu

.def	u_suma0	=r10
.def	u_suma1	=r11
.def	u_suma2	=r12
.def	u_suma3	=r13
.def	u_suma4	=r14
.def	u_suma5	=r15	; akumulator kwadratow probek napiecia

; r16 =temp, r17 =flagi		; temp nie moze byc wykorzystywany
.def	kwd0	=r18
.def	kwd1	=r19
.def	kwd2	=r20
.def	kwd3	=r21	; kwd3::kwd0 -wynik kwadratu probki
.def	kwd4	=r22	; inne zastosowanie
.def	kwd5	=r23	; 

.def	prb0	=r24
.def	prb1	=r25
.def	prb2	=r26	;
.def	prb_znak	=r27	; rejestr X

.def	spi_bufor	=r28
.def	okresow	=r29	; rejestr Y

.def	probek0	=r30
.def	probek1	=r31	; rejestr Z



;======== M A K R A ===========================================================

; SPI dziala z predkoscia 2MHz (CLK/4 - spitwi.asm)
.macro	SPI_BAJT_WYSLIJ
	out	SPDR, spi_bufor
SBW_1:	sbis	SPSR, SPIF
	rjmp	SBW_1		; czekaj na ustawienie flagi zakonczenia transmisji
	in	spi_bufor, SPSR	; kasuj powyzsza flage
	in	spi_bufor, SPDR	; j.w.
.endm	; 4 cykle od zakonczenia transmisji do wyjscia

;--------------------------------------
.macro	SPI_BAJT_CZYTAJ	; @0 -rejestr odbiorczy
	clr	spi_bufor
	out	SPDR, spi_bufor
SBC_1:	sbis	SPSR, SPIF
	rjmp	SBC_1		; czekaj na ustawienie flagi zakonczenia transmisji
	in	@0, SPSR		; kasuj powyzsza flage
	in	@0, SPDR		; odczyt bajtu z rejestru danych SPI
.endm	; 4 cykle od zakonczenia transmisji do wyjscia

;------------------------------------------------------------------------------
.macro	KWADRAT16_32:	; (@0:@1)^2 ==> kwd3:kwd2:kwd1:kwd0
			; korzysta z r0, r1, r2 oraz r2=0
	clr	r2		; r2 zawsze rowny 0
	mul	@0, @0
	movw	kwd2, r0		; kwd3:kwd2 <== r1:r0
	mul	@1, @1
	movw	kwd0, r0		; kwd1:kwd0 <== r1:r0
	mul	@0, @1
	lsl	r0
	rol	r1
	rol	r2		; wynik ostatniego mul razy 2
	add	kwd1, r0
	adc	kwd2, r1
	adc	kwd3, r2		; dodaj podwojony iloczyn
	clr	r2		; r2 zawsze rowny 0
.endm	; cykli: 16

;------------------------------------------------------------------------------
.macro	SUMA32_48	; @0:@1:@2:@3:@4:@5 += kwd3:kwd2:kwd1:kwd0
	add	@5, kwd0
	adc	@4, kwd1
	adc	@3, kwd2
	adc	@2, kwd3
	adc	@1, r2	; r2=0
	adc	@0, r2
.endm	; cykli: 6
;------------------------------------------------------------------------------


.cseg
;======== P R O G R A M =======================================================
INT2_INT:	; rozpoznanie trybu pracy
	sbrc	flagi, fKAL		; przeskocz, jesli tryb zwykly
	rjmp	INT2_KAL



;======== Wlasciwa procedura odbioru probek ===================================
INT2_PRB:
	sbis	ADE_SAG_PIN, ADE_SAG	; testuj linie SAG
	jmp	BRAK_ZASILANIA
	in	sreg_kopia, SREG	; zachowaj rejestr SREG

; minimalne opoznienie dla wyslania komendy odczytu probek to 7us (dla takiej konfiguracji int2.asm)

	; sumowanie wartosci sredniej napiecia - rejestry prb1 i prb0 nie zmieniaja
	; zawartosci po opuszczeniu przerwania (petla glowna czeka na koniec zbierania probek)
	clr	r2
	KWADRAT16_32	prb1, prb0
	SUMA32_48	u_suma5, u_suma4, u_suma3, u_suma2, u_suma1, u_suma0
	lds	kwd0, Ak_mavU
	lds	kwd1, Ak_mavU+1
	lds	kwd2, Ak_mavU+2
	lds	kwd3, Ak_mavU+3	; akumulator wartosci sredniej
	add	kwd0, prb0
	adc	kwd1, prb1
	adc	kwd2, r2
	adc	kwd3, r2		; sumowanie wartosci sredniej
	sts	Ak_mavU, kwd0
	sts	Ak_mavU+1, kwd1
	sts	Ak_mavU+2, kwd2
	sts	Ak_mavU+3, kwd3	;20cykli = 2,5us
	rcall	DELAY_2us
	;7,25us opoznienia
;	rcall	DELAY_3_5us
;	;8us opoznienia

	SPI_ADE_ON
	ldi	spi_bufor, ADE_WAVEFORM_ADR	; komenda odczytu probek
	SPI_BAJT_WYSLIJ		; wyslij bajt poprzez SPI
;	clr	r2
	clt
	rcall	DELAY_3_5us		; min czas miedzy bajtami = 4us

;--1-----	; czytanie pierwszego bajtu
	SPI_BAJT_CZYTAJ	prb_znak	 ;4 cykle od zakonczenia transmisji
	
	; sprawdzenie przejscia przez zero napiecia (kanal 2)
	mov	r0, prb_znak	; prb_znak przechowuje pierwszy odczytany bajt z SPI
	ldi	spi_bufor, 0b10000000
	and	r0, spi_bufor	; maska na bit znaku napiecia
	brmi	I2P_U_MINUS	;8c	; skacze, jesli bit znaku ustawiony (minus)
	; probka dodatnia:
	lds	r1, Hist_zera	; zaladuj licznik histerezy przejscia przez zero
	tst	r1
	breq	I2P_U_PLUS	;12c	; jesli Hist_zera=0, to nie jest testowane przejscie przez 0
	; testowanie wartosci histerezy
	inc	r1		; zwieksz licznik histerezy
	lds	spi_bufor, Hist_zera_ile	; laduj wartosc oczekiwana histerezy
	cp	r1, spi_bufor
	brlo	I2P_HIST_MNIEJ  ;17c	; skacz, jesli nie osiagnieto wartosci histerezy
	; jest przejscie przez zero
	sts	Hist_zera, r2	; wyzeruj licznik histerezy i skasuj bit testowania histerezy
	inc	okresow		; zwieksz liczbe przejsc przez zero
	lds	spi_bufor, Okresy_ile	; sprawdzenie czy osiagnieto koniec zliczania
	cp	okresow, spi_bufor ;23c
	brlo	I2P_OKRESOW_MNIEJ	; jesli mniej, to pobieraj dalej
	rjmp	I2P_KONIEC_OKRESOW	; jesli rowne, to zliczonych jest wymagana ilosc okresow


I2P_HIST_MNIEJ:
	sts	Hist_zera, r1	; zapisz licznik histerezy
	rjmp	I2P_11
I2P_U_MINUS:
	ldi	spi_bufor, 0b10000000	; ustaw bit rozpoczenia testowania histerezy
	sts	Hist_zera, spi_bufor	; zapisz
	nop
I2P_U_PLUS:	nop	;14c
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
I2P_11:	nop	;23c
	cpi	okresow, 0xFF	; jesli okresow = -1 to nie zbieraj probek
	brne	I2P_ZLICZAJ
	rjmp	I2P_NIEZL

I2P_OKRESOW_MNIEJ:
	nop	;26c
I2P_ZLICZAJ:
	nop
	nop
	nop
	adiw	probek0, 1		; zwieksz licznik probek


;17us...
;--2-----
I2P_BAJT2:	SPI_BAJT_CZYTAJ	prb1	; odczyt drugiego bajtu - prad starszy bajt
	;4c
	mov	prb2, prb_znak
	lds	r1, Hist_przepel_I	; laduj zmienna
	lds	r0, Hist_przepel_I_ile
	; test ilosci probek
	lds	spi_bufor, Probek_ile
	cp	probek0, spi_bufor
	lds	spi_bufor, Probek_ile+1
	cpc	probek1, spi_bufor	; porownanie liczby zebranych probek z liczba maksymalna
	brlo	I2P_B3		; jesli mniej, to zbieraj dalej
	set			; jesli rowne, to ustaw flage T
	;17c
I2P_B3:	lds	kwd0, Off_I_dc
	lds	kwd1, Off_I_dc+1	; offset DC, czyli symetrii probek
	mov	r2, kwd1
	swap	r2		; dolna polowka r2 to bity znaku offsetu
	lds	kwd2, Prad_min
	lds	kwd3, Prad_min+1	; probka o najmniejszej amplitudzie
	lds	kwd4, Prad_max
	lds	kwd5, Prad_max+1	; probka o najwiekszej amplitudzie
	;31c

;25us...
;--3-----
	SPI_BAJT_CZYTAJ	prb0	; odczyt trzeciego bajtu - prad mlodszy bajt
	lsr	prb2
	ror	prb1
	ror	prb0
	lsr	prb2
	ror	prb1
	ror	prb0		; /4
	;10c
	cp	prb0, spi_bufor	; spi_bufor jest zerowany w SPI_BAJT_CZYTAJ
	cpc	prb1, spi_bufor
	brne	I2P_I_DOB		; probka nie przepelniona
	sbrs	prb2, 0		; bit 16 - jesli H to przepelnienie
	rjmp	I2P_I_DOB
	sbr	flagi, 1<<fOVER_I	; ustaw flage przepelnienia probki z ADE7759

I2P_I_DOB:	;14c, 16c
	add	prb0, kwd0
	adc	prb1, kwd1		; kompensacja offsetu
	adc	prb2, r2
	;17c; 19c

	; sprawdzenie znaku probki pradu
	sbrs	prb2, 1		; sprawdzenie bitu znaku - bit 17 (bo bylo /4)
	rjmp	I2P_PRAD_PLUS

	; probka pradu ujemna
	com	prb0
	com	prb1
	com	prb2		; tylko odwrocenie bitow
	sbrs	prb2, 0		; bit 16 - jesli H to przepelnienie
	rjmp	I2P_IM_DOB		; jesli L to probka dobra
	sbr	flagi, 1<<fOVER_I	; ustaw flage przepelnienia probki z ADE7759
	ser	prb0
	ser	prb1		; ustaw probke na maks.
I2P_IM_DOB:	; 25, 27;   27, 29  cykli
	; sprawdzenie amplitudy probki ujemnej
	cp	prb0, kwd2
	cpc	prb1, kwd3
	brlo	I2P_PRAD_DAL	; probka mniejsza --> dalej
	sts	Prad_min, prb0
	sts	Prad_min+1, prb1	; probka wieksza --> zapisz
	rjmp	I2P_PRAD_DAL


I2P_PRAD_PLUS: ;20c; 22c
	sbrs	prb2, 0		; bit 16 - jesli H to przepelnienie
	rjmp	I2P_IP_DOB		; jesli L to probka dobra
	sbr	flagi, 1<<fOVER_I	; ustaw flage przepelnienia probki z ADE7759
	ser	prb0
	ser	prb1		; ustaw probke na maks.
I2P_IP_DOB:	; 23c, 25c;   25c, 27c
	; sprawdzenie amplitudy probki dodatniej
	cp	prb0, kwd4
	cpc	prb1, kwd5
	brlo	I2P_PRAD_DALx	; probka mniejsza --> dalej
	sts	Prad_max, prb0
	sts	Prad_max+1, prb1	; probka wieksza --> zapisz
I2P_PRAD_DALx:
	nop
	nop

I2P_PRAD_DAL: ;plus: (29, 32), (31, 34), (33, 36)
	; minus: (29, 34), (31, 36), (33, 38)

	nop
	nop

;--4a----	odbior czwartego bajtu
 	clr	spi_bufor
	out	SPDR, spi_bufor
;33us...

	; test przepelnienia probki pradu
	sbrc	flagi, fOVER_I	; flaga ustawiana wczesniej
	rjmp	I2P_PRAD_OVER
	clr	r1		; zeruj licznik histerezy (wystapila dobra probka)
	rjmp	I2P_PRAD_OK		; jesli L to probka dobra
I2P_PRAD_OVER:	; testowanie histerezy przepelnienia (kolejnych probek)
	inc	r1		; zwieksz licznik histerezy
	cp	r0, r1		; sprawdz, czy osiagnieto maks. ilosc
	brlo	I2P_PRAD_OK		; ...jesli przekroczono, to zostaw flage ustawiona
	cbr	flagi, 1<<fOVER_I	; ...jesli nie przekroczono histerezy, to kasuj flage
I2P_PRAD_OK:
	sts	Hist_przepel_I, r1	; zapisz zmienna
	; 7c -ok, 9c -over

	KWADRAT16_32	prb1, prb0
	;23c, 25c
	SUMA32_48	i_suma5, i_suma4, i_suma3, i_suma2, i_suma1, i_suma0
	;29c, 31c
	lds	kwd0, Ak_mavI
	lds	kwd1, Ak_mavI+1
	lds	kwd2, Ak_mavI+2
	lds	kwd3, Ak_mavI+3	; akumulator wartosci sredniej
	add	kwd0, prb0
	adc	kwd1, prb1
	adc	kwd2, r2
	adc	kwd3, r2		; sumowanie wartosci sredniej


;--4b----	; odczyt czwartego bajtu - starszy bajt U
	in	spi_bufor, SPSR	; kasuj flage
	in	prb1, SPDR		; odczyt bajtu z rejestru danych SPI


	sts	Ak_mavI, kwd0
	sts	Ak_mavI+1, kwd1
	sts	Ak_mavI+2, kwd2
	sts	Ak_mavI+3, kwd3

⌨️ 快捷键说明

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