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

📄 mypaulm2.asm

📁 8051 monitor programm: - use external ram to run user program - use eeprom to save user program
💻 ASM
📖 第 1 页 / 共 4 页
字号:
; PAULMON2, a user-friendly 8051 monitor, by Paul Stoffregen; Please email comments, suggestions, bugs to paul@ece.orst.edu; It's free.  PAULMON2 is in the public domain.  You may copy; sections of code from PAULMON2 into your own programs, even; for commercial purposes.  PAULMON2 should only be distributed; free of charge, but may be bundled as 'value-added' with other; products, such as development boards, CDROMs, etc.  Please; distribute the PAULMON2.DOC file and other files, not just; the object code!; The PAULMON2.EQU and PAULMON2.HDR files contain valuable; information that could help you to write programs for use; with PAULMON2.; PAULMON2 is in the public domain. PAULMON2 is distributed in; the hope that it will be useful, but without any warranty;; without even the implied warranty of merchantability or fitness; for a particular purpose. ; You are probably reading this code to see what it looks like; and possibly learn something, or to modify it for some reason.; Either is ok, but please remember that this code uses a number; of tricks to cram all the functionality into just 4k.  As a; result, the code can be difficult to read, and adding new; features can be very difficult without growing beyond 4k.  To; add or modify commands in PAULMON2, please consider using the; "external command" functionality.  It is easier to develop; new commands this way, and you can distribute them to other; users.  Email paul@ece.orst.edu if you have new PAULMON2; commands to contribute to others.  Details about adding new; commands to PAULMON2 (with examples) can be found at:; http://www.ece.orst.edu/~paul/8051-goodies/pm2_docs/addons.html;---------------------------------------------------------;;							  ;;	    PAULMON2's default configuration		  ;;							  ;;---------------------------------------------------------;; PAULMON2 should be assembled using the modified AS31 assembler,; originally written by Ken Stauffer, many small changes by Paul; Stoffregen.  This free assembler is available on the web at; http://www.ece.orst.edu/~paul/8051-goodies/goodies-index.html; As well, these web pages have a fill-out form which makes it; very easy to custom configure PAULMON2.  Using this form will; edit the code for you, run the AS31 assmebler, and send you the; object code to program into your chip.; These two parameters control where PAULMON2 will be assembled,; and where it will attempt to LJMP at the interrupt vector locations..equ	base, 0x0000		;location for PAULMON2.equ    vector, 0x8000    ;location to LJMP interrupt vectors change to 8000h; These three parameters tell PAULMON2 where the user's memory is; installed.  "bmem" and "emem" define the space that will be searched; for program headers, user installed commands, start-up programs, etc.; "bmem" and "emem" should be use so they exclude memory areas where; perphreal devices may be mapped, as reading memory from an io chip; may reconfigure it unexpectedly.  If flash rom is used, "bmem" and "emem"; should also include the space where the flash rom is mapped..equ    pgm, 0x8000             ;default location for the user program.equ    bmem, 0x1000            ;where is the beginning of memory.equ	emem, 0xFFFF		;end of the memory; Flash ROM parameters.	 If "has_flash" is set to zero, all flash rom; features are turned off, otherwise "bflash" and "eflash" should specify; the memory range which is flash rom.	Though AMD doesn't suggest it,; you may be able to map only a part of the flash rom with your address; decoder logic (and not use the rest), but you should be careful that; "bflash" and "eflash" don't include and memory which is NOT flash rom; so that the erase algorithm won't keep applying erase pulses until it; finally gives up (which will stress the thin oxide and degrade the; flash rom's life and reliability).  "erase_pin" allows you to specify; the bit address for a pin which (if held low) will tell PAULMON2 to; erase the flash rom chip when it starts up.  This is useful if you; download programs with the "start-up" headers on them and the code you've; put in the flash rom crashes!.equ	has_flash, 0		;set to non-zero value if flash installed.equ	bflash, 0x8000		;first memory location of Flash ROM.equ	eflash, 0xFFFF		;last memory location of Flash ROM;.equ	 erase_pin, 0		 ;00 = disable erase pin feature.equ   erase_pin, 0xB5	       ;B5 = pin 15, P3.5 (T1); Please note... much of the memory management code only looks at the; upper 8 bits of an address, so it's not a good idea to somehow map; your memory chips (with complex address decoding logic) into chunks; less than 256 bytes.	In other words, only using a piece of a flash; rom chip and mapping it between C43A to F91B would confuse PAULMON2; (as well as require quit a bit of address decoding logic circuitry); To set the baud rate, use this formula or set to 0 for auto detection; baud_const = 256 - (crystal / (12 * 16 * baud));.equ	baud_const, 0		;automatic baud rate detection;.equ	baud_const, 255		;57600 baud w/ 11.0592 MHz;.equ	baud_const, 253		;19200 baud w/ 11.0592 MHz;.equ	baud_const, 252		;19200 baud w/ 14.7456 MHz;.equ	baud_const, 243		;4808 baud w/ 12 MHz.equ	baud_const, 244		;9600 baud w/ 22.1184 MHz.equ	line_delay, 6		;num of char times to pause during uploads; About download speed: when writing to ram, PAULMON2 can accept data; at the maximum baud rate (baud_const=255 or 57600 baud w/ 11.0592 MHz).; Most terminal emulation programs introduce intentional delays when; sending ascii data, which you would want to turn off for downloading; larger programs into ram.  For Flash ROM, the maximum speed is set by; the time it takes to program each location... 9600 baud seems to work; nicely for the AMD 28F256 chip.  The "character pacing" delay in a; terminal emulation program should be sufficient to download to flash; rom and any baud rate.  Some flash rom chips can write very quickly,; allowing high speed baud rates, but other chips can not.  You milage; will vary...; Several people didn't like the key definations in PAULMON1.; Actually, I didn't like 'em either, but I never took the time; to change it.	 Eventually I got used to them, but now it's; really easy to change which keys do what in PAULMON2.	 You; can guess what to do below, but don't use lowercase..equ	help_key, '?'		;help screen.equ	dir_key,  'M'		;directory.equ	run_key,  'R'		;run program.equ	dnld_key, 'D'		;download.equ	upld_key, 'U'		;upload.equ	nloc_key, 'N'		;new memory location.equ	jump_key, 'J'		;jump to memory location.equ	dump_key, 'H'		;hex dump memory.equ	intm_key, 'I'		;hex dump internal memory.equ	edit_key, 'E'		;edit memory.equ	clrm_key, 'C'		;clear memory.equ	erfr_key, 'Z'		;erase flash rom; timing parameters for AMD Flash ROM 28F256.  These parameters; and pretty conservative and they seem to work with crystals; between 6 MHz to 24 MHz... (tested with AMD 28F256 chips only); unless you know this is a problem, it is probably not a good; idea to fiddle with these..equ	pgmwait, 10		;22.1184 MHz crystal assumed;.equ	pgmwait, 19		;11.0592 MHz.equ	verwait, 5.equ	erwait1, 40		;fourty delays @22.1184;.equ	erwait1, 20		;twenty delays for 11.0592 MHz.equ	erwait2, 229		;each delay .5 ms @22.1184MHz; These symbols configure paulmon2's internal memory usage.; It is usually not a good idea to change these unless you; know that you really have to..equ	psw_init, 0		;value for psw (which reg bank to use).equ	dnld_parm, 0x10		;block of 16 bytes for download.equ	stack, 0x30		;location of the stack.equ	baud_save, 0x78		;save baud for warm boot, 4 bytes;---------------------------------------------------------;;							  ;;		     Interrupt Vectors			  ;;  (and little bits of code crammed in the empty spaces)  ;;							  ;;---------------------------------------------------------;	.org	base	ljmp	poweron		;reset vector	.org	base+3	ljmp	vector+3	;ext int0 vectorr6r7todptr:	mov	dpl, r6	mov	dph, r7	ret	.org	base+11	ljmp	vector+11	;timer0 vectordptrtor6r7:	mov	r6, dpl	mov	r7, dph	ret	.org	base+19	ljmp	vector+19	;ext int1 vectordash:	mov	a, #'-'		;seems kinda trivial, but each time	ajmp	cout		;this appears in code, it takes 4	nop			;bytes, but an acall takes only 2	.org	base+27	ljmp	vector+27	;timer1 vectorcout_sp:acall	cout	ajmp	space	nop	.org	base+35	ljmp	vector+35	;uart vectordash_sp:acall	dash	ajmp	space	nop	.org	base+43	ljmp	vector+43	;timer2 vector (8052);---------------------------------------------------------;;							  ;;	The jump table for user programs to call	  ;;	      subroutines within PAULMON		  ;;							  ;;---------------------------------------------------------;.org	base+46		;never change this line!!  Other			;programs depend on these locations			;to access paulmon2 functions	ajmp	phex1		;2E	ajmp	cout		;30	ajmp	cin		;32	ajmp	phex		;34	ajmp	phex16		;36	ajmp	pstr		;38	ajmp	ghex		;3A	ajmp	ghex16		;3C	ajmp	esc		;4E	ajmp	upper		;40	ljmp	autobaud	;42pcstr_h:ljmp	pcstr		;45	ajmp	newline		;48	ljmp	lenstr		;4A	ljmp	pint8u		;4D	ljmp	pint8		;50	ljmp	pint16u		;53	ljmp	smart_wr	;56	ljmp	prgm		;59	ljmp	erall		;5C	ljmp	find		;5Fcin_filter_h:	ljmp	cin_filter	;62	ajmp	asc2hex		;64;---------------------------------------------------------;;							  ;;	       Subroutines for serial I/O		  ;;							  ;;---------------------------------------------------------;cin:	jnb	ri, cin	clr	ri	mov	a, sbuf	retdspace: acall	spacespace:	mov	a, #' 'cout:	jnb	ti, cout	clr	ti		;clr ti before the mov to sbuf!	mov	sbuf, a	ret;clearing ti before reading sbuf takes care of the case where;interrupts may be enabled... if an interrupt were to happen;between those two instructions, the serial port will just;wait a while, but in the other order and the character could;finish transmitting (during the interrupt routine) and then;ti would be cleared and never set again by the hardware, causing;the next call to cout to hang forever!newline2:			;print two newlines	acall	newlinenewline:push	acc		;print one newline	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_filter_h	;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_filter_h	;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_filter_h	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	ret	;carry set if invalid inputasc2hex:	clr	c	add	a, #208	jnc	hex_not	add	a, #246	jc	hex_maybe	add	a, #10	clr	c	rethex_maybe:	add	a, #249	jnc	hex_not	add	a, #250	jc	hex_not	add	a, #16	clr	c	rethex_not:setb	c	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	ret;a not so well documented feature of pstr is that you can print;multiple consecutive strings without needing to reload dptr;(which takes 3 bytes of code!)... this is useful for inserting;numbers or spaces between strings.pstr:	push	accpstr1:	clr	a	movc	a, @a+dptr	inc	dptr	jz	pstr2	mov	c, acc.7	anl	a, #0x7F	acall	cout	jc	pstr2	sjmp	pstr1pstr2:	pop	acc	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	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	lenstr1lenstr2:pop	acc	retesc:  ;checks to see if <ESC> is waiting on serial port      ;C=clear if no <ESC>, C=set if <ESC> pressed      ;buffer is flushed	push	acc	clr	c	jnb	ri,esc2	mov	a,sbuf	cjne	a,#27,esc1	setb	cesc1:	clr	riesc2:	pop	acc	ret;---------------------------------------------------------;;							  ;;    The 'high-level' stuff to interact with the user	  ;;							  ;;---------------------------------------------------------;menu: ;first we print out the prompt, which isn't as simple      ;as it may seem, since external code can add to the      ;prompt, so we've got to find and execute all of 'em.	mov	dptr, #prompt1	  ;give 'em the first part of prompt	acall	pcstr_h	mov	a, r7	acall	phex	mov	a, r6	acall	phex	;mov	 dptr, #prompt2	acall	pstr;now we're finally past the prompt, so let's get some input	acall	cin_filter_h	;get the input, finally	acall	upper;push return address onto stack so we can just jump to the program	mov	b, #(menu & 255)  ;we push the return address now,	push	b		  ;to save code later...	mov	b, #(menu >> 8)	  ;if bogus input, just ret for	push	b		  ;another prompt.;first we'll look through memory for a program header that says;it's a user installed command which matches what the user pressed;user installed commands need to avoid changing R6/R7, which holds;the memory pointer.  The stack pointer can't be changed obviously.;all the other general purpose registers should be available for;user commands to alter as they wish.menux:	mov	b, a		;now search for external commands...	mov	dptr, #bmemmenux1: acall	find	jnc	menuxend	   ;searched all the commands?	mov	dpl, #4	clr	a	movc	a,@a+dptr	cjne	a, #254, menux2	 ;only FE is an ext command	inc	dpl	clr	a	movc	a,@a+dptr	cjne	a, b, menux2	  ;only run if they want it	acall	space	mov	dpl, #32	acall	pstr		   ;print command name	acall	newline	mov	dpl, #64	clr	a	jmp	@a+dptr		;take a leap of faith and jump to it!menux2: inc	dph	mov	a, dph	cjne	a, #((emem+1) >> 8) & 255, menux1menuxend:	mov	a, b;since we didn't find a user installed command, use the builtin onesmenu1a: cjne	a, #help_key, menu1b	mov	dptr, #help_cmd2	acall	pcstr_h	ajmp	helpmenu1b: cjne	a, #dir_key, menu1c	mov	dptr, #dir_cmd	acall	pcstr_h	ajmp	dirmenu1c: cjne	a, #run_key, menu1d	mov	dptr, #run_cmd	acall	pcstr_h	ajmp	runmenu1d: cjne	a, #dnld_key, menu1e	mov	dptr, #dnld_cmd	acall	pcstr_h	ajmp	dnldmenu1e: cjne	a, #upld_key, menu1f	mov	dptr, #upld_cmd

⌨️ 快捷键说明

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