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

📄 int2.asm

📁 实现对ADE7759电能芯片的读写和校准,AVR单片机源码与电路图,单相电能表读写程序和初始化程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	;51c, 53c
	mov	prb2, prb_znak
	swap	prb2
	lds	r1, Hist_przepel_U	; laduj zmienna
	lds	r0, Hist_przepel_U_ile
	;57c
	lds	kwd0, Off_U_dc
	lds	kwd1, Off_U_dc+1	; offset DC, czyli symetrii probek
	mov	r2, kwd1
	swap	r2		; dolna polowka r2 to bity znaku offsetu
	;63c
	nop

;--5a----	odbior piatego bajtu
	clr	spi_bufor
	out	SPDR, spi_bufor

	lds	kwd2, Napiecie_min
	lds	kwd3, Napiecie_min+1	; probka o najmniejszej amplitudzie
	lds	kwd4, Napiecie_max
	lds	kwd5, Napiecie_max+1	; probka o najwiekszej amplitudzie
	;8c

;42us...

;--5b----	odczyt piatego bajtu
SBC_5:	sbis	SPSR, SPIF
	rjmp	SBC_5		; czekaj na ustawienie flagi zakonczenia transmisji
	in	spi_bufor, SPSR	; kasuj flage
	in	prb0, SPDR		; odczyt bajtu z rejestru danych SPI
	clr	spi_bufor
	SPI_ADE_OFF

	lsr	prb2
	ror	prb1
	ror	prb0
	lsr	prb2
	ror	prb1
	ror	prb0		; /4
	;11c
	cp	prb0, spi_bufor	; spi_bufor jest zerowany w SPI_BAJT_CZYTAJ
	cpc	prb1, spi_bufor
	brne	I2P_U_DOB		; probka nie przepelniona
	sbrs	prb2, 0		; bit 16 - jesli H to przepelnienie
	rjmp	I2P_U_DOB
	sbr	flagi, 1<<fOVER_U	; ustaw flage przepelnienia probki z ADE7759

I2P_U_DOB:	;15c, 17c
	add	prb0, kwd0
	adc	prb1, kwd1		; kompensacja offsetu
	adc	prb2, r2
	;18c; 20c

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

	; probka napiecia ujemna
	com	prb0
	com	prb1
	com	prb2		; tylko odwrocenie bitow
	sbrs	prb2, 0		; bit 16 - jesli H to przepelnienie
	rjmp	I2P_UM_DOB		; jesli L to probka dobra
	sbr	flagi, 1<<fOVER_U	; ustaw flage przepelnienia probki z ADE7759
	ser	prb0
	ser	prb1		; ustaw probke na maks.
I2P_UM_DOB:	; 26, 28;   28, 30  cykli
	; sprawdzenie amplitudy probki ujemnej
	cp	prb0, kwd2
	cpc	prb1, kwd3
	brlo	I2P_NAP_DAL		; probka mniejsza --> dalej
	sts	Napiecie_min, prb0
	sts	Napiecie_min+1, prb1	; probka wieksza --> zapisz
	rjmp	I2P_NAP_DAL


I2P_NAP_PLUS: ;21c; 23c
	sbrs	prb2, 0		; bit 16 - jesli H to przepelnienie
	rjmp	I2P_UP_DOB		; jesli L to probka dobra
	sbr	flagi, 1<<fOVER_U	; ustaw flage przepelnienia probki z ADE7759
	ser	prb0
	ser	prb1		; ustaw probke na maks.
I2P_UP_DOB:	; 24c, 26c;   26c, 28c
	; sprawdzenie amplitudy probki dodatniej
	cp	prb0, kwd4
	cpc	prb1, kwd5
	brlo	I2P_NAP_DAL		; probka mniejsza --> dalej
	sts	Napiecie_max, prb0
	sts	Napiecie_max+1, prb1	; probka wieksza --> zapisz


I2P_NAP_DAL:  ;plus: (28, 31), (30, 33), (32, 35)
	; minus: (30, 35), (32, 37), (34, 39)


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

	;  plus_ok: 35-42,  plus_ov: 37-44
	; minus_ok: 37-46, minus_ov: 39-48

;50us...
;	KWADRAT16_32	prb1, prb0
;	SUMA32_48	u_suma5, u_suma4, u_suma3, u_suma2, u_suma1, u_suma0
;	;57c - 70c
;zmiana!	lds	kwd0, Ak_mavU
; na	lds	kwd1, Ak_mavU+1
; poczatek	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
	;77c - 90c
;--------

	brts	I2P_KONIEC_PROBEK	; jesli T=1 zebrano wymagana ilosc probek (nie okresow)

	out	SREG, sreg_kopia
	reti	;84c - 97c
;ok. 56us min.
;ok. 3,5us wiecej dla maks.
;  + czas na poczatku przerwania!


;--------------------------------------
I2P_NIEZL:		; niezbieranie probek, gdy okresow = -1
	SPI_ADE_OFF
	lds	prb0, Prb_0xff
	lds	prb1, Prb_0xff+1
	adiw	prb0, 1
	sts	Prb_0xff, prb0
	sts	Prb_0xff+1, prb1
	lds	r0, Prb_na_okr_x2	; r1:r0 zawiera ilosc probek na okres *2
	lds	r1, Prb_na_okr_x2+1
	cp	prb0, r0
	cpc	prb1, r1
	brlo	I2PN_D
	clr	okresow
	; jesli zliczono przerwan (od probek) dwa razy wiecej niz
	; okres sieci (1/50Hz) i nie stwierdzono okresowosci, to
	; pewnie przylozono napiecie "nieprzemmienne"
	; wiec zacznij zbierac probki
I2PN_D:	clr	prb0
	clr	prb1
	out	SREG, sreg_kopia
	reti


;------------------------------------------------------------------------------
I2P_KONIEC_OKRESOW:	; koniec zliczania ze wzgledu na ilosc okresow napiecia
	;26c
	SPI_ADE_OFF

;--------------------------------------
I2P_KONIEC_PROBEK:	; koniec zliczania ze wzgledu na ilosc probek
	push	temp
	push	r0
	rcall	ZBIERANIE_PROBEK_WYLACZ
	pop	r0
	pop	temp

	cbr	flagi, 1<<fINT2	; kasuj flage informacji o stanie przerwania INT2

	out	SREG, sreg_kopia
	ret	; RET aby po wyjsciu z przerwania nie wskoczylo znowu do niego
		; poniewaz moze byc ustawiona flaga INT2 w GIFR



;==============================================================================
;===== Procedura odbioru probek ===============================================
;===== dla pradu stalego (gdy nie ma przebiegow okresowych) ===================
;==============================================================================
INT2_KAL:	; potrzebne do kalibracji
; linia SAG musi byc wylaczona (rejestr MODE)
; poniewaz gdy nie ma okresowosci napiecia w CH2 to zglaszane jest przerwanie
; na linii IRQ nawet jesli rejestr IRQEN=0
; a takze ilosc probek na okres =140 (7kHz)

	push	spi_bufor
	in	spi_bufor, SREG	; zachowaj rejestr SREG
	push	spi_bufor

	rcall	DELAY_3_5us
	rcall	DELAY_3_5us

	SPI_ADE_ON
	ldi	spi_bufor, ADE_RSTSTATUS_ADR	; komenda odczytu interrupt status
	SPI_BAJT_WYSLIJ		; wyslij bajt poprzez SPI
	rcall	DELAY_3_5us		; min czas miedzy bajtami = 4us
	SPI_BAJT_CZYTAJ	spi_bufor
	SPI_ADE_OFF

	sbrc	spi_bufor, I_WSMP	; przeskocz, jesli bit WSMP wyzerowany
	rcall	INT2_PRB		; WSMP=1 --> przerwanie w celu odbioru probki
	cli

	pop	spi_bufor
	out	SREG, spi_bufor
	pop	spi_bufor
	reti





;==============================================================================
;	DELAY_2us
; petla = 4 takty
; stala = 12 takty (lacznie z wywolaniem procedury - RCALL)
; czas [us] = (D40us * 4 + 12) /  F_zegara [MHz]
; D40us = (czas * F_zegara - 12) / 4
;==============================================================================
.equ	D2us	=1	; 2us dla F_zegara =8MHz
DELAY_2us:			; 3c (rcall)
	nop		; 1c (wyrownanie)
	push	r16	; 2c
	ldi	r16, D2us	; 1c
D2us_1:	dec	r16	; 1c
	tst	r16	; 1c
	brne	D2us_1	; 2c
	pop	r16	; 2c
	ret		; 4c

;------------------------------------------------------------------------------
.equ	D3_5us	=4	; 3,5us dla F_zegara =8MHz
DELAY_3_5us:		; 3c
	nop		; 1c
	push	r16	; 2c
	ldi	r16, D3_5us	; 1c
D35us_1:	dec	r16	; 1c
	tst	r16	; 1c
	brne	D35us_1	; 2c
	pop	r16	; 2c
	ret		; 4c



.exit
;==============================================================================


