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

📄 math.asm

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

; r0, r1, r2 -rejestry operacyjne, r2=0
.def	bit0	=r27
.def	bit1	=r28

.def	p0	=r24
.def	p1	=r25
.def	p2	=r26	; wynik pierwiastka

.def	n0	=r10
.def	n1	=r11
.def	n2	=r12
.def	n3	=r13
.def	n4	=r14
.def	n5	=r15	; liczba pierwiastkowana
; wynik kwadratu
;.def	kwd5:0	=r23:r18	; deklaracja w int2.asm
; takie rozmieszczenie rejestrow nie powoduje koniecznosci zapisu r9::r4 (i_suma) do RAM



.cseg
;------------------------------------------------------------------------------
KWADRAT_16:	; (p1:p0)^2 ==> kwd3:kwd2:kwd1:kwd0
	; korzysta z r0, r1, r2 oraz r2=0
	clr	r2		; r2 zawsze rowny 0
	mul	p1, p1
	movw	kwd2, r0		; kwd3:kwd2 <== r1:r0
	mul	p0, p0
	movw	kwd0, r0		; kwd1:kwd0 <== r1:r0
	mul	p1, p0
	lsl	r0
	rol	r1
	rol	r2		; wynik ostatniego mul razy 2
	add	kwd1, r0
	adc	kwd2, r1
	adc	kwd3, r2		; dodaj podwojony iloczyn
	ret
	; cykli 15+ret


;==============================================================================
;   PIERW_32
; Pierwiastek z liczby 4-bajtowej   (typ BISEKCJA)
; PIERW_32  -> wejscie w N3:N2:N1:N0, wyjscie w P1:P0
; cykle: max 470, min 60
;==============================================================================
PIERW_32:
	ldi	kwd0, 0b10000000	; bit1:bit0 = 2^15
	mov	bit1, kwd0		; zaladowanie licznika bitowego
	clr	bit0
	clr	p1
	clr	p0
	clr	r2

P32_P:	add	p0, bit0		; liczba petli nie wieksza niz ilosc bitow zmiennej bit (16)
	adc	p1, bit1
	rcall	KWADRAT_16		; (P1:P0)^2 = kwd3:kdw2:kwd1:kwd0
	cp	kwd0, n0
	cpc	kwd1, n1
	cpc	kwd2, n2
	cpc	kwd3, n3		; porownanie kwadratu pierwiastka (p) z liczba pierwiastkowana
	brlo	P32_MNIEJ		; skacz jesli kwd3:...  mniejsze od n3:...
	breq	P32_KON		; skacz jesli rowne
	sub	p0, bit0
	sbc	p1, bit1		; jesli kwd3:...  wieksze to odejmij
P32_MNIEJ:	lsr	bit1		; przesun bit w prawo
	ror	bit0
	brcc	P32_P		; jesli bit nie wyszedl do C to nastepna petla
P32_KON:	ret	; P1:P0 zawiera pierwiastek calkowity z N3::N0




;==============================================================================
;   DIV_48_16
; Dzielenie bez znaku liczby 6-bajtowej przez 2 bajtowa
; n5::n0 = n5::n0 / y1:y0,   reszta w rsz1:rsz0
; UWAGA:	rejestry dzielnej (n) sa zmieniane
; cykli:	okolo 910
;==============================================================================
; dzielnik:
;.def	n5:0	=r15:r10	  deklaracja w PIERW_48
.def	y0	=r30	; (probek0)
.def	y1	=r31	; (probek1)
.def	rsz0	=r0
.def	rsz1	=r1	; reszta (niewykorzystywana w RMS)
.def	dic	=r24	; licznik

DIV_48_16:	ldi	dic, 49		;init loop counter
	clr	rsz0		;clear remainder Low byte
	sub	rsz1, rsz1		;clear remainder High byte and carry
	rjmp	D48_1
D48_0:	sec
D48_1:	rol	n0		;shift left dividend
	rol	n1
	rol	n2
	rol	n3
	rol	n4
	rol	n5
	dec	dic		;decrement counter
	breq	D48_2		;if done (zero) - return
	rol	rsz0		;shift dividend into remainder
	rol	rsz1
	brcs	D48_3		; jesli bit wychodzi z rsz1 nalezy go wprowadzic do n0

	sub	rsz0, y0		;remainder = remainder - divisor
	sbc	rsz1, y1
	brcc	d48_0		;if result negative
	add	rsz0, y0		;    restore remainder
	adc	rsz1, y1
	clc			;    clear carry to be shifted into result
	rjmp	D48_1		;else get next bit

D48_3:	sub	rsz0, y0		; rsz = rsz - y (poniewaz rsz jest wieksze)
	sbc	rsz1, y1
	rjmp	d48_0

D48_2:	ret



