好的,我來幫你系統地解析這道題。這是一個經典的 8051 單片機擴展外部程序存儲器(EPROM) 的題目,涵蓋了硬件電路設計和軟件編程兩個方面。下面分步講解。
一、題目核心要求解析
要素 說明
MCU 89C51(內部有 4KB Flash,地址 0000H~0FFFH)
EPROM 27128(16K×8 bit,地址 0000H~3FFFH)
真值表位置 外部 ROM 的 1000H 開始的單元
功能 按鍵計數,在數碼管上顯示按鍵次數
關鍵點 真值表必須放在 外部 ROM 中,程序用 MOVC 查表讀取
二、27128 芯片引腳功能
你提到的引腳對應關系:
27128 引腳 功能說明
Q0~Q7 數據輸出線(8 位),接 89C51 的 P0 口
A0~A13 地址線(14 位),尋址 16K 空間
/E (OE) 輸出使能(低有效),接 89C51 的 PSEN
/G (CE) 片選(低有效),直接 接地 或接譯碼電路
補充:27128 還有 VCC (+5V)、GND、VPP(編程高壓,正常使用時接+5V)等引腳。
三、擴展電路設計原理
8051 訪問外部程序存儲器時,P0 口分時復用(先送低8位地址,后傳數據),P2 口提供高8位地址,因此需要 地址鎖存器。
關鍵信號連接
89C51 引腳 連接目標 作用
P0.0~P0.7 → 74HC373 的 D0~D7(輸入側) 分時輸出低8位地址 / 輸入數據
74HC373 的 Q0~Q7 → 27128 的 A0~A7 鎖存后的低8位地址
P2.0~P2.5 → 27128 的 A8~A13 高6位地址(P2.6、P2.7 可做其他用途)
ALE → 74HC373 的 LE (鎖存使能) 地址鎖存控制
PSEN → 27128 的 /E (OE) 外部程序存儲器讀選通
EA → VCC (+5V) 先訪問內部 ROM,超范圍自動轉外部
27128 的 /G (CE) → GND 始終片選有效
P1 口 → 數碼管段碼(如共陰數碼管 a~dp) 顯示按鍵次數
完整電路原理圖(文字描述)
+-----------+
P0.0~P0.7 -->| D0~D7 Q0|--> A0~A7 +-----------+
ALE -->| LE Q7|--> | |
| 74HC373 | | 27128 |
+-----------+ | EPROM |
| |
P2.0~P2.5 ----------------------------------->| A8~A13 |
| |
PSEN ------------------------------------->| /E (OE) |
| |
GND ------------------------------------->| /G (CE) |
| |
+5V ------------------------------------->| VPP, VCC |
+-----------+
89C51 EA --> VCC (+5V) // 先訪問內部4KB,超0FFFH自動轉外部
P1.0~P1.7 --> 數碼管段碼 (a~dp + dp)
P3.2 (INT0) --> 按鍵輸入 (或P3.3等)
地址映射說明
89C51 內部 ROM 地址范圍:0000H ~ 0FFFH(4KB)27128 外部 ROM 地址范圍:0000H ~ 3FFFH(16KB)
EA=1 時的訪問規則:
地址 0000H~0FFFH:訪問內部 Flash(程序代碼放這里)
地址 1000H~3FFFH:自動轉向外部 27128 讀取
所以 真值表放在 1000H~10xxH,程序放在內部 0000H~0FFFH,互不沖突 ✅
四、軟件程序設計
4.1 真值表定義(要燒錄到 27128 中)
假設使用 共陰極數碼管,段碼順序:a→b→c→d→e→f→g→dp
地址 內容 顯示
1000H → 3FH 0
1001H → 06H 1
1002H → 5BH 2
1003H → 4FH 3
1004H → 66H 4
1005H → 6DH 5
1006H → 7DH 6
1007H → 07H 7
1008H → 7FH 8
1009H → 6FH 9
假設使用 共陽極數碼管,段碼順序:a→b→c→d→e→f→g→dp
地址 內容 顯示
1000H → C0H 0
1001H → F9H 1
1002H → A4H 2
1003H → B0H 3
1004H → 99H 4
1005H → 92H 5
1006H → 82H 6
1007H → F8H 7
1008H → 80H 8
1009H → 90H 9
燒錄 27128 時需要編程器,將上述數據按地址寫入 27128 中。
4.2 89C51 程序(匯編語言)
;============================================
; 89C51 + 27128 外部ROM 按鍵計數顯示程序
; 程序放在內部 Flash,真值表在外部ROM 1000H
;============================================
ORG 0000H ; 復位入口
LJMP MAIN
ORG 0030H ; 主程序起始地址
MAIN:
MOV SP, #60H ; 設置堆棧
MOV P1, #00H ; 數碼管初始滅
CLR A
MOV R0, #00H ; R0 作為按鍵計數器(0~9循環)
LOOP:
; 檢測按鍵(假設按鍵接P3.2,低有效)
JB P3.2, LOOP ; 沒按下則等待
ACALL DELAY_20MS ; 消抖
JB P3.2, LOOP ; 再次確認
; 按鍵已按下,計數加1
INC R0
CJNE R0, #10, DISP ; 到10則回0
MOV R0, #00H
DISP:
; 從外部ROM 1000H 查表讀取段碼
MOV DPTR, #1000H ; 真值表基地址
MOV A, R0 ; 取計數值
MOVC A, @A+DPTR ; 從外部ROM讀取段碼
MOV P1, A ; 輸出到數碼管
; 等待按鍵釋放
WAIT_UP:
JNB P3.2, WAIT_UP ; 按鍵未釋放則等待
ACALL DELAY_20MS ; 消抖
JNB P3.2, WAIT_UP
SJMP LOOP ; 繼續循環
; 簡單延時子程序(假設12MHz晶振)
DELAY_20MS:
MOV R6, #40
DLY1:
MOV R7, #248
DJNZ R7, $
DJNZ R6, DLY1
RET
END
4.3 C語言版本(可讀性更好)
#include <reg51.h>
sfr P1 = 0x90; // 數碼管段碼輸出口
sbit KEY = P3^2; // 按鍵輸入
void delay_ms(unsigned int ms)
{
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 125; j++);
}
unsigned char read_external_rom(unsigned int addr)
{
unsigned char code *pt; // code 指向程序存儲區
pt = (unsigned char code *)addr;
return *pt;
}
void main()
{
unsigned char count = 0;
unsigned char seg;
while(1)
{
if(KEY == 0) // 檢測按鍵按下
{
delay_ms(20); // 消抖
if(KEY == 0)
{
count++;
if(count >= 10) count = 0;
// 從外部ROM 1000H + count 處讀取段碼
seg = read_external_rom(0x1000 + count);
P1 = seg; // 輸出到數碼管
while(KEY == 0); // 等待釋放
delay_ms(20);
}
}
}
}
五、關鍵知識點總結
為什么要用鎖存器 74HC373?
8051 的 P0 口是 分時復用 的:在讀取外部 ROM 時,P0 先輸出 低8位地址(A0~A7),隨后切換為 數據總線(D0~D7)。鎖存器的作用就是把先出現的地址"鎖存"住,讓 EPROM 在整個讀周期都能拿到穩定的地址。
為什么 PSEN 接 /E 而不是 RD?
PSEN(Program Store Enable)是 8051 專用于讀取 外部程序存儲器 的選通信號
RD(P3.7)是用于讀取 外部數據存儲器(RAM/IO)的信號
27128 是 程序存儲器(ROM),所以用 PSEN 控制
為什么 EA 接 VCC?
EA=1 時,CPU 優先從內部 ROM 取指,只有 地址超過內部 ROM 范圍(89C51 為 0FFFH)時,才自動轉向外部 ROM。這樣:
程序代碼放內部 Flash(0000H~0FFFH)
MOVC 查表時地址 1000H 自動指向外部 ROM ✅
如果 EA=0,則 CPU 完全從外部 ROM 取指,這種情況下程序代碼也需燒入 27128。
MOVC 指令與外部 ROM 的關系
MOV DPTR, #1000H ; 指向外部 ROM 地址
MOV A, R0 ; 偏移量 = 計數值
MOVC A, @A+DPTR ; 讀取 (1000H + R0) 處的數據
執行 MOVC 時,CPU 自動:
P0/P2 輸出地址(1000H+R0)
ALE 鎖存地址
PSEN 輸出低脈沖 → 27128 的 /E 被選通
27128 輸出數據到 P0 → 讀入 ACC
題目的本質:你要把數碼管的段碼真值表(共陰極或共陽極的0~9段碼)燒錄到27128里,放在地址 1000H 起始的位置。單片機運行時,通過 MOVC 指令 從外部程序存儲器讀取段碼,送給數碼管顯示按鍵次數。
✅ 不是把段碼寫在程序里,而是存在外擴的27128里——這就是老師要考核的外部ROM擴展 + MOVC查表。
|