首部曲

壹、8051 源起

1980年,8051微控制器由美國Intel公司設計製造並上市。架構在8048的設計基礎上,並改進其許多缺點,而成就的一顆8位元微控制器。8051除了具備了基本的運算功能之外,8051還具有timer,uart,gpio,counter,external int等功能,不一定要搭配週邊晶片即可工作,因此8051又稱作單晶片(single chip)。


8051外觀圖 DIP40
8051接腳圖

8051和8086都是40pin的晶片。8051是一顆八位元的微控制器,而8086是一顆八位元的微處理器。兩者的主要差異在於8051擁有一些特殊功能介面,而8086只是一個微處理器。如果要8086擁有gpio功能,8086就必須要外掛一顆8255的晶片。如果要8086擁有uart功能,8086就必須要接上pc16550d晶片。如果要8086擁有接受外部各中斷的要求,8086就必須要外接8259晶片。如果8086擁有計時計數器功能,8086就必須要外接一顆8254晶片。而這一切在標準8051中都是內建的功能,並不需要外接。當然如果想要擴充特別的介面的話,8051還是要外接晶片以達到系統的需求。


從8051外觀圖,我們可以看到8051有4組gpio port,每一組各有8支腳,分為P0,P1,P2,P3。

P0可當一般gpio使用,或是使用外部記憶體時的address[7~0],data[7~0]。
P1可當一般gpio使用,P0.0可以設定為計時器2的外部信號輸入腳位。
P2可當一般gpio使用,或是使用外部記憶體時的address[15~8]。
P3可當一般gpio使用,也歸劃為特殊功能之輸出入腳位,如串列埠、計數器、外部中斷等特殊功能。

其他腳位的功能如下所述。

VCC晶片電壓源輸入腳位,分5V和3.3V兩種。
GND晶片電壓源接地腳位。
XTAL1、XTAL2石英震盪時鐘訊號輸入腳位
/EA此腳位接5v致能8051內部程式記憶體,此腳位接地致能8051外部程式記憶體。
ALE此腳位為8051外部記憶體讀寫時之位址值拴鎖訊號,用於將P0輸出之Address[7~0]栓所在74373上。
PSEN外部程式記憶體的讀取訊號。

基本上,P0、P1的功能已經被定為外部記憶體的存取介面。P3上除了特殊功能外,P3.6、P3.7被規劃為外部記憶體的讀寫信號/WR、/RD,然後就用完了。P1上,除了P1.0被規劃為計數器2的輸入外,其他腳位尚未被規劃為特殊功能腳位。目前有許多廠商的8051,會把P1.1~P1.6規劃為特殊功能。這類的8051在市面上很多,例如myson cs8955 就多了 I2C slave、I2C master、 AD convertor等特殊功能,把P1.1~P1.6通通用完,讓8051的功能更加強大。許多特殊的設計讓8051的應用範圍更加廣泛,也讓8051的應用推陳出新。


貳 、8051 內部構造

從8051接腳圖,我們可以知道8051功能的概況。如果要正確發揮8051的功能,就必須要了解整個8051的內部結構,進而撰寫一套量身訂做的程式碼。8051的內部架構如圖所示,有核心、記憶體、各功能介面。

8051系統方塊圖
8051 core:

負責指令解碼與指令執行。
8051的指令分為算術運算指令、邏輯運算指令、資料搬移指令、程式跳躍指令。

System block:

這個區塊中包含有PSW,PCON,SP,DHP,DPL,ACC,B等特殊功能暫存器。

Interrupt block:

這個區塊中包含有IE特殊功能暫存器。

Timer/Counter block:

這個區塊中包含有TCON,TMOD,TCON2,TL0,TH0,TL1,TH1,TL2,TH2等特殊功能暫存器。

Serial port block:

這個區塊中包含有SCON,SBUF等特殊功能暫存器。

General purpose input output block:

這個區塊中包含有P0,P1,P2,P3等特殊功能暫存器。

Internal ram:

