Voting

Category

assembly language

Bookmarking

Del.icio.us Digg Diigo DZone Earthlink Google Kick.ie
Windows Live LookLater Ma.gnolia Reddit Rojo StumbleUpon Technorati

Language Assembler (PIC/14bit)

Date:04/20/05
Author:Thilo Manske
URL:n/a
Comments:6
Info:n/a
Score: (3.49 in 41 votes)
;	$Id: 99bottlesofbeer.asm,v 1.3 2003/10/23 10:17:21 thilo Exp thilo $
;
;	99 bottles of beer on the wall for any recent midrange Microchip MCU with 14bit
;	programm word (PIC16CXXX/PIC16FXXX family) and USART module, e.g. all PIC16F87x
;
;	written by Thilo Manske 
;
;	needs 3 GP registers and 158 words (~277 bytes) of program memory
;	use gpasm to assemble (see http://gputils.sourceforge.net/)

;	adjust the following lines for your CPU
	list	p=16f873
	include "p16f873.inc"
	__config _WDT_OFF & _XT_OSC

; GP registers, since they are in [0x70..0x7f] they are available in all banks
; and we don't have to care about bank switching when we access them
	cblock 0x70
	pointer
	bottles10
	bottles1
	endc

;; macro to select the correct bank for <address>
;; The default BANKSEL macro always sets/clears both bank bits, but we only
;; use bank 0 and 1 and don't have to take care of RP1
SELBANK 	macro	address
	if address < 0x80
		bcf	STATUS,RP0
	else
		bsf	STATUS,RP0
	endif
	endm

; start
	org 0
	SELBANK SPBRG
	movlw	d'38'		; adjust this for your clock freq/baud rate
	movwf	SPBRG

	movlw	(1<<TXEN)	; enable the transmitter
	movwf	TXSTA		; TXSTA is in the same bank as SPBRG

	SELBANK	RCSTA
	movlw	(1<<SPEN)	; enable the serial port
	movwf	RCSTA

restart:
	movlw	9
	movwf	bottles10
	movwf	bottles1

bigloop:
	call	nbottlesofbeer
	call	onthewall
	call 	commacrlf
	call	nbottlesofbeer
	call	stopcrlf

	movlw	takeonedowntxt
	call	stringout
	call	commacrlf

	decf	bottles1,f
	bnz	goon		; second digit==0?

	tstf	bottles10,f	; and first digit==0 as well?
	bz	outofbeer	; no more bottles of beer :(

goon:
	btfss	bottles1,7	; underflow in second digit?
		goto	ok		

	decf	bottles10,f	; yes

	movlw	9
	movwf	bottles1
ok:
	call	nbottlesofbeer
	call	onthewall
	call	stopcrlf
	call	crlf
	goto	bigloop
	
outofbeer:
	movlw	nomoretxt
	call	stringout
	call	bottlesofbeer
	call	stopcrlf

	SELBANK	TXSTA
	btfss	TXSTA,TRMT	; wait for the transmit buffer to drain
		goto	$-1

	sleep			; Good night!

	goto	restart	; since we haven't enabled any interrupts, there isn't
			; any chance the PIC will ever wake up and get here
; subroutines

;;	writes ".\r\n"
stopcrlf
	movlw	'.'
	goto	$+2		; skip next instruction	
;;	writes ",\r\n"
commacrlf:
	movlw	','
	call	charout
;; writes carriage return + linefeed
crlf:
	movlw	'\r'
	call	charout
	movlw	'\n'
;; puts char in w out on the serial bus
charout:
	SELBANK	TXSTA
	btfss	TXSTA,TRMT	; send buffer empty?
		goto $-1

	SELBANK	TXREG
	movwf	TXREG
	return

;; writes "n bottles of beer"
nbottlesofbeer:
	movf	bottles10,w
	bnz	firstdigit	; first digit zero?

	decf	bottles1,w	; second digit one?
	bz	onebottleofbeer	; one last bottle :-/
	goto	seconddigit
firstdigit
	addlw	'0'
	call	charout
seconddigit
	movf	bottles1,w
	addlw	'0'
	call	charout
;; writes "bottles of beer"
bottlesofbeer
	movlw	bottletxt
	call	stringout
	movlw 	's'
	call	charout
;; writes "of beer"
ofbeer
	movlw	ofbeertxt
;; writes string w is pointing to
stringout
	movwf	pointer
	call	getchar
	addlw	0		; test for zero (flag is not set by retlw)
	skpnz
		return		; yes -> end of string
	call	charout
	incf	pointer,w
	goto	stringout
getchar				; this will look weird to people who don't know how
	movwf	PCL		; you read data out of a PICs program memory ;)

;; writes "1 bottle of beer"
onebottleofbeer
	movlw	'1'
	call	charout
	movlw	bottletxt
	call	stringout
	goto	ofbeer
;; writes "on the wall"
onthewall
	movlw	onthewalltxt
	goto	stringout

; "data subroutines"
bottletxt
	dt " bottle{CODE}"
ofbeertxt
	dt " of beer{CODE}"
onthewalltxt
	dt " on the wall{CODE}"
takeonedowntxt
	dt "Take one down, pass it around{CODE}"
nomoretxt
	dt "No more{CODE}"

	end

Download Source | Write Comment

Alternative Versions

Comments

>>  martin said on 10/30/06 08:09:08

martin great, great, GREAT!
i worked with pics some time ago,
so can say this is GREAT!
i'd love to see this code running

>>  sawlin said on 01/21/07 15:49:40

sawlin great , i want more example like this ,it is very useful for me,

>>  Peter said on 01/12/10 13:41:28

Peter Nice try, unfortunately this code will never work since PIC16xxx does not know the following instructions: bnz, bz, tstf, skpnz

>>  Peter said on 01/13/10 16:44:26

Peter I now realise these instructions (bnz, bz, tstf, skpnz) are build in gpasm macros. So this code probably works after all.

>>  Jim Robertson said on 08/07/10 01:28:30

Jim Robertson MPASM MACROS

bnz MACRO _Address
btfss STATUS, Z
goto _Address
ENDM

bz MACRO _Address
btfsc STATUS, Z
goto _Address
ENDM

tstf MACRO _reg
movf _reg, F
ENDM

skpnz MACRO
btfsc STATUS, Z
ENDM

>>  Han ten Have said on 08/08/10 15:07:33

Han ten Have This is why I discarded macro-assembly a long time ago.

Download Source | Write Comment

Add Comment

Please provide a value for the fields Name, Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.

Please don't post large portions of code here! Use the form to submit new examples or updates instead!

Name:

eMail:

URL:

Security Code:
  
Comment: