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

📄 serialio.asm

📁 A software duplex UART for 8xc751 & 8cc752
💻 ASM
字号:
;Serial I/O routines using the 8051's built-in UART.;Almost all of these should use CIN and COUT, so they;could pretty easily be adapted to other devices which;could have similar single character I/O routines,;including the 8051's UART using interrupts and buffers;in memory.;Much of this code appears in PAULMON1... see the;PAULMON1.EQU file for an example of how to use some;of these routines.    ;timer reload calculation    ; baud_const = 256 - (crystal / (12 * 16 * baud))				.equ	baud_const, 252	         ;19200 baud w/ 15 MHz;.equ	 baud_const, 243	 ;4800 baud w/ 12 MHz;---------------------------------------------------------;;							  ;;	       Subroutines for serial I/O		  ;;							  ;;---------------------------------------------------------;cin:	jnb	ri, cin	clr	ri	mov	a, sbuf	retcout:	jnb	ti, cout	clr	ti	mov	sbuf, a	retnewline:push	acc	mov	a, #13	acall	cout	mov	a, #10	acall	cout	pop	acc	ret	;get 2 digit hex number from serial port	; c = set if ESC pressed, clear otherwise	; psw.5 = set if return w/ no input, clear otherwiseghex:ghex8:	clr	psw.5ghex8c:	acall	cin		;get first digit	acall	upper	cjne	a, #27, ghex8fghex8d: setb	c	clr	a	retghex8f: cjne	a, #13, ghex8h	setb	psw.5	clr	c	clr	a	retghex8h: mov	r2, a	acall	asc2hex	jc	ghex8c	xch	a, r2		;r2 will hold hex value of 1st digit	acall	coutghex8j:	acall	cin		;get second digit	acall	upper	cjne	a, #27, ghex8k	sjmp	ghex8dghex8k: cjne	a, #13, ghex8m	mov	a, r2	clr	c	retghex8m: cjne	a, #8, ghex8pghex8n: acall	cout	sjmp	ghex8cghex8p: cjne	a, #21, ghex8q	sjmp	ghex8nghex8q: mov	r3, a	acall	asc2hex	jc	ghex8j	xch	a, r3	acall	cout	mov	a, r2	swap	a	orl	a, r3	clr	c	ret	;carry set if esc pressed	;psw.5 set if return pressed w/ no inputghex16:	mov	r2, #0		;start out with 0	mov	r3, #0	mov	r4, #4		;number of digits left	clr	psw.5ghex16c:	acall	cin	acall	upper	cjne	a, #27, ghex16d	setb	c		;handle esc key	clr	a	mov	dph, a	mov	dpl, a	retghex16d:cjne	a, #8, ghex16f	sjmp	ghex16kghex16f:cjne	a, #127, ghex16g  ;handle backspaceghex16k:cjne	r4, #4, ghex16e   ;have they entered anything yet?	sjmp	ghex16cghex16e:acall	cout	acall	ghex16y	inc	r4	sjmp	ghex16cghex16g:cjne	a, #13, ghex16i   ;return key	mov	dph, r3	mov	dpl, r2	cjne	r4, #4, ghex16h	clr	a	mov	dph, a	mov	dpl, a	setb	psw.5ghex16h:clr	c	retghex16i:mov	r5, a		  ;keep copy of original keystroke	acall	asc2hex	jc	ghex16c	xch	a, r5	lcall	cout	mov	a, r5	push	acc	acall	ghex16x	pop	acc	add	a, r2	mov	r2, a	clr	a	addc	a, r3	mov	r3, a	djnz	r4, ghex16c	clr	c	mov	dpl, r2	mov	dph, r3	retghex16x:  ;multiply r3-r2 by 16 (shift left by 4)	mov	a, r3	swap	a	anl	a, #11110000b	mov	r3, a	mov	a, r2	swap	a	anl	a, #00001111b	orl	a, r3	mov	r3, a	mov	a, r2	swap	a	anl	a, #11110000b	mov	r2, a	retghex16y:  ;divide r3-r2 by 16 (shift right by 4)	mov	a, r2	swap	a	anl	a, #00001111b	mov	r2, a	mov	a, r3	swap	a	anl	a, #11110000b	orl	a, r2	mov	r2, a	mov	a, r3	swap	a	anl	a, #00001111b	mov	r3, a	retasc2hex:	     ;carry set if invalid input	clr	c	push	b	subb	a,#'0'	mov	b,a	subb	a,#10	jc	a2h1	mov	a,b	subb	a,#7	mov	b,aa2h1:	mov	a,b	clr	c	anl	a,#11110000b	 ;just in case	jz	a2h2	setb	ca2h2:	mov	a,b	pop	b	retphex:phex8:	push	acc	swap	a	anl	a, #15	add	a, #246	jnc	phex_b	add	a, #7phex_b: add	a, #58	acall	cout	pop	accphex1:	push	acc	anl	a, #15	add	a, #246	jnc	phex_c	add	a, #7phex_c: add	a, #58	acall	cout	pop	acc	retPHEX16:	PUSH	ACC	MOV	A,DPH	ACALL	PHEX	MOV	A,DPL	ACALL	PHEX	POP	ACC	RETPSTR:		       ;print string @DPTR	PUSH	ACCPSTR1:	CLR	A	MOVC	A,@A+DPTR	JZ	PSTR2	mov	c, acc.7	anl	a, #01111111b	acall	cout	Jc	pstr2	inc	dptr	SJMP	PSTR1					       PSTR2:	POP	ACC	RET    ;first we initialize all the registers we can, setting up;for serial communication.poweron:	mov	sp, #0x30	clr	psw.3		;set for register bank 0 (init needs it)	clr	psw.4	orl	PCON,#10000000b   ; set double baud rate	MOV	TMOD,#00010001b	MOV	SCON,#01010000b  ; Set Serial for mode 1 &				 ; Enable reception	ORL	TCON,#01010010b  ; Start timer 1 both timer	mov	a, #baud_const	mov	th1, a	setb	ti		;ti is normally set in this program	clr	ri		;ri is normally cleared	;jump to main program from here...pint8u: ;prints the unsigned 8 bit value in Acc in base 10        push    b        push    acc        sjmp    pint8bpint8:  ;prints the signed 8 bit value in Acc in base 10        push    b        push    acc        jnb     acc.7, pint8b        mov     a, #'-'        lcall   cout        pop     acc        push    acc        cpl     a        add     a, #1pint8b: mov     b, #100        div     ab        setb    f0        jz      pint8c        clr     f0        add     a, #'0'        lcall   coutpint8c: mov     a, b        mov     b, #10        div     ab        jnb     f0, pint8d        jz      pint8epint8d: add     a, #'0'        lcall   coutpint8e: mov     a, b        add     a, #'0'        lcall   cout        pop     acc        pop     b        ret	;print 16 bit unsigned integer in DPTR, using base 10.pint16u:	;warning, destroys r2, r3, r4, r5, psw.5	push	acc	mov	a, r0	push	acc	clr	psw.5	mov	r2, dpl	mov	r3, dphpint16a:mov	r4, #16	;ten-thousands digit	mov	r5, #39	acall	pint16x	jz	pint16b	add	a, #'0'	lcall	cout	setb	psw.5pint16b:mov	r4, #232	;thousands digit	mov	r5, #3	acall	pint16x	jnz	pint16c	jnb	psw.5, pint16dpint16c:add	a, #'0'	lcall	cout	setb	psw.5pint16d:mov	r4, #100	;hundreds digit	mov	r5, #0	acall	pint16x	jnz	pint16e	jnb	psw.5, pint16fpint16e:add	a, #'0'	lcall	cout	setb	psw.5pint16f:mov	a, r2		;tens digit	mov	r3, b	mov	b, #10	div	ab	jnz	pint16g	jnb	psw.5, pint16hpint16g:add	a, #'0'	lcall	coutpint16h:mov	a, b		;and finally the ones digit	mov	b, r3	add	a, #'0'	lcall	cout	pop	acc	mov	r0, a	pop	acc	ret;ok, it's a cpu hog and a nasty way to divide, but this code;requires only 21 bytes!  Divides r2-r3 by r4-r5 and leaves;quotient in r2-r3 and returns remainder in acc.  If Intel;had made a proper divide, then this would be much easier.pint16x:mov	r0, #0pint16y:inc	r0	clr	c	mov	a, r2	subb	a, r4	mov	r2, a	mov	a, r3	subb	a, r5	mov	r3, a	jnc	pint16y	dec	r0	mov	a, r2	add	a, r4	mov	r2, a	mov	a, r3	addc	a, r5	mov	r3, a	mov	a, r0	retupper:	;converts the ascii code in Acc to uppercase, if it is lowercase	push	acc 	clr	c	subb	a, #97	jc	upper2		;is it a lowercase character	subb	a, #26	jnc	upper2	pop	acc	add	a, #224	;convert to uppercase	retupper2: pop	acc		;don't change anything	retpbin:	mov	r0, #8pbin2:	rlc	a	mov	f0, c	push	acc	mov	a, #'0'	addc	a, #0	lcall	cout	pop	acc	mov	c, f0	djnz	r0, pbin2	rlc	a	retlenstr: mov	r0, #0	  ;returns length of a string in r0	push	acclenstr1:clr	a	movc	a,@a+dptr	jz	lenstr2	mov	c,acc.7	inc	r0	Jc	lenstr2	inc	dptr	sjmp	lenstr1					 lenstr2:pop	acc	ret    .equ    str_buf, 0x20           ;16 byte buffer.equ    max_str_len, 19getstr: ;get a string and store in an internal ram buffer        ;  str_buf = beginning of the buffer        ;  max_str_len = max number of char to receive        ;   (buffer must be one larger for null termination)        mov     r0, #str_bufgstrz:  mov     @r0, #0                 ;fill buffer with zeros        inc     r0        cjne    r0, #(str_buf+max_str_len+1), gstrz        mov     r0, #str_bufgstr_in:lcall   cin        lcall   isascii        jnc     gstr_ctrl        cjne    r0, #(str_buf+max_str_len), gstradd        sjmp    gstr_ingstradd:lcall   cout        mov     @r0, a        inc     r0        sjmp    gstr_ingstr_ctrl:        cjne    a, #13, gstrc2          ;carriage return        clr     a        mov     @r0, a        retgstrc2: cjne    a, #8, gstrc3           ;backspacegstrbk: cjne    r0, #str_buf, gstrbk2        sjmp    gstr_ingstrbk2:mov     a, #8        lcall   cout        mov     a, #' '        lcall   cout        mov     a, #8        lcall   cout        dec     r0        sjmp    gstr_ingstrc3: cjne    a, #127, gstrc4         ;delete        sjmp    gstrbkgstrc4:        sjmp    gstr_in                 ;ignore all otherspstrbuf:  ;print the string in the internal ram buffer        mov     r0, #str_bufpstrbuf2:        mov     a, @r0        jz      pstrbuf3        lcall   cout        inc     r0        sjmp    pstrbuf2pstrbuf3:        ret        ;get unsigned integer input to accgint8u:        mov     r0, #0          ;r0 holds sum so far        mov     r1, #0          ;r1 counts number of charactersgi8_in: lcall   cin        mov     r2, a           ;r2 is temp holding space for input char        clr     c        subb    a, #'0'        jc      gi8_ctrl        subb    a, #10        jnc     gi8_ctrl        mov     a, r0        mov     b, #10        mul     ab        xch     a, b        jnz     gi8_in        mov     a, r2        clr     c        subb    a, #'0'        add     a, b        jc      gi8_in        mov     r0, a        mov     a, r2        lcall   cout        inc     r1        sjmp    gi8_ingi8_ctrl:        mov     a, r2        cjne    a, #13, gi8c2        mov     a, r0        retgi8c2:  cjne    a, #8, gi8c3gi8bk:  cjne    r1, #0, gi8bk2        sjmp    gi8_ingi8bk2: mov     a, #8        lcall   cout        mov     a, #' '        lcall   cout        mov     a, #8        lcall   cout        mov     a, r0        mov     b, #10        div     ab        mov     r0, a        sjmp    gi8_ingi8c3:  cjne    a, #127, gi8c4        sjmp    gi8bkgi8c4:        sjmp    gi8_inisascii:        ;is acc an ascii char, c=1 if yes, c=0 if no        push    acc        cjne    a, #0x7F, isasc2        sjmp    isasc_noisasc2: anl     a, #10000000b        jnz     isasc_no        pop     acc        push    acc        anl     a, #11100000b        jz      isasc_no        setb    c        pop     acc        retisasc_no:        clr     c        pop     acc        ret

⌨️ 快捷键说明

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