 
converts a 16-bit number into a counted string for transmission by Serout.
The PBASIC version of Serout has a tremendously convenient feature; the ability to treat data for transmission as either bytes or numbers. The value 65, if sent as a byte, would appear as the letter "A" on the receiving end. If sent as a number, "65" shows up at the receiver. This routine, called BIN_ASC for binary-to-ASCII, converts a pair of bytes (interpreted as a 16-bit number) into text. For example, if the bytes both contain 0FFh, BIN_ASC creates a text string containing "65535" ready for transmission by Serout.
The routine suppresses leading zeros, just as the PBASIC version does. So the number 17 is output as "17" and not "00017".
BIN_ASC goes one step beyond the conversion built into the PBASIC's Serout
by allowing you to specify a fixed decimal point in positions 0 through 4
of the text string. Here are examples of the output: 
Fixed Point at: Value = 1 Value = 65535 0 .00001 .65535 1 .0001 6.5535 2 .001 65.535 3 .01 655.35 4 .1 6553.5 5 1 65535
By setting the fixed point to a value of 5 or greater, you can eliminate it entirely. BIN_ASC can also prepare data for other types of ASCII output devices, such as LCDs or parallel printers. Just write the driver to expect a Serout-style counted string, as described in the previous Serout entry.
The routine uses a short table called decade. Remember that tables and
subroutines must be located in the first 256 words of a 512-word program
memory page. 
To see BIN_ASC in operation, run it on the PSIM simulator. When the program finishes executing, look at the locations 18h through 1Fh. BIN_ASC will have built a counted string of ASCII characters representing the input value (in decimal) with an inserted decimal point. In the case of the demo, the string will be "655.35" which will display as bytes 36h, 35h, 35h, 2Eh, 33h, and 35h. The string count (6) will appear in location 1Fh.
For a live demonstration, connect the circuit below to an erasable PIC or PIC emulator, such as the Parallax downloader. Assemble SEROUT_#.SRC from the accompanying disk and program the PIC or downloader with the assembled program. Make sure to use a 4-MHz clock on the PIC or downloader. Load a terminal program on the PC connected to the PIC and set it for 2400 baud, no parity, 8 data bits, 1 stop bit (N81). When you apply power to the PIC or reset the downloader, the string "655.35" will appear on the PC s creen.
 
;
; ***************************************************************************
; ***  Bubble Software Parallax to PIC Source Converter. Copyright 1999.  ***
; ***  http://www.bubblesoftonline.com                 email: sales@picnpoke.com  ***
; ***************************************************************************
;
; BIN_ASC 16-bit value
; This routine converts a 16-bit number into a counted string of
; ASCII characters compatible with Serout. It suppresses
; leading zeros so that numbers like 17 are sent as "17" not "00017".
	P = pic16c55
	#include <16c55.inc>   ; processor assembler definitions
	_CONFIG _xt_osc & _wdt_off & _protect_off
 reset start
buffer 	equ 	d'31' 	; String buffer at end of memory.
ASC_0 	equ  	'0'	; ASCII numbers: 30h thru 39h.
ASC_dp 	equ  	'.'	; ASCII char for decimal point (period).
fix 	equ	d'3'  	; Position for fixed decimal point.
 org 8
dec_no 	Res 	d'1' 	; Decade (1,10,100...) to work on.
tempH 	Res 	d'1' 	; 16-bit temporary variable used by
tempL 	Res 	d'1' 	; the BIN_ASC routine.
hiB 	Res 	d'1' 	; MSB of number to convert.
lowB 	Res 	d'1' 	; LSB of number to convert.
flags 	Res 	1
zs 	equ  	flags.0	; Leading-zero suppression flag.
 org 0
decade       ADDWF pcl                  
             RETLW d'39'                
             RETLW d'16'
             RETLW d'3'
             RETLW d'232'
             RETLW d'0'
             RETLW d'100'
             RETLW d'0'
             RETLW d'10'
             RETLW d'0'
             RETLW d'1'
start        MOVLW 0x00FF               ; To see routine's output, either
             MOVWF hiB
             MOVLW 0x00FF               ; use the PSIM PIC simulator, or
             MOVWF lowB
             CALL BIN_ASC               ; merge with Serout.
             GOTO $                     ; Endless loop
; This routine accepts a 16-bit number in hiB, lowB and converts it into
; a counted ASCII text string located at the address "buffer." The buffer
; grows downward in memory. The first (0th) item in buffer is the number
; of characters in the string.
BIN_ASC      CLRF buffer                ; Clear char count (item 0 in buf).
             CLRF flags                 ; Clear zs flag.
             CLRF dec_no                ; Clear decade no.
             MOVLW buffer-1             ; Reserve 0th byte of buffer for count.
             MOVWF fsr