8051有128 bytes 的sram,8052有256 bytes的sram

External ram:

8051的外部記憶體可以擴充到64k。通常安排前32k為sram,後32k為外部裝置地址使用。

Internal rom:

這個部份和各家廠牌的設計有關。8031裡面就沒有internal rom。有的廠牌晶片會配有不同的internal rom容量。例如,4k,8k,16k,32,64k等容量。

External rom:

External rom最大可接64k。華邦的W27C512為64k容量的ROM晶片。


參、8051內部記憶體

了解8051的內部記憶體配置是一件重要的事。8051之所以稱作單晶片,也是因為有夠多的內部記憶體,使它能夠獨立執行任務,這點和8086這類cpu的晶片是很不一樣的。8051內部記憶體規劃了128 bytes sram,8052內部記憶體規劃了256 bytes sram。8052是因應8051資源太少的問題而設計出來的晶片。在硬體上,8052比8051多了128 bytes sram和計時器2。目前大部分都是使用8052的晶片,只是稱呼上,8051比8052更加普遍就是了。其實二者近似雙胞胎,差異有限。了解8051的內部記憶體配置,是一件重要的事。因為資源有限的情況下,對記憶體中的每一個位元的使用都要斤斤計較,不該隨意浪費。這也是微處理器的程式設計和高階的電腦語言程式設計之間的主要差異之一。
8051外部資料匯流排的定址可到64k的位址空間,內部資料匯流排只能定址到256的位址空間。所以內部記憶體的定址無法超過256,這也限制了8051的internal sram的設計,並導致8052的間接定址記憶體空間的出現。


8051(2)記憶體配置圖
8051內部記憶體

從上圖,我們可以發現記憶體分為直接存取和間接存取兩個區域。直接存取區域的記憶體是8051設計的原型,間接存取區域是8052獨有的記憶體區域。圖中有幾個指令範例,指出不同的記憶體區域必須用不同的指令存取。

setb 20h.0 20h~2fh之間的記憶體是可位元定址空間,共16 bytes,也等於是128 bits。可以使用setb、clr兩個指令將其設定為1或清除為0。
mov acc,30h 00h~7fh之間的記憶體是直接位元定址區域,涵概了可位元定址空間共128 bytes。可以使用mov指令讀取或設定記憶體位址中的值。
mov acc,80h

80h~ffh之間的記憶體是特殊功能暫存器的區域。這個區域的可定址空間是128 bytes,而真正有意義的位址並沒有那個多個,大部分的位址都是沒有意義的位址。可以使用mov指令讀取或設定記憶體位址中的值。
特別一題的是,此區域中的80h、88h、90h、98h...、f0h等位址是可被位元讀取並設定的。所以8051中,可位元存取的位元總數是256 bits,32bytes。

mov r0,80h
mov acc,@r0

間接記憶體區域的可定址空間是128 bytes。這個記憶體區域的存取必須使用間接的方式存取。由r0預先存放欲讀取之記憶體位置的值,再以mov acc,@r0 和mov @r0,acc 指令讀取寫入該位址。

上面所使用的範例是為了說明可位元定址空間、直接位元組定址空間和間接位元組定址空間之差異及存取方式。實際上,8051有提供更多的指令集可用以存取這三個記憶體空間。這些指令會在後面的指令集中再度說明。

以下,再針對內部記憶體空間做更詳細的敘述。

暫存器庫
register bank

00h~1fh共32個位元組。這個區域的sram可規劃為指令輔助用暫存器。8051指令中有遇到r0、r1這樣的暫存器,而r0、r1就是從暫存器庫中取用的。8051重製後,會內定00h~07h為8051御用暫存器庫。使用者可以透過PSW特殊暫存器設定目前要用的暫存器庫是哪一個。

PSW[4:3]=00b設定為暫存器庫0r0 is at 00h
PSW[4:3]=01b設定為暫存器庫1r0 is at 08h
PSW[4:3]=10b設定為暫存器庫2r0 is at 10h
PSW[4:3]=11b設定為暫存器庫3r0 is at 18h

可位元定址記憶體空間
bit addressable memory space
這個空間的範圍是從20h到2fh。
存取方式︰
直接位元組定址存取方式...mov 20h,#0
間接位元組定址存取方式...mov r0,#20h...mov acc,@r0
直接位元定址存取方式...setb 20h.0...clr 20h.0
直接位元組記憶體定址空間
direct memory access space
這個空間的範圍是從00h到7fh。
用途為存放程式變數及堆疊使用。
存取方式︰
直接位元組定址存取方式...mov 00h,#0
間接位元組定址存取方式...mov r0,#8...mov acc,@r0
特殊暫存器空間
special function register

這個位址的空間是從80h到ffh。但是只有26的位址是有意義的,其餘位保留區域。
存取方式︰
直接位元組定址存取方式...mov r0,80h
位址為8的倍數者,可用位元定址存取方式...setb 80h.0

系統控制群PSW,PCON,SP,DPL,DPH,ACC,B等特殊功能暫存器。
中斷控制群IE,IP等特殊功能暫存器。
計時計數器控制群TMOD,TCON,TCON2,TH0,TL0,TH1,TL1,TH2,TL2,RCAP2H,RCAP2L等特殊功能暫存器。
串列埠控制群SCON,SBUF等特殊功能暫存器。
通用輸出入埠控制群P0,P1,P2,P3等特殊功能暫存器。

間接位元組記憶體定址空間
indirect memory access space
這個定址空間是屬於8052,範圍從80h到ffh。這個區域的定址空間和特殊暫存器的定址空間完全重疊,卻不互相影響,因為存取方式的不同把他們完全隔開了。
存取方式︰
間接位元組定此存取方式...mov r0,#80h...mov acc,@r0

肆、8051特殊功能暫存器

特殊功能暫存器(special function register,簡稱sfr)負責8051內部各硬體功能的管理與設定。開機上電後,這些特殊功能暫存器會有一個初始值。之後,程式執行時,必須為所要執行的功能的特殊功能暫存器做設定的動作。
8051(2)的特殊功能暫存器定址如下表所示︰

8051內部記憶體

其中TCON2、RCAP2L、RCAP2H、TH2、TL2屬於8052,8051中沒有這5個暫存器。

8051的特殊暫存器分為五個群組︰

  • 一、系統控制群(system control group)
  • 二、中斷控制群(interrupt control group)
  • 三、計時計數器控制群(timer/counter control group)
  • 四、串列埠控制群(serial port control group)
  • 五、通用輸出輸入埠控制群(general purpose control group)

一、系統控制群

包含PSW、PCON、SP、DPL、DPH、ACC、B等特殊暫存器。

SP

位址0x81,堆疊指標暫存器(stack pointer),指向目前堆疊的頂點。
8051的堆疊由下往上長:
堆入動作
PC=PC+1
*PC=DATA
堆出動作
DATA=*PC
PC=PC-1

與SP有關的指令有push、pop、acall、lcall、ret、reti。

PSW

0xD0,程式狀態暫存器。

76543210
CYACF0RS1RS0OVRSVP
CY進位旗號
AC輔助進位旗號
F0使用者自行定義位元,可當一個位元變數使用。
RS1、RS000暫存器庫一、01暫存器庫二、10暫存器庫3、11暫存器庫4。
OV溢位旗號
RSV保留旗號
PACC特殊暫存器的同位元旗號,ACC中"1"的個數為奇數則P=1。反之,則為0。
PCON

0x87,電源控制暫存器。

76543210
SMODRSV2RSV1RSV0GF1GF0PWDNIDL
SMOD如果串列埠模式為1、2、3,而且使用計時器一為鮑率產生器時,SMOD=1將使鮑率變為2倍。
RSV2保留位元,未定義。
RSV2保留位元,未定義。
RSV2保留位元,未定義。
GF1一般用途位元,可當一個位元變數使用。
GF0一般用途位元,可當一個位元變數使用。
PWDN省電模式,必須使用reset訊號讓其回復到一般操作模式。
IDLIDL=1會使8051的clock停止,必須使用外部中斷或reset訊號使8051回復到一般操作模式。
ACC

0xe0,累積器暫存器(accumulator)。

B

0xf0,算術輔助運算暫存器(arithmetic auxiliary)。

DPH

0x83,資料指標暫存器高位元組,DPTR[15:8]。

DPL

0x82,資料指標暫存器低位元組,DPTR[7:0]。

二、中斷控制群

包含IE,IP等特殊暫存器。

IE

0xa8,中斷控制暫存器。

76543210
EARSVET2ESET1EX1ET0EX0
EAEA=1致能所有中斷
RSV保留位元,未定義。
ET2計時器2 中斷
ES串列埠中斷
ET1計時器1 中斷
EX1外部中斷1
ET0計時器0 中斷
EX0外部中斷0
IP

0xb8,中斷控制暫存器。

76543210
RSVRSVPT2PSPT1PX1PT0PX0
RSV保留位元,未定義。
RSV保留位元,未定義。
PT2計時器2 中斷優先權位元
PS串列埠中斷優先權位元
PT1計時器1 中斷優先權位元
PX1外部中斷1 優先權位元
PT0計時器0 中斷優先權位元
PX0外部中斷0優先權位元

三、計時計數控制群

包含TMOD,TCON,TCON2,TH0,TL0,TH1,TL1,TH2,TL2,RCAP2L,RCAP2H等特殊暫存器。

TMOD

0x89,計時計數器模式暫存器。

76543210
GATE1C1/T1M11M10GATE0C0/T0M01M00
GATE1

計時計數器1 致動選擇位元。
GATE1=1,由INT1外部訊號驅動計時計數器1。
GATE1=0,由TCON 的TR1位元驅動計時計數器1。

C1/T1計時計數器1 功能設定位元。
C1/T1=1,計時計數器1 為計數器功能。
C1/T1=0,計時計數器1 為計時器功能。
M11,M10 計時計數器1 操作模式設定位元。
[M11:M10]
模式
功能描述
00
0
13位元
01
1
16位元
10
2
8位元
11
3
停止計時計數器1 的功能
GATE0

計時計數器0 致動選擇位元。
GATE0=1,由INT0外部訊號驅動計時計數器0。
GATE0=0,由TCON 的TR0位元驅動計時計數器0。

C0/T0

計時計數器0 功能設定位元。
C0/T0=1,計時計數器0 為計數器功能。
C0/T0=0,計時計數器0 為計時器功能。

M01,M00 計時計數器0 操作模式設定位元。
[M01:M00]
模式
功能描述
00
0
13位元
01
1
16位元
10
2
8位元,自動重新載入。
11
3

TL0為8位元計時計數器。
TH0為8位元計時器,以TCON的TR1驅動。
TL1,TH1可作為鮑率產生器。

TCON

0x88,計時計數器控制暫存器。

76543210
TF1TR1TF0TR0IE1IT1IE0IT0
T2CON

0xc8,計時器2控制暫存器。

76543210
TF2EXF2RCLKTCLKEXEN2TR2C/T2CR/RL2
TH0

0x8a,計時器0 計時值高位元組。

TL0

0x8b,計時器0 計時值低位元組。

TH1

0x8c,計時器1 計時值高位元組。

TL1

0x8d,計時器1 計時值低位元組。

TH2

0xcc,計時器2 計時值高位元組。

TL2

0xcd,計時器2 計時值低位元組。

RCAP2H 0xca,計時器2 重載捕獲暫存器。
RCAP2L 0xcb,計時器2 重載捕獲暫存器。

四、串列埠控制群

包含SCON,SBUF等特殊暫存器。

SCON

0x98,串列埠控制暫存器。

76543210
SM0SM1SM2RENTB8RB8TIRI
SBUF

0x99,串列埠控制暫存器。

76543210
TF2EXF2RCLKTCLKEXEN2TR2C/T2CR/RL2

五、通用輸出輸入控制群

包含P0,P1,P2,P3等特殊暫存器。

P0 0x80,通用輸出輸入埠0。
P1 0x90,通用輸出輸入埠1。
P2 0xa0,通用輸出輸入埠2。
P3 0xb0,通用輸出輸入埠3。

伍、8051 指令集

每顆微處理器都有一套為自己量身定做的指令集。這套指令集必須滿足各種動作的需求,讓程式語言的撰寫能夠順暢,甚至能夠加快效能。

8051的指令集的設計可分為四個集別:

  • 算術運算指令集
  • 資料搬移指令集
  • 邏輯運算指令集
  • 程式跳躍指令集

算術運算指令集mul、div、add、addc、subb、inc、dec
資料搬移指令集mov、movc、movx、swap、setb、clr、rr、rrc、rl、rlc、push、pop
邏輯運算指令集orl、anl、cpl、cjne、djnz、jb、jnb、jc、jnc、jz、jnz
程式跳躍指令集acall、lcall、ret、reti、sjmp、ajmp、ljmp

一、算術運算指令集

指令功能描述
mul mul ab
乘法運算指令
機械碼10100100
divdiv ab
除法
機械碼10000100
addadd acc,rn
加法一
機械碼00101b2b1b0
addadd acc,direct
加法二
機械碼00100101
addadd acc,#data
加法三
機械碼00100100
addadd acc,@rn
加法四
機械碼00100100
addcaddc acc,rn
含進位加法一
機械碼00111b2b1b0
addcaddc acc,direct
含進位加法二
機械碼00110101
機械碼a7a6a5a4a3a2a1a0
addcaddc acc,@rn
含進位加法三
機械碼0011011b0
addcaddc acc,#data
含進位加法四
機械碼00110100
機械碼d7d6d5d4d3d2d1d0
subbsubb acc,rn
減法一
機械碼10011b2b1b0
subbsubb acc,direct
減法二
機械碼10010101
機械碼a7a6a5a4a3a2a1a0
subbsubb acc,@rn
減法三
機械碼1001011b0
subbsubb acc,#data
減法四
機械碼10010100
機械碼d7d6d5d4d3d2d1d0
incinc acc
遞增一
機械碼00000100
incinc rn
遞增二
機械碼00001b2b1b0
incinc direct
遞增三
機械碼00000101
機械碼a7a6a5a4a3a2a1a0
incinc @ri
遞增四
機械碼0000011b0
incinc dptr
遞增五
機械碼10100011
decdec acc
遞減一
機械碼00010100
decdec rn
遞減二
機械碼00011b2b1b0
decdec direct
遞減三
機械碼00010101
機械碼a7a6a5a4a3a2a1a0
decdec @ri
遞減四
機械碼0001011b0
dada acc
十六進位轉BCD
機械碼11010100

二、資料搬移指令集

指令功能描述
movmov acc,rn
資料搬移指令一
機械碼11101b2b1b0
movmov acc,direct
資料搬移指令二
機械碼11100101
機械碼a7a6a5a4a3a2a1a0
movmov acc,@rn
資料搬移指令三
機械碼1110011b0
movmov acc,#data
資料搬移指令四
機械碼11100101
機械碼d7d6d5d4d3d2d1d0
movmov rn,acc
資料搬移指令五
機械碼11111b2b1b0
movcmovc a,@a+dptr
程式碼資料讀取指令一
機械碼10010011
movcmovc a,@a+pc
程式碼資料讀取指令二
機械碼10000011
movxmovx acc,@rn
外部記憶體讀取指令一
機械碼1110001b0
movxmovx acc,@dptr
外部記憶體讀取指令二
機械碼11100000
movxmovx @rn,acc
外部記憶體寫入指令一
機械碼1111001b0
movxmovx @dptr,acc
外部記憶體寫入指令二
機械碼11110000
setbsetb c
設定進位位元為1
機械碼11010011
setbsetb bitaddress
設定直接位元為1
機械碼11010010
機械碼a7a6a5a4a3a2a1a0
clrclr a
清除累積器為0
機械碼11110100
clrclr c
清除進位位元為0
機械碼11000011
clrclr bitaddress
清除直接位元為0
機械碼11000010
機械碼a7a6a5a4a3a2a1a0
rrrr acc
右移
機械碼00000011
rrcrrc acc
含進位右移
機械碼00010011
rlrl acc
左移
機械碼00100011
rlcrlc acc
含進位左移
機械碼00110011
pushpush address8
推入堆疊
機械碼11000000
機械碼a7a6a5a4a3a2a1a0
poppop address8
取出推疊
機械碼11010000
機械碼a7a6a5a4a3a2a1a0

三、邏輯運算指令集

指令功能描述
orlorl acc,rn
或邏輯指令一
機械碼01001b2b1b0
orlorl acc,address8
或邏輯指令二
機械碼01000101
機械碼a7a6a5a4a3a2a1a0
orlorl acc,@rn
或邏輯指令三
機械碼0100011b0
orlorl acc,#data
或邏輯指令四
機械碼01000100
datad7d6d5d4d3d2d1d0
orlorl byte_address8,acc
或邏輯指令五
機械碼01000010
byte_address8a7a6a5a4a3a2a1a0
orlorl direct,#data
或邏輯指令六
機械碼01000011
byte_address8a7a6a5a4a3a2a1a0
data8d7d6d5d4d3d2d1d0
cplcpl acc
累積器反向邏輯運算指令
機械碼11110100
cplcpl c
位元反向邏輯運算指令
機械碼10110011
cplcpl bitaddress8
位元反向邏輯運算指令
機械碼10110010
bit_address8a7a6a5a4a3a2a1a0
djnzdjnz rn,relative_address8
遞減不為0則跳躍指令
機械碼11011b2b1b0
relative_address8a7a6a5a4a3a2a1a0
djnzdjnz byte_address8,relative_address8
遞減不為0則跳躍指令
機械碼11010101
byte_address8a7a6a5a4a3a2a1a0
relative_address8a7a6a5a4a3a2a1a0
jbjb bit_address8,relative_address8
位元為1 則跳躍指令
機械碼00100000
bit_address8a7a6a5a4a3a2a1a0
relative_address8a7a6a5a4a3a2a1a0
jnbjnb bit_address8,relative_address8
位元為0則跳躍指令
機械碼00110000
bit_address8a7a6a5a4a3a2a1a0
relative_address8a7a6a5a4a3a2a1a0
jcjc relative_address8
進位為1 跳躍指令
機械碼01000000
relative_address8a7a6a5a4a3a2a1a0
jncjnc relative_address8
進位為0 跳躍指令
機械碼01010000
relative_address8a7a6a5a4a3a2a1a0
jzjz relative_address8
累積器為0 跳躍指令
機械碼01100000
relative_address8a7a6a5a4a3a2a1a0
jnzjnz relative_address8
累積器為1 跳躍指令
機械碼01110000
relative_address8a7a6a5a4a3a2a1a0

四、程式跳躍指令集

指令功能描述
acallacall relative_address11
絕對呼叫指令
機械碼a10a9a810001
relative_address11a7a6a5a4a3a2a1a0
lcalllcall address16
長程呼叫指令
機械碼00010010
code_address16a15a14a13a12a11a10a9a8
code_address16a7a6a5a4a3a2a1a0
retret
呼叫返回指令
機械碼00100010
retireti
中斷呼叫返回指令
機械碼00110010
sjmpsjmp relative_address8
短成跳躍指令
機械碼10000000
relative_address8a7a6a5a4a3a2a1a0
ajmpajmp relative_address11
絕對跳躍指令
機械碼a10a9a800001
relative_address11a7a6a5a4a3a2a1a0
ljmpljmp code_address16
長程跳躍指令
機械碼00000010
code_address16a15a14a13a12a11a10a9a8
code_address16a7a6a5a4a3a2a1a0