;==============================================================================
;   MUL_16_16
; mnozenie 16bit przez 16bit => 32bit
; kwd3::kwd0 = n1:n0 * mn1:mn0
; cykli:	17+ret
;==============================================================================
; korzysta z r0, r1, r2 oraz:
.def	mn0	=r24
.def	mn1	=r25	; mnoznik
;.def	n1:0	=r11:r10	  deklaracja w PIERW_48
;.def	kwd5:0	=r23:r18	; deklaracja w int2.asm

MUL_16_16:	clr	r2
	mul	mn1, n1
	movw	kwd2, r0
	mul	mn0, n0
	movw	kwd0, r0
	mul	mn1, n0
	add	kwd1, r0
	adc	kwd2, r1
	adc	kwd3, r2
	mul	mn0, n1
	add	kwd1, r0
	adc	kwd2, r1
	adc	kwd3, r2
	ret

;==============================================================================
;   MUL_24_16
; mnozenie 24bit przez 16bit => 40bit
; kwd4::kwd0 = n1:n0 * mn2::mn0	(mn2::mn0 = p2::p0)
; cykli:	31+ret
;==============================================================================
.def	mn2	=r26	; mnoznik, bajt trzeci

MUL_24_16:	rcall	MUL_16_16	; mnozenie dwoch mlodszych bajtow: n1:n0 x mn1:mn0
	clr	kwd4
	;clr	r2	; w MUL_16_16
	mul	n0, mn2
	add	kwd2, r0
	adc	kwd3, r1
	adc	kwd4, r2
	mul	n1, mn2
	add	kwd3, r0
	adc	kwd4, r1
	ret

;==============================================================================
;   MUL_32_16
; mnozenie 32bit przez 16bit => 48bit
; kwd5::kwd0 = n3::n0 * mn1:mn0, ale wykorzystuje n5::n0 !
; cykli:	52+ret
;==============================================================================
MUL_32_16:	rcall	MUL_16_16		; mnozenie dwoch mlodszych bajtow: n1:n0 x mn1:mn0
	movw	n0, n2		; przerzut starszych bajtow do mlodszych
	movw	n2, kwd0
	movw	n4, kwd2		; kopia wyniku
	rcall	MUL_16_16		; mnozenie n3:n2 x mn1:mn0
	movw	kwd4, kwd2
	movw	kwd2, kwd0		; starsze bajty na starsze miejsca wyniku
	movw	kwd0, n2		; dodanie pierwszego mnozenia
	add	kwd2, n4
	adc	kwd3, n5
	adc	kwd4, r2
	adc	kwd5, r2
	ret


;==============================================================================
;   BIN_7_BCD	(max. 0x63=99d)
; konwersja niepelnego bajtu na BCD (2 bajty)
; wejscie w bcd0, wyjscie w bcd1:bcd0
; cykli:	5/50 +ret
; words:	7
;==============================================================================

BIN_7_BCD:	clr	bcd1		;clear result MSD
B7B_1:	subi	bcd0, 10		;input = input - 10
	brcs	B7B_2		;abort if carry set
	inc	bcd1		;inc MSD
	rjmp	B7B_1		;loop again
B7B_2:	subi	bcd0, -10		;compensate extra subtraction
	ret


;==============================================================================
;   BIN_16_BCD
; konwersja 2 bajtow do spakowanego BCD (3 bajty)
; wejscie w bin1:bin0, wyjscie w bcd2::bcd0
; rejestry bin? sa zmieniane!
; cykli:	760+ret
; words:	32
; Pointers used: Y
;==============================================================================
.equ	adrbcdl	=18		; adres rejestru LSB(bcd)
.equ	adrbcdh	=20		; adres rejestru MSB(bcd)

.def	bin0	=r6		;binary value Low byte
.def	bin1	=r7
.def	bin2	=r8
.def	bin3	=r9
.def	bcd0	=r18		;BCD value digits 1 and 0
.def	bcd1	=r19		;BCD value digits 3 and 2
.def	bcd2	=r20		;BCD value digit 5 i 4
.def	bcd3	=r21		;BCD value digit 7 i 6
.def	bcd4	=r22		;BCD value digit 9 i 8

.def	lcz16	=r10		;loop counter

BIN_16_BCD:	ldi	temp, 16
	mov	lcz16, temp		;Init loop counter	
	clr	bcd4		;clear result (5 bytes)
	clr	bcd3
	clr	bcd2		;clear result (3 bytes)
	clr	bcd1		
	clr	bcd0		
	clr	yh
B16B_1:	lsl	bin0		;shift input value
	rol	bin1		;through all bytes
	rol	bcd0		;
	rol	bcd1
	rol	bcd2
	dec	lcz16		;decrement loop counter
	brne	B16B_2		;if counter not zero
	ret