BIN_ASC_loop MOVF dec_no,w              ; Get 1st hex digit of decade no.
             CALL decade                ; from the lookup table.
             MOVWF tempH                
             INCF dec_no                ; Get 2nd digit of decade no.
             MOVF dec_no,w              ; from the table.
             CALL decade                
             MOVWF tempL                
             CALL d_point               ; Insert decimal point.
             CALL sub_it                ; Divide hiB,lowB by tempH,tempL
             MOVF indirect,w            ; returning answer in indirect.
             BTFSC flags,d'0'           ; If zs = 0 AND digit = 0 then
             GOTO BIN_ASC_no_zs
             BTFSC status,z             ; digit is a leading zero to be
             GOTO BIN_ASC_no_zed
BIN_ASC_no_zs MOVWF indirect             ;	ignored. Otherwise, it's either
             MOVLW ASC_0                ; an included zero (as in 7501)
             ADDWF indirect
             INCF buffer                ; or a non-zero digit.
             DECF fsr                   ; Point to next memory location.
             BSF flags,d'0'             ; First non-zero digit sets zs bit.
BIN_ASC_no_zed  INCF dec_no             ; Next decade.
             MOVLW d'8'                 ; If dec_no = 8, we're down to ones.
             SUBWF dec_no,w
             BTFSS status,z
             GOTO BIN_ASC_loop          ; Otherwise, do next decade.
             INCF dec_no                ; Update dec_no
             CALL d_point               ; and call d_point.
             MOVF lowB,w                ; Whatever's left belongs in ones.
             MOVWF indirect
             MOVLW ASC_0                ; Add offset for conversion to ASCII.
             ADDWF indirect
             INCF buffer                ; Add 1 to character count.
             RETLW 0h                   
; This routine performs division by iterated subtraction. It is efficient
; in this application because the dividend and divisor keep getting smaller
; as BIN_ASC runs, so the quotient is never larger than nine. A general-
; purpose division routine would be slower (and longer).
sub_it       CLRF indirect              ; Clear to track no. of subtractions.
sub_it_loop  MOVF tempL,w               ; Subtract LSB.
             SUBWF lowB
             BTFSC status,c             ; If no borrow, continue w/MSB.
             GOTO sub_it_skip
             MOVLW d'1'                 ; Otherwise borrow from MSB.
             SUBWF hiB
             BTFSC status,c             ; If borrow causes a carry, then
             GOTO sub_it_skip
             INCF hiB                   ; add numbers back and return.
             MOVF tempL,w               
             ADDWF lowB
             RETLW 0h                   
sub_it_skip  MOVF tempH,w               ; Subtract MSB.
             SUBWF hiB
             BTFSC status,c             ; If no borrow, subtract again.
             GOTO sub_it_skip2
             MOVF tempL,w               ; Otherwise, undo the subtraction
             ADDWF lowB
             BTFSC status,c             ; by adding entire 16-bit no.
             INCF hiB                   ; back together and return.
             MOVF tempH,w               
             ADDWF hiB
             RETLW 0h                   
sub_it_skip2 INCF indirect              ; No borrow, so do it again.
             GOTO sub_it_loop           
; This routine adds a decimal point in the location set by "fix" in the
; equates at the beginning of the program. The location of the decimal point
; is in front of the "fix"ed digit, numbered starting with 0. If you fix the
; point at 0, the first (0th) character in the string produced by BIN_ASC
; will be a decimal point. If you don't want a decimal point, either move
; it out of range (fix = 6), or delete this routine and the "call d_point"
; in the body of BIN_ASC above.
d_point      MOVLW fix*2+1              
             SUBWF dec_no,w
             BTFSS status,z
             RETLW 0h                   
             BSF flags,d'0'             
             MOVLW ASC_dp               
             MOVWF indirect
             INCF buffer                
             DECF fsr                   
             RETLW 0h                   
             
             
             end
; BIN_ASC 16-bit value
; This routine converts a 16-bit number into a counted string of
; ASCII characters compatible with Serout. It suppresses
; leading zeros so that numbers like 17 are sent as "17" not "00017".
buffer	=	31	; String buffer at end of memory.
ASC_0	=	'0'	; ASCII numbers: 30h thru 39h.
ASC_dp	=	'.'	; ASCII char for decimal point (period).
fix	=	3	; Position for fixed decimal point.
	org	8
