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

📄 avr_204.asm

📁 Collected AVR assembler code samples to learn assembler. I use it in my classes.
💻 ASM
字号:
;**** A P P L I C A T I O N   N O T E   A V R 2 0 4 ************************;*;* Title:		BCD Arithmetics;* Version:		1.3;* Last updated:	2004.02.02;* Target:		AT90Sxxxx (All AVR Devices);*;* Support E-mail:	avr@atmel.com;* ;* DESCRIPTION;* This Application Note lists subroutines for the following Binary Coded;* Decimal arithmetic applications:;*;* Binary 16 to BCD Conversion (special considerations for AT90Sxx0x);* Binary 8 to BCD Conversion;* BCD to Binary 16 Conversion;* BCD to Binary 8 Conversion;* 2-Digit BCD Addition;* 2-Digit BCD Subtraction;*;* VERSION HISTORY;* 1.1 Original version;* 1.2 Fixed error in BCDADD routine
;* 1.3 Fixed error in BCD2BIN8 routine (packed version);***************************************************************************.include "..\8515def.inc"	rjmp	RESET	;reset handle;***************************************************************************;*;* "bin2BCD16" - 16-bit Binary to BCD conversion;*;* This subroutine converts a 16-bit number (fbinH:fbinL) to a 5-digit ;* packed BCD number represented by 3 bytes (tBCD2:tBCD1:tBCD0).;* MSD of the 5-digit number is placed in the lowermost nibble of tBCD2.;*  ;* Number of words	:25;* Number of cycles	:751/768 (Min/Max);* Low registers used	:3 (tBCD0,tBCD1,tBCD2) ;* High registers used  :4(fbinL,fbinH,cnt16a,tmp16a)	;* Pointers used	:Z;*;***************************************************************************;***** Subroutine Register Variables.equ	AtBCD0	=13		;address of tBCD0.equ	AtBCD2	=15		;address of tBCD1.def	tBCD0	=r13		;BCD value digits 1 and 0.def	tBCD1	=r14		;BCD value digits 3 and 2.def	tBCD2	=r15		;BCD value digit 4.def	fbinL	=r16		;binary value Low byte.def	fbinH	=r17		;binary value High byte.def	cnt16a	=r18		;loop counter.def	tmp16a	=r19		;temporary value;***** Codebin2BCD16:	ldi	cnt16a,16	;Init loop counter		clr	tBCD2		;clear result (3 bytes)	clr	tBCD1			clr	tBCD0			clr	ZH		;clear ZH (not needed for AT90Sxx0x)bBCDx_1:lsl	fbinL		;shift input value	rol	fbinH		;through all bytes	rol	tBCD0		;	rol	tBCD1	rol	tBCD2	dec	cnt16a		;decrement loop counter	brne	bBCDx_2		;if counter not zero	ret			;   returnbBCDx_2:ldi	r30,AtBCD2+1	;Z points to result MSB + 1bBCDx_3:	ld	tmp16a,-Z	;get (Z) with pre-decrement;----------------------------------------------------------------;For AT90Sxx0x, substitute the above line with:;;	dec	ZL;	ld	tmp16a,Z;;----------------------------------------------------------------	subi	tmp16a,-$03	;add 0x03	sbrc	tmp16a,3	;if bit 3 not clear	st	Z,tmp16a	;	store back	ld	tmp16a,Z	;get (Z)	subi	tmp16a,-$30	;add 0x30	sbrc	tmp16a,7	;if bit 7 not clear	st	Z,tmp16a	;	store back	cpi	ZL,AtBCD0	;done all three?	brne	bBCDx_3		;loop again if not	rjmp	bBCDx_1		;***************************************************************************;*;* "bin2BCD8" - 8-bit Binary to BCD conversion;*;* This subroutine converts an 8-bit number (fbin) to a 2-digit ;* BCD number (tBCDH:tBCDL).;*  ;* Number of words	:6 + return;* Number of cycles	:5/50 (Min/Max) + return;* Low registers used	:None;* High registers used  :2 (fbin/tBCDL,tBCDH);*;* Included in the code are lines to add/replace for packed BCD output.	;*;***************************************************************************;***** Subroutine Register Variables.def	fbin	=r16		;8-bit binary value.def	tBCDL	=r16		;BCD result MSD.def	tBCDH	=r17		;BCD result LSD;***** Codebin2bcd8:	clr	tBCDH		;clear result MSDbBCD8_1:subi	fbin,10		;input = input - 10	brcs	bBCD8_2		;abort if carry set	inc	tBCDH		;inc MSD;---------------------------------------------------------------------------;				;Replace the above line with this one;				;for packed BCD output				;	subi	tBCDH,-$10 	;tBCDH = tBCDH + 10;---------------------------------------------------------------------------	rjmp	bBCD8_1		;loop againbBCD8_2:subi	fbin,-10	;compensate extra subtraction;---------------------------------------------------------------------------;				;Add this line for packed BCD output;	add	fbin,tBCDH	;---------------------------------------------------------------------------		ret;***************************************************************************;*;* "BCD2bin16" - BCD to 16-Bit Binary Conversion;*;* This subroutine converts a 5-digit packed BCD number represented by ;* 3 bytes (fBCD2:fBCD1:fBCD0) to a 16-bit number (tbinH:tbinL).;* MSD of the 5-digit number must be placed in the lowermost nibble of fBCD2.;* ;* Let "abcde" denote the 5-digit number. The conversion is done by;* computing the formula: 10(10(10(10a+b)+c)+d)+e.;* The subroutine "mul10a"/"mul10b" does the multiply-and-add operation ;* which is repeated four times during the computation.;*  ;* Number of words	:30 ;* Number of cycles	:108 ;* Low registers used	:4 (copyL,copyH,mp10L/tbinL,mp10H/tbinH);* High registers used  :4 (fBCD0,fBCD1,fBCD2,adder)	;*;***************************************************************************;***** "mul10a"/"mul10b" Subroutine Register Variables.def	copyL	=r12		;temporary register.def	copyH	=r13		;temporary register.def	mp10L	=r14		:Low byte of number to be multiplied by 10.def	mp10H	=r15		;High byte of number to be multiplied by 10.def	adder	=r19		;value to add after multiplication	;***** Codemul10a:	;***** multiplies "mp10H:mp10L" with 10 and adds "adder" high nibble 	swap	addermul10b:	;***** multiplies "mp10H:mp10L" with 10 and adds "adder" low nibble 	mov	copyL,mp10L	;make copy	mov	copyH,mp10H	lsl	mp10L		;multiply original by 2	rol	mp10H	lsl	copyL		;multiply copy by 2	rol	copyH			lsl	copyL		;multiply copy by 2 (4)	rol	copyH			lsl	copyL		;multiply copy by 2 (8)	rol	copyH			add	mp10L,copyL	;add copy to original	adc	mp10H,copyH		andi	adder,0x0f	;mask away upper nibble of adder	add	mp10L,adder	;add lower nibble of adder	brcc	m10_1		;if carry not cleared	inc	mp10H		;	inc high bytem10_1:	ret	;***** Main Routine Register Variables.def	tbinL	=r14		;Low byte of binary result (same as mp10L).def	tbinH	=r15		;High byte of binary result (same as mp10H).def	fBCD0	=r16		;BCD value digits 1 and 0.def	fBCD1	=r17		;BCD value digits 2 and 3.def	fBCD2	=r18		;BCD value digit 5;***** CodeBCD2bin16:	andi	fBCD2,0x0f	;mask away upper nibble of fBCD2	clr	mp10H			mov	mp10L,fBCD2	;mp10H:mp10L = a	mov	adder,fBCD1	rcall	mul10a		;mp10H:mp10L = 10a+b	mov	adder,fBCD1	rcall	mul10b		;mp10H:mp10L = 10(10a+b)+c	mov	adder,fBCD0			rcall	mul10a		;mp10H:mp10L = 10(10(10a+b)+c)+d	mov	adder,fBCD0	rcall	mul10b		;mp10H:mp10L = 10(10(10(10a+b)+c)+d)+e	ret;***************************************************************************;*;* "BCD2bin8" - BCD to 8-bit binary conversion;*;* This subroutine converts a 2-digit BCD number (fBCDH:fBCDL) to an ;* 8-bit number (tbin).;*  ;* Number of words	:4 + return;* Number of cycles	:3/48 (Min/Max) + return;* Low registers used	:None;* High registers used  :2 (tbin/fBCDL,fBCDH)	;*;* Modifications to make the routine accept a packed BCD number is indicated;* as comments in the code. If the modifications are used, fBCDH shall be;* loaded with the BCD number to convert prior to calling the routine.;*;***************************************************************************;***** Subroutine Register Variables.def	tbin	=r16		;binary result.def	fBCDL	=r16		;lower digit of BCD input.def	fBCDH	=r17		;higher digit of BCD input;***** CodeBCD2bin8:;--------------------------------------------------------------------------;|				;For packed BCD input, add these two lines;|	mov	tbin,fBCDH	;copy input to result;|	andi	tbin,$0f	;clear higher nibble of result;--------------------------------------------------------------------------BCDb8_0:subi	fBCDH,1		;fBCDH = fBCDH - 1;--------------------------------------------------------------------------;|				;For packed BCD input, replace the above;|				;line with this;|	subi	fBCDH,$10	;MSD = MSD - 1;--------------------------------------------------------------------------
	brcs	BCDb8_1		;if carry not set
	subi	tbin,-10	;    result = result + 10	rjmp	BCDb8_0		;    loop againBCDb8_1:ret			;else return;***************************************************************************;*;* "BCDadd" - 2-digit packed BCD addition;*;* This subroutine adds the two unsigned 2-digit BCD numbers ;* "BCD1" and "BCD2". The result is returned in "BCD1", and the overflow ;* carry in "BCD2".;*  ;* Number of words	:21;* Number of cycles	:23/25 (Min/Max);* Low registers used	:None;* High registers used  :3 (BCD1,BCD2,tmpadd)	;*;***************************************************************************;***** Subroutine Register Variables.def	BCD1	=r16		;BCD input value #1.def	BCD2	=r17		;BCD input value #2.def	tmpadd	=r18		;temporary register;***** CodeBCDadd:	ldi	tmpadd,6	;value to be added later	add	BCD1,BCD2	;add the numbers binary	clr	BCD2		;clear BCD carry	brcc	add_0		;if carry not clear	ldi	BCD2,1		;    set BCD carryadd_0:	brhs	add_1		;if half carry not set	add	BCD1,tmpadd	;    add 6 to LSD	brhs	add_2		;    if half carry not set (LSD <= 9)	subi	BCD1,6		;        restore value	rjmp	add_2		;elseadd_1:	add	BCD1,tmpadd	;    add 6 to LSDadd_2:	brcc	add_2a	ldi	BCD2,1	add_2a:	swap	tmpadd	add	BCD1,tmpadd	;add 6 to MSD	brcs	add_4		;if carry not set (MSD <= 9)	sbrs	BCD2,0		;    if previous carry not set	subi	BCD1,$60	;	restore value add_3:	ret			;elseadd_4:	ldi	BCD2,1		;    set BCD carry	ret;***************************************************************************;*;* "BCDsub" - 2-digit packed BCD subtraction;*;* This subroutine subtracts the two unsigned 2-digit BCD numbers ;* "BCDa" and "BCDb" (BCDa - BCDb). The result is returned in "BCDa", and ;* the underflow carry in "BCDb".;*  ;* Number of words	:13;* Number of cycles	:12/17 (Min/Max);* Low registers used	:None;* High registers used  :2 (BCDa,BCDb)	;*;***************************************************************************;***** Subroutine Register Variables.def	BCDa	=r16		;BCD input value #1.def	BCDb	=r17		;BCD input value #2;***** CodeBCDsub:	sub	BCDa,BCDb	;subtract the numbers binary	clr	BCDb	brcc	sub_0		;if carry not clear	ldi	BCDb,1		;    store carry in BCDB1, bit 0sub_0:	brhc	sub_1		;if half carry not clear	subi	BCDa,$06	;    LSD = LSD - 6sub_1:	sbrs	BCDb,0		;if previous carry not set	ret			;    return	subi	BCDa,$60	;subtract 6 from MSD	ldi	BCDb,1		;set underflow carry	brcc	sub_2		;if carry not clear	ldi	BCDb,1		;    clear underflow carry	sub_2:	ret			;****************************************************************************;*;* Test Program;*;* This program calls all the subroutines as an example of usage and to ;* verify correct operation.;*;****************************************************************************;***** Main Program Register variables.def	temp	=r16		;temporary storage variable;***** CodeRESET:	ldi	temp,low(RAMEND)	out	SPL,temp	ldi	temp,high(RAMEND)	out	SPH,temp	;init Stack Pointer (remove for AT90Sxx0x);***** Convert 54,321 to 2.5-byte packed BCD format	ldi	fbinL,low(54321)	ldi	fbinH,high(54321)	rcall	bin2BCD16	;result: tBCD2:tBCD1:tBCD0 = $054321;***** Convert 55 to 2-byte BCD 	ldi	fbin,55	rcall	bin2BCD8	;result: tBCDH:tBCDL = 0505;***** Convert $065535 to a 16-bit binary number	ldi	fBCD2,$06	ldi	fBCD1,$55	ldi	fBCD0,$35	rcall	BCD2bin16	;result: tbinH:tbinL = $ffff (65,535);***** Convert $0403 (43) to an 8-bit binary number	ldi	fBCDL,3	ldi	fBCDH,4	rcall	BCD2bin8	;result: tbin = $2b (43);***** Add BCD numbers 51 and 79	ldi	r20,$00	ldi	r21,$00	l1:	mov	BCD1,r20	mov	BCD2,r21	rcall	BCDadd		;result: BCD2:BCD1=$0130	inc 	r20	inc 	r21	rjmp	l1;***** Subtract BCD numbers 72 - 28	ldi	BCDa,$72	ldi	BCDb,$28	rcall	BCDsub		;result: BCDb=$00 (positive result), BCDa=44;***** Subtract BCD numbers 0 - 90	ldi	BCDa,$00	ldi	BCDb,$90	rcall	BCDsub		;result: BCDb=$01 (negative result), BCDa=10	forever:rjmp	forever

⌨️ 快捷键说明

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