EPROM 27512 模擬器製作 ── 始用並列埠

作者 : 鄭旭崇

§前言

    在 8051 盛行的現在,許多的控制器都用他來當作微處理機,例如:溫度控制器,PID壓力控制器
,化學用PH儀...等等不勝枚舉.通常8051內部只有4k BYTE 程式記憶體,而8052內部只有8k BYTE 
程式記憶體,如果我們的程式大小超過 4K BYTE 或 8k BYTE 的話,這時就必須外加一顆 EPROM
或是 Flash ROM 了.就一般販售的 ROM 模擬器而言,一套至少要 NT2000 元左右,如果自己製作
的話,成本將不到 NT600 元,這對於貧窮的學生們,個人工作室將是節省支出的方法.
而且使用 ROM 模擬器的優點除了縮短開發時間,更可不限次數的燒錄.

本 ROM 模擬器的特色:
* 支援 32kx8bit 27256 和 64kx8bit 27512.
* 不必插卡,無須外加電源.(電源由目標板 target baord 供應)
* 程式 Download 迅速,約 0.5 秒.
* 接受 Binary 檔案格式.
* 作業環境 Windows 95/98 , DOS.

§並列埠的原理

壹.並列埠I/O位址之取得
    一般個人電腦內定的第一個並列介面埠(LPT1),起始位址為0378H,目前
已經被列為標準的ON  BOARD基本配備了。您的電腦若有加裝Printer c
ard,那麼它的起始位址應該是0278H.在每一電腦內部最多可以裝設3個並列埠
,作業系統保留了3個I/O空間給並列介面。並列埠的I/O位址範圍如表一所示。

┌───────────────┬──────┐
│  I/O  Port  位址	│  介面名稱  │
├───────────────┼──────┤
│  0378H - 037AH	│  LPT1  │
├───────────────┼──────┤
│  0278H - 027AH	│  LPT2  │
├───────────────┼──────┤
│  03BCH - 03BEH	│  LPT3  │
└───────────────┴──────┘
	<表一> 並列埠的I/O位址範圍

    另外,並列埠的起始位址亦可由記憶體內的資訊取得,見表二。

┌───────┬──────────┐
│記憶體位址	│   I/O起始位址   │
├───────┼──────────┤
│0000:0408H	│   LPT1	      │
├───────┼──────────┤
│0000:040AH	│   LPT2	      │
├───────┼──────────┤
│0000:040DH	│   LPT3	      │
└───────┴──────────┘
 <表二> 由記憶體取得並列埠的I/O位址

    我們可以使用Windows所提供的debug.exe來查看,在DOS的提
示字元下輸入:
C:\>DEBUG
-D  0000:0408
0000:0400			   78 03 00 00 00 00 00 00	     x.......
0000:0410  23 54 00 80 02 80 00 60-00 00 3A 00 3A 00 53 1F   #T.....`..:.:.S.
0000:0420  54 14 0D 1C 44 20 30 0B-30 0B 30 0B 30 0B 3A 27   T...D 0.0.0.0.:'
0000:0430  30 0B 34 05 30 0B 38 09-0D 1C 2E 34 4C 26 00 00   0.4.0.8....4L&..
0000:0440  00 00 C0 00 00 00 00 00-00 03 50 00 00 80 00 00   ..........P.....

我們可以清楚地看到在記憶體0000:0408的位址上,記錄著78  03,讀者
一定會問LPT1的起始位址不是0378H嗎?怎麼會是7803呢?其實這是作業
系統將高BYTE的資料放在高位址,低BYTE的資料放在低位址的結果。相信寫過
MASM組合語言的人,對這種資料的排法應該感到不陌生才對。

貳.並列埠之名稱及用途
    小弟以LPT1為例,說明並列埠之名稱及用途。

I/O埠位址	功能
0378H	資料埠。當您的並列埠直接由主機板接出來,未經過KeyPro時
		,那麼此Port可以做資料雙向傳遞。值得注意的是,如果您的電
		腦已經插上了一個KeyPro的話,此Port只能當輸出用。若
		強制給它輸入電壓,恐有燒毀之虞,要特別小心。

0379H	狀態埠。為輸入埠,主要用來接收印表機的工作狀態。

037AH	控制埠。為輸出埠,主要用來送出信號給印表機。


    D-TYPE  25Pin並列埠接腳之對照,請參考下表。
┌────────┬──────┬─────┬──────────┐
│D-TYPE 25 Pin   │ 信號名稱	│ 位址.Bit │IN/OUT		  │
│接腳編號	  │		│	    │			  │
├────────┼──────┼─────┼──────────┤
│     1	  │ /STROBE	│ 037AH.0  │OUT		  │
├────────┼──────┼─────┼──────────┤
│     2∼9	  │ D0 TO D7	│ 0378H    │IN/OUT OR ONLY OUT  │
├────────┼──────┼─────┼──────────┤
│     10	  │ /ACK	│ 0379H.6  │IN		  │
├────────┼──────┼─────┼──────────┤
│     11	  │ BUSY	│ 0379H.7  │IN		  │
├────────┼──────┼─────┼──────────┤
│     12	  │ PE 	│ 0379H.5  │IN		  │
├────────┼──────┼─────┼──────────┤
│     13	  │ SLCT	│ 0379H.4  │IN		  │
├────────┼──────┼─────┼──────────┤
│     14	  │ /A.F.X	│ 037AH.1  │OUT		  │
├────────┼──────┼─────┼──────────┤
│     15	  │ /ERROR	│ 0379H.3  │IN		  │
├────────┼──────┼─────┼──────────┤
│     16	  │ /INIT	│ 037AH.2  │OUT		  │
├────────┼──────┼─────┼──────────┤
│     17	  │ /SCLT IN	│ 037AH.3  │OUT		  │
├────────┼──────┼─────┼──────────┤
│     18∼25 │ GND	│	    │OUT		  │
└────────┴──────┴─────┴──────────┘
<表三> D-TYPE  25Pin並列埠接腳對照表

    I/O位址379H與37AH並未用到所有的Bit。379H只用了5個Bit
,37AH只用了4個Bit。其中有些輸入位元被反向,有些輸出位元被反向,造成了
程式設定值與實際輸出值間的差異。以Port  037AH為例,程式在輸出控制碼前
,應先做轉換。轉換的方法其實很簡單,就是將實際輸出值除了Bit2沒有反向外,其
餘的Bit皆給他反向,再按照Bit0到Bit3的順序,以1,2,4,8的數值加
權,即可得到設定值。 轉換對照值請參考下表。
請注意,Port  037AH的Bit4到Bit7並沒有連接到並列埠上,所以這4
個Bit是Don’t  care的。
┌────┬──────────────┬───────┐
│ 設定值 │ Port 037AH 的 Bit 3 - 0	│ 實際輸出值	│
│	  │	 /B3	B2   /B1   /B0	│		│
├────┼──────────────┼───────┤
│   B	  │	  1	0     1     1	│     0	│
├────┼──────────────┼───────┤
│   A	  │	  1	0     1     0	│     1	│
├────┼──────────────┼───────┤
│   9	  │	  1	0     0     1	│     2	│
├────┼──────────────┼───────┤
│   8	  │	  1	0     0     0	│     3	│
├────┼──────────────┼───────┤
│   F	  │	  1	1     1     1	│     4	│
├────┼──────────────┼───────┤
│   E	  │	  1	1     1     0	│     5	│
├────┼──────────────┼───────┤
│   D	  │	  1	1     0     1	│     6	│
├────┼──────────────┼───────┤
│   C	  │	  1	1     0     0	│     7	│
├────┼──────────────┼───────┤
│   3	  │	  0	0     1     1	│     8	│
├────┼──────────────┼───────┤
│   2	  │	  0	0     1     0	│     9	│
├────┼──────────────┼───────┤
│   1	  │	  0	0     0     1	│     A	│
├────┼──────────────┼───────┤
│   0	  │	  0	0     0     0	│     B	│
├────┼──────────────┼───────┤
│   7	  │	  0	1     1     1	│     C	│
├────┼──────────────┼───────┤
│   6	  │	  0	1     1     0	│     D	│
├────┼──────────────┼───────┤
│   5	  │	  0	1     0     1	│     E	│
├────┼──────────────┼───────┤
│   4	  │	  0	1     0     0	│     F	│
└────┴──────────────┴───────┘
<表四> 設定值與輸出值轉換對照表

    現在我們可以用組合語言來控制它了。
┌────────────┬──────────────────┐
│由0378H輸出38H  │					│
├────────────┘					│
│MOV  AL,38H      ;將欲輸出的值存入AL.		│
│MOV  DX,0378H  ;將I/O位址存入DX.		│
│OUT  DX,AL	      ;把資料OUT出去.		│
└───────────────────────────────┘
┌────────────┬──────────────────┐
│由037AH輸出08H  │   				│
├────────────┘   				│
│MOV  AL,03H      ;查表四,當實際輸出值為08H時	│
│MOV  DX,037AH  ;程式設定值為03H.		│
│OUT  DX,AL	       				│
└───────────────────────────────┘
看到這裡,讀者是否對並列埠有更深一層的了解呢?小弟曾在第 252 期的專欄裡發表過
"始用並列埠製作 AT89C2051 燒錄器"一文後,至今仍有許多讀者來信問小弟如何使用並列埠讀取資料
的問題,小第在此幫各位解答.
關於 PRINTER PORT 的資料線(D0~D7) 在正常的情況下是不能當作輸入使用的.為了可以讓資料輸
入,我們可以用 Print port 的 0379H.4 ~ 0379H.7(PS4,PS5,PS6,PS7),這四個 bit ,再經由74LS244
當作 Buffer 切換,每次讀 4bit 分成兩次即可.如圖一所示.





			< 圖一 > 使用並列埠讀取資料

§線路圖 & 說明
    首先看到圖二為 ROM 模擬器的結構圖.CN1為公 25 Pin DSUB 連結器,CN2為 28 Pin 的夾式IC Pin,
J1 與 J2 分別是 20 Pin 和 28 Pin 的 HDC 雙排 Pin.





			< 圖二 > ROM 模擬器的結構圖

    圖三,圖四顯示著J1到CN1和J2到CN2的接線,其中J2雖然是 28 PIN HDC 雙排 Conector,但是 28 PIN
並非標準規格,所以讀者可以使用標準規格的 34 PIN HDC 雙排 Conector來取代,只用到 1 ~ 28 PIN 即可.
排線的使用長度最好是十五到二十公分,排線太長了信號會衰減,亦較容易受電磁干擾.排線太短了會造成操
作上的不方便.





			< 圖三 > J1到CN1的接線







			< 圖四 > J2到CN2的接線

    再來看到圖五是 ROM 模擬器的主線路,看起來有點複雜,但這可是小弟經過千辛萬苦才想出來的電路,
也曾經是小弟開發單晶片時不可缺乏的工具喔.況且如果 ROM 模擬器那麼簡單的話,那麼那些賣模擬器的
廠商豈不是要喝西北風了?言歸正傳,圖五我們看到兩顆 62256 U8,U9 是用來存放 64K BYTE 資料的地方,
在 U5,U6,U7 左邊的 D0...D7,和 A0...A15 分別是模擬 27512 的 D0...D7,和 A0...A15,U10C Pin8 及
U10C Pin 9 分別模擬 27512 的 /OE 及 /CE.U1,U11 是用來將 Print Port 的 PD0...PD7 解成 
RD0...RD7,RA0...RA15以便將資料寫入 62256 中.U10,U12,U13 負責控制 Data Bus 與 Address Bus 的
三態流向.

此電路的工作分成兩個時期,Download 時期和模擬時期.

在 Download 時期 U5,U6,U7 這三顆 IC 的第19腳拉到 High,因此 D0...D7,和 A0...A15 呈三態高阻抗輸出
,這是為了防止資料下載時影響 Target Board 的 Bus.
而此時 U2,U3,U4 的左邊輸出 RD0...RD7,和 RA0...RA15,由 RA15 和 U10C 來選擇 U8 或 U9這兩顆 RAM 的
/CE 致能,再經由 /RWE 信號線產生寫入時序,即可將資料寫入 62256 RAM 內,完成 Downlaod動作.

在 Download 時期結束後,
U5,U6,U7 三顆 IC 第19腳拉到 Low,使得
D0...D7,和 RD0...RD7 相通,A0...A15,和 RA0...RA15 相通.
U2,U3,U4 三顆 IC 第1腳拉到 High 以關閉輸出,進入ROM模擬時期,
這時已可以由 D0...D7,和 A0...A15 來讀取資料了.





			< 圖五 > ROM 模擬器的主線路

§程式 & 說明
    還是一句老話,組合語言是全宇宙公認最複雜最難懂的程式語言,其實組合語言的每一個指令都很簡
單,但是一旦把它們組合成一個程序或模組時,想要由這些指令碼去了解一個程序或模組的行為,則是相當
堅難。這就是組合語言奧妙與藝術的地方。學習組合語言的人口並不多,精通組合語言的人更是希有動物
,有鑑於此,小弟對於此程式不做太詳細的說明。看不懂的人也沒關係,你只要知道大概的原理,會用就好。