Probka napiecia lub pradu jest 20-bitowa (w uzupelnieniu do dwoch):
- bit 19 to znak
- maks wartosc probki to +262143 oraz -262143  => +(2^18-1) oraz -(2^18-1)
  probki przepelnione - zatrzasniecie na +262144 oraz -262144  czyli: +-(2^18)
- czyli bit 18 sygnalizuje przepelnienie, ale TYLKO na dodatniej probce
- probka przesylana przez SPI jest 24-bitowa: najstarsze 4 bity to powielony bit znaku (bit 19)
  wyjatek stanowi przeslanie jednoczesne probki pradu i napiecia - wtedy sa one 20-bitowe
- format przesylania probki pradu i napiecia:
      ________ ________ ____________________________ ____________________________
     | 4-bity | 4-bity |      16-bitow  pradu       |     16-bitow  napiecia     |
     | nap.   | pradu  |                            |                            |
     | b 19:16| b 19:16|        bity 15:0           |        bity 15:0           |
 (b39)-------- -------- ---------------------------- ----------------------------(b0)
 
SPI: | 1st bajt czytany|  2nd B czyt. | 3rd B czyt. |  4rd B czyt. | 5rd B czyt. |

;------------------------------------------------------------------------------

Obrobka pradu i napiecia - pelna rozdzielczosc:

*** czesc w przerwaniu ***
1. odbior 1st bajtu - znaki probki pradu i napiecia
1a.  testowanie przejscia przez zero (napiecia) oraz histerezy przejscia
1b.  jesli brak okresowosci przez dwa okresy sieci 50Hz (czyli w ciagu 40ms) to od tego momentu
     zbierana jest wymagana ilosc probek (okresow_ile+1) * probek_na_okres
2. odbior 2nd bajtu
3. po pobraniu 3rd bajtu - laczenie probki (3B)
3a.  dzielenie probki przez 4
3b.  test przepelnienia probki z ADE7759
3c.  kompensacja offsetu za pomoca 11-bitowej liczby w kodzie U2 (max. +-230mA i +-4,6V)
3d.  detekcja znaku probki - jesli ujemna, to negacja
3e.  test przepelnienia probki po korekcji -oddzielnie dla probki dodatniej i ujemnej
3f.  sprawdzanie wartosci probki -amplituda (j.w.)
3g.  testowanie przepelnienia probki (flaga fOVER) oraz histerezy przepelnienia (bit 18)
3h.  kwadrat probki   (2B)^2 => (4B)
3i.  akumulacja probek^2 przez zadana ilosc okresow (lub konkretna ilosc probek)
     (4B) => (6B)
3j.  akumulacja probki (nie kwadratu) j.w. - (2B) => (4B)    (wartosc srednia)
4. analogicznie jak 2.
5. analogicznie jak 3.

*** czesc poza przerwaniem ***
6. dzielenie akumulatora przez ilosc probek   (6B) / (2B) => (4B)
7. pierwiastek kwadratowy wyniku   sqrt(4B) => (2B)
   (rozdzielczosci: 3,28LSB na 1mA, 16,5LSB na 0,1V)
8. kompensacja offsetu zera (odjecie)
*** dla pradu: ***
9. mnozenie przez wsp_I   (2B) * (2B) => (4B)
10. odrzut dwoch najmlodszych bajtow   (4B) / (2B) => (2B)
   dwa starsze bajty zawieraja wartosc pradu w [mA] (maks 20000 mA)
*** dla napiecia: ***
9. mnozenie przez wsp_LPF1   (2B) * (2B) => (4B)
10. wynik razy 2 (rol)   => (5B)
11. odrzut dwoch najmlodszych bajtow   (5B) / (2B) => (3B)
12. mnozenie przez wsp_U   (3B) * (2B) => (5B) a wlasciwie (4B)
13. odrzut dwoch najmlodszych bajtow   (4B) / (2B) => (2B)
    dwa starsze bajty zawieraja wartosc napiecia w [0,1V] (maks 3960 0,1V)

;--------------------------------------
Uwaga! Wartosc probki napiecia jest zalezna od czestotliwosci, Wsp_LPF1 kompensuje ta odchylke



;==============================================================================
Maksymalny czas obslugi przerwania to 70us dla 280 probek na okres (WAVSEL =14kHz)

- dla SCK =2MHz (fosc/4) czas transmisji bajtu to 4us

czas przerwania INT2_PRB (bez dodatkowego opoznienia na poczatku):
- minimalny: 58,5us
- maksymalny: 61,5us

W zwiazku z przeniesieniem kwadratu i akumulacji wartosci sredniej napiecia na poczatek
tam gdzie ma byc dodatkowe opoznienie, zaoszczedza sie na czasie trwania przerwania.

⌨️ 快捷键说明

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