B16B_2:	ldi	yl, adrbcdh+1	; Y points to result adr(bcd2)+1
B16B_3:
	ld	temp, -Y		;get (Y) with pre-decrement
	subi	temp, -0x03		;add 0x03
	sbrc	temp, 3		;if bit 3 not clear
	st	Y, temp		;	store back
	ld	temp, Y		;get (Y)
	subi	temp, -0x30		;add 0x30
	sbrc	temp, 7		;if bit 7 not clear
	st	Y, temp		;store back
	cpi	yl, adrbcdl		;done all three?
	brne	B16B_3		;loop again if not
	rjmp	B16B_1		


;==============================================================================
;   BIN_32_BCD
; konwersja 4 bajty do spakowanego BCD (5 bajtow)
; wejscie w bin3::bin0, wyjscie w bcd4::bcd0
; rejestry bin? sa zmieniane!
; cykli:	okolo 2500
; words:	26
; Pointers used: Y
;==============================================================================
.equ	adrbcd32l	=18		; adres rejestru LSB(bcd)
.equ	adrbcd32h	=22		; adres rejestru MSB(bcd)
; reszta deklaracji jak wyzej
.def	lcz32	=r10		;loop counter

BIN_32_BCD:	ldi	temp, 32
	mov	lcz32, temp		;Init loop counter	
	clr	bcd4		;clear result (5 bytes)
	clr	bcd3
	clr	bcd2
	clr	bcd1		
	clr	bcd0		
	clr	yh
B32B_1:	lsl	bin0		;shift input value
	rol	bin1		;through all bytes
	rol	bin2
	rol	bin3
	rol	bcd0		;
	rol	bcd1
	rol	bcd2
	rol	bcd3
	rol	bcd4
	dec	lcz32		;decrement loop counter
	brne	B32B_2		;if counter not zero
	ret

B32B_2:	ldi	yl, adrbcd32h+1	; Y points to result adr(bcd4)+1
B32B_3:
	ld	temp, -Y		;get (Y) with pre-decrement
	subi	temp, -0x03		;add 0x03
	sbrc	temp, 3		;if bit 3 not clear
	st	Y, temp		;	store back
	ld	temp, Y		;get (Y)
	subi	temp, -0x30		;add 0x30
	sbrc	temp, 7		;if bit 7 not clear
	st	Y, temp		;store back
	cpi	yl, adrbcd32l	;done all three?
	brne	B32B_3		;loop again if not
	rjmp	B32B_1		


;==============================================================================
;   ROZPAKUJ_BCD
; konwersja spakowanego bcd do rozpakowanych cyfr po jednej na bajt
; + korekta na tablice znakow LCD
; wejscie w bcd4::bcd0, wyjscie w cyfra9::cyfra0
; cykli:	86
; words:	18
; Pointers used: X, Y
;==============================================================================
.equ	adrcyfra0	=6
.def	cyfra0	=r6
.def	cyfra1	=r7
.def	cyfra2	=r8
.def	cyfra3	=r9
.def	cyfra4	=r10
.def	cyfra5	=r11
.def	cyfra6	=r12
.def	cyfra7	=r13
.def	cyfra8	=r14
.def	cyfra9	=r15
.def	lic_cf	=r1

ROZPAKUJ_BCD:
	clr	yh
	ldi	yl, adrcyfra0	; adres rejestrow cyfra
	clr	xh
	ldi	xl, adrbcd32l	; adres rejestrow bcd
	ldi	temp, 5
	mov	lic_cf, temp	; licznik na 10 cyfr

RB_1:	ld	temp, x		; zaladuj wartosc bcd (spakowana)
	andi	temp, 0x0F		; dolna polowka bajtu
	ori	temp, 0b00110000	; poprawne ustawienie cyfry w tablicy znakow
	st	y+, temp		; zapis cyfry
	ld	temp, x+		; zaladuj wartosc bcd (spakowana)
	swap	temp
	andi	temp, 0x0F		; gorna polowka bajtu
	ori	temp, 0b00110000	; poprawne ustawienie cyfry w tablicy znakow
	st	y+, temp		; zapis cyfry
	dec	lic_cf
	brne	RB_1
	ret



;==============================================================================
;   BCD_8_BIN
; konwersja 1 bajtu spakowanego BCD na 1 bajt bin
; wejscie w bcd0, wyjscie w bin0
; cykli:	12+ret
; words:	10
; rejestry:	bcd0, bin0, r0, r1, temp
;==============================================================================
BCD_8_BIN:
	push	bcd0		; kopia
	swap	bcd0		; gorna polowka
	andi	bcd0, 0x0F
	ldi	temp, 10
	mul	bcd0, temp		; mnozenie: "dziesiatek" x 10
	pop	bcd0
	andi	bcd0, 0x0F		; dolna polowka
	add	r0, bcd0		; suma dziesiatek i jednosci
	mov	bin0, r0
	ret


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

⌨️ 快捷键说明

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