;********************************************
;* ROM 模擬器 Download 程式	作者:鄭旭崇 *
;********************************************
PRINT	MACRO	STR			  ;DOS 中斷呼叫,顯示字串之巨集定義
	MOV	DX,OFFSET STR		  ;
	MOV	AH,09H			  ;
	INT	21H			  ;
	ENDM				  ;

INPUT	MACRO	BUFF			  ;DOS 中斷呼叫,輸入字串之巨集定義
	MOV	DX,OFFSET BUFF		  ;
	MOV	AH,0AH			  ;
	INT	21H			  ;
	ENDM				  ;

H_OPEN	MACRO	FILE_NAME,MODE		  ;DOS 中斷呼叫,開啟檔案之巨集定義
	MOV	DX,OFFSET FILE_NAME	  ;
	MOV	AL,MODE 		  ;
	MOV	AH,3DH			  ;
	INT	21H			  ;
	ENDM				  ;

H_READ	MACRO	BUFF,BYTE,HAND		  ;DOS 中斷呼叫,讀取檔案之巨集定義
	MOV	DX,OFFSET BUFF		  ;
	MOV	CX,BYTE 		  ;
	MOV	BX,HAND 		  ;
	MOV	AH,3FH			  ;
	INT	21H			  ;
	ENDM
					  ;DOS 中斷呼叫,關閉檔案之巨集定義
H_CLOSE MACRO	HAND			  ;
	MOV	BX,HAND 		  ;
	MOV	AH,3EH			  ;
	INT	21H			  ;
	ENDM				  ;

H_OUT	MACRO	ABC,DEF 		  ;資料輸出之巨集定義
	MOV	DX,ABC			  ;
	MOV	AL,DEF			  ;
	OUT	DX,AL			  ;
	CALL	DLY			  ;
	ENDM				  ;

;=======================================================
_378H	EQU	378H			  ;並列埠 LPT1
_37AH	EQU	37AH			  ;

	.MODEL SMALL
	.DATA
BUFFER	DB	4096 DUP(?)		;存放被Download檔資料 4096 Byte.
PROMPT	DB	'COPY RIGHT BY Fraptt Cheng.',10,13,'INPUT FILE NAME:','$'
PROMPT1 DB	10,13,'SUCCESS !$'
PROMPT2 DB	10,13,7,'FILE NOT FOUND!','$'
IN_BUFF DB	32,33 DUP(?)		;存放被燒錄的檔案名稱
HANDLE	DW	?			;檔案碼
ADDRESS DB	2 DUP(?)		;Download 位址計數
DAT	DB	?			;資料暫存區

	.CODE				;程式碼開始
BEGIN:	MOV	AX,DS
	MOV	ES,AX

	MOV	AX,@DATA		;
	MOV	DS,AX			;
	MOV	BX,80H			;
	MOV	AL,ES:[BX]		;
	CMP	AL,0			;檢查PSP內有無參數?
	JE	L1_COM			;

	MOV	DI,OFFSET IN_BUFF	;PSP內,有參數
					;
	MOV	CX,20			;將參數值複製一份到 IN_BUFF
L0:	MOV	AL,ES:[BX]		;
	CMP	AL,0DH			;
	JE	L2_COM			;
	MOV	DS:[DI],AL		;
	INC	DI			;
	INC	BX			;
	LOOP	L0			;

L1_COM: PRINT	PROMPT			;PSP內,沒有參數
	INPUT	IN_BUFF 		;顯示 PROMPT1 提示使用者輸入檔案名稱
L2_COM: 				;
	MOV	BL,IN_BUFF[1]		;
	XOR	BH,BH			;
	MOV	BYTE PTR IN_BUFF[BX+2],0;
	H_OPEN	IN_BUFF+2,0		;開啟檔案
	JC	CLOSE1			;無法開啟跳到 CLOSE1
	MOV	HANDLE,AX		;

	MOV	ADDRESS[0],0		;ROM 模擬器位址記數 = 0
	MOV	ADDRESS[1],0		;
	LEA	SI,BUFFER		;
;--------------------------------------
RD_FL:	H_READ	BUFFER,4096,HANDLE
	CMP	AX,0
	JE	CLOSE
	CALL	DOWN_LOAD
	JMP	RD_FL