dec_no	ds	1	; Decade (1,10,100...) to work on.
tempH	ds	1	; 16-bit temporary variable used by
tempL	ds	1	; the BIN_ASC routine.
hiB	ds	1	; MSB of number to convert.
lowB	ds	1	; LSB of number to convert.
flags	ds	1
zs	=	flags.0 ; Leading-zero suppression flag.
	device	pic16c55,xt_osc,wdt_off,protect_off
	reset	start
	org	0
decade	jmp	pc+w
	retw	39,16,3,232,0,100,0,10,0,1
start	mov	hiB, #0FFh	; To see routine's output, either
	mov	lowB, #0FFh	; use the PSIM PIC simulator, or
	call	BIN_ASC ; merge with Serout.
	jmp	$	; Endless loop
; This routine accepts a 16-bit number in hiB, lowB and converts it into
; a counted ASCII text string located at the address "buffer." The buffer
; grows downward in memory. The first (0th) item in buffer is the number
; of characters in the string.
BIN_ASC clr	buffer	; Clear char count (item 0 in buf).
	clr	flags	; Clear zs flag.
	clr	dec_no	; Clear decade no.
	mov	fsr,#buffer-1	; Reserve 0th byte of buffer for count.
:loop	mov	w,dec_no	; Get 1st hex digit of decade no.
	call	decade	; from the lookup table.
	mov	tempH,w
	inc	dec_no	; Get 2nd digit of decade no.
	mov	w,dec_no	; from the table.
	call	decade
	mov	tempL,w
	call	d_point ; Insert decimal point.
	call	sub_it	; Divide hiB,lowB by tempH,tempL
	mov	w,indirect	; returning answer in indirect.
	jb	zs,:no_zs	; If zs = 0 AND digit = 0 then
	jz	:no_zed ; digit is a leading zero to be
:no_zs	mov	indirect,w	;	ignored. Otherwise, it's either
	ADD	indirect,#ASC_0 ; an included zero (as in 7501)
	inc	buffer	; or a non-zero digit.
	dec	fsr	; Point to next memory location.
	setb	zs	; First non-zero digit sets zs bit.
:no_zed inc	dec_no	; Next decade.
	cse	dec_no,#8	; If dec_no = 8, we're down to ones.
	jmp	:loop	; Otherwise, do next decade.
	inc	dec_no	; Update dec_no
	call	d_point ; and call d_point.
	mov	indirect,lowB	; Whatever's left belongs in ones.
	ADD	indirect,#ASC_0 ; Add offset for conversion to ASCII.
	inc	buffer	; Add 1 to character count.
	ret
; This routine performs division by iterated subtraction. It is efficient
; in this application because the dividend and divisor keep getting smaller
; as BIN_ASC runs, so the quotient is never larger than nine. A general-
; purpose division routine would be slower (and longer).
sub_it	clr	indirect	; Clear to track no. of subtractions.
:loop	sub	lowB,tempL	; Subtract LSB.
	jc	:skip	; If no borrow, continue w/MSB.
	sub	hiB,#1	; Otherwise borrow from MSB.
	jc	:skip	; If borrow causes a carry, then
	inc	hiB	; add numbers back and return.
	add	lowB,tempL
	ret
:skip	sub	hiB,tempH	; Subtract MSB.
	jc	:skip2	; If no borrow, subtract again.
	ADD	lowB,tempL	; Otherwise, undo the subtraction
	snc	; by adding entire 16-bit no.
	inc	hiB	; back together and return.
	ADD	hiB,tempH
	ret
:skip2	inc	indirect	; No borrow, so do it again.
	jmp	:loop
; This routine adds a decimal point in the location set by "fix" in the
; equates at the beginning of the program. The location of the decimal point
; is in front of the "fix"ed digit, numbered starting with 0. If you fix the
; point at 0, the first (0th) character in the string produced by BIN_ASC
; will be a decimal point. If you don't want a decimal point, either move
; it out of range (fix = 6), or delete this routine and the "call d_point"
; in the body of BIN_ASC above.
d_point cse	dec_no,#fix*2+1
	ret
	setb	zs
	mov	indirect,#ASC_dp
	inc	buffer
	dec	fsr
	ret
See also:
Comments:
| file: /Techref/microchip/seepicsrc/psbpix/serout2.htm, 13KB, , updated: 2006/9/17 09:53, local time: 2025/10/31 03:51, 
 
216.73.216.87,10-2-37-96:LOG IN | 
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://www.piclist.com/tecHREF/microchip/seepicsrc/psbpix/serout2.htm"> microchip seepicsrc psbpix serout2</A> | 
| Did you find what you needed? | 
|  PICList 2025 contributors: o List host: MIT, Site host massmind.org, Top posters @none found - Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated! * Contributors: Richard Seriani, Sr. | 
| Welcome to www.piclist.com! | 
.