CLOSE:					;關閉檔案
	H_OUT	_378H,0FH		;DISABLE 74574
	H_OUT	_37AH,0C3H
	H_OUT	_37AH,0CBH
	H_OUT	_37AH,0C3H
	PRINT	PROMPT1			;顯示成功訊息
	JMP	CLOSE2

CLOSE1: PRINT	PROMPT2			;顯示檔案開啟失敗訊息
CLOSE2: H_CLOSE HANDLE			;關閉檔案
	MOV	AH,4CH
	INT	21H			;離開程式

;=========================================
DOWN_LOAD:
	MOV	CX,4096 		;DOWN LOAD 4096 BYTES.
D1:	LODSB				;AL = SI -> BUFFER DATA.
	MOV	DAT,AL
	CALL	WRITE_BYTE

	MOV	BL,ADDRESS[0]		;ADDRESS = ADDRESS + 1
	MOV	BH,ADDRESS[1]
	INC	BX
	MOV	ADDRESS[0],BL
	MOV	ADDRESS[1],BH
	LOOP	D1

	LEA	SI,BUFFER
EXIT:	RET
;============================================
WRITE_BYTE:
	H_OUT	_378H,00H	 ;ENABLE 74574
	H_OUT	_37AH,0C3H
	H_OUT	_37AH,0CBH
	H_OUT	_37AH,0C3H

	H_OUT	_378H,DAT	 ;TRAN. DATA
	H_OUT	_37AH,0C2H
	H_OUT	_37AH,0CAH
	H_OUT	_37AH,0C2H

	H_OUT	_378H,ADDRESS[0] ;TRAN. LOW ADDRESS
	H_OUT	_37AH,0C1H
	H_OUT	_37AH,0C9H
	H_OUT	_37AH,0C1H

	H_OUT	_378H,ADDRESS[1] ;TRAN. HI ADDRESS
	H_OUT	_37AH,0C0H
	H_OUT	_37AH,0C8H
	H_OUT	_37AH,0C0H

	H_OUT	_37AH,0C6H
	H_OUT	_37AH,0CEH	  ;WRITE TO RAM
	H_OUT	_37AH,0C6H

	H_OUT	_378H,0FH	 ;DISABLE 74574
	H_OUT	_37AH,0C3H
	H_OUT	_37AH,0CBH
	H_OUT	_37AH,0C3H
	RET
;================================================
DLY:				;延時副程式
	PUSH	CX
	MOV	CX,0F2H
DLY1:	DEC	CX
	CMP	CX,0
	JNE	DLY1
	POP	CX
	RET


	.STACK			;定義堆疊段
	END	BEGIN

    原始程式以文書編輯軟體寫好後,以檔案名稱為 EROM.ASM 存檔。存檔後便可對
EROM.ASM 進行組譯及連結。組譯軟體必須是 MASM 5.0 以上的版本,使用 MASM 5.0
以下版本的朋友,本原始程式在區段宣告的地方須作小幅度的修改,怎麼修改,請參考相
關書籍。原始程式經過組譯及連結後,產生 EROM.EXE 之可執行檔,可在 DOS 命令列
下直接執行。

組譯程式,在 DOS 提示字元下輸入:
C:\>MASM EROM;;;;

Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.


  51252 + 258220 Bytes symbol space free

      0 Warning Errors
      0 Severe	Errors

連結程式,在 DOS 提示字元下輸入:
C:\>MASM EROM;;;;

Microsoft (R) 8086 Object Linker  Version 3.05
Copyright (C) Microsoft Corp 1983, 1984, 1985.	All rights reserved.

  -- EROM.EXE 可執行檔已產生 --


執行例:

C:\>EROM TEST.TSK
	.....約0.5秒
SUCCESS !
	或
C:\>EROM
COPY RIGHT BY Fraptt Cheng.
INPUT FILE NAME:TEST.TSK
	.....約0.5秒
SUCCESS !


§結語

    這個 ROM 模擬器已經跟隨著小弟做過許多 CASE ,說實在還挺好用的.而今發表出來無非是想要
讓更多有緣的人一起分享小弟的成果,讓大家有一個更好的學習開發環境.其實說到 Print Port 還有
很多東西可以做的,像是,模擬PLC 等等,有興趣的讀者不妨研究看看,也許還會發掘
更多用途呢!讀者朋友對於本文章有任何問題或建議,歡迎您 E-mail 給我,小弟的 E-mail是 :
FineTech@ms69.hinet.net 當然,讀者朋友們想要程式的 Source Code 的話,也可以來信索取.



http://www.finetech.idv.tw