文章一开始我首先要说明的一点就是bank功能与扩展关键字并没有什么必然的关系,硬要说有关系那就是都只在51内核单片机的ROM或者RAM空间超过64KB的时候才会使用。
放到一篇文章里面是因为我站在现在(2025/12/27)眼光来看,觉得在当前进行嵌入式开发这些东西都没有使用的意义,所以把他们放到一块进行讲解作为选读内容。
51单片机的PC和指针寄存器都是双8位拼接成的16位寄存器这个我想都知道,在内部RAM不够使用的时候可以进行外部扩展,如下图扩展到最大64KB的XRAM空间,如果遇到了64KB空间还是不够怎么办。

其实这并不是什么难以理解的技术,上图使用了16根地址线扩展出64KB的RAM空间,不够就继续加地址线就好了,而且每加一根可用空间就会变成原来的两倍。不过内核最多16位寻址想要应对多出的地址线也就需要进行额外的操作,因此诞生了bank以及bank切换技术。


上面是一个经典的8051扩展出256KB大小ROM空间的简略原理图,其实就是多加了两根地址线。code bank支持多个bank中程序运行,当程序在当前bank中调用函数(同bnak调用)时,它会直接跳转到该函数的物理地址。要调用不同bank中的函数(跨bnak调用),程序必须首先切换到目标bank,然后跳转到该函数的地址。
bank切换的问题是由链接器负责的,显然你也需要对链接器和启动文件进行一些配置,首先需要把L51_BANK.A51文件引入N_BANKS就是bank的数量,B_MODE就是切换bank的方式有几种可选,我这里填写4表示自己提供切换方式,下面的SWITCHX就是操控P3.3,P1.5引脚变化的代码这个并不难理解,其他方式这里不一一列举。
# L51_BANK.A51
?N_BANKS EQU 4 ; Four banks are required.
?B_MODE EQU 4 ; user-provided bank switch code.
P1 DATA 90H ; I/O Port Addresses
P3 DATA 0B0H ; "
SWITCH0 MACRO ; Switch to Memory Bank #0
CLR P3.3 ; Clear Port 3 Bit 3
CLR P1.5 ; Clear Port 1 Bit 5
ENDM
SWITCH1 MACRO ; Switch to Memory Bank #1
SETB P3.3 ; Set Port 3 Bit 3
CLR P1.5 ; Clear Port 1 Bit 5
ENDM
SWITCH2 MACRO ; Switch to Memory Bank #2
CLR P3.3 ; Clear Port 3 Bit 3
SETB P1.5 ; Set Port 1 Bit 5
ENDM
SWITCH3 MACRO ; Switch to Memory Bank #3
SETB P3.3 ; Set Port 3 Bit 3
SETB P1.5 ; Set Port 1 Bit 5
ENDMSTARTUP.A51启动代码里面也需要添加一些内容确保复位之后CPU处于一个确定的状态。
MOV SP,#?STACK-1
P1 DATA 90H ; I/O Port Addresses
P3 DATA 0B0H
EXTRN DATA (?B_CURRENTBANK)
MOV ?B_CURRENTBANK,#0 ; Select code bank 0
CLR P3.3 ; Clear Port 3 Bit 3
CLR P1.5 ; Clear Port 1 Bit 5
JMP ?C_START看上面的代码你就可以知道bnak的切换实际上算是一个手动过程,开发者自己利用链接器切换了bank欺骗了内核让他以为还是在同一个物理空间进行访问执行代码,这好像是一个自动的过程,但对于内核来说它是完全不知道自己在哪一个bank里的。
如果在bank1里正常执行程序的时候有一个中断来了,中断函数在bank0里面怎么办,这就带来一个问题,一些公共使用的程序必须在一个公共区域也就是每个bank放一份(先不要说浪费空间每个bank一份不代表物理上需要存很多份,后面会说)。
任何必须在不切换代码库的情况下始终可用的代码都必须放在公共区域中,包括但不限于复位和中断向量,中断服务程序,字符串常量,bank切换程序,bnak间跳转表。剩下的程序可以放在bank区域根据需要进行切换bank以执行程序。

在配置界面进行配置的时候banks数量一定要和L51_BANK.A51以及实际的硬件对的上,这个过程全部由开发者操作,出错链接器也不能检查出来。后面的bank Area就是实际上可以切换的区域,但这个不是必须配置的,如果不配置链接器会自动调整公共区域的大小将始终可用的代码在每一个bank公共区域放一份副本,确保任何bank可用。
你会发现外部扩展ROM空间是把扩展RAM空间的端口给占用了,而且还有一个问题是公共代码需要再每个bank存放一份实际上大大的浪费了物理空间,这个其实完全可以通过物理连接解决这些问题。

你看这个256KB按理说4个BANK两个bank选择线就可以但这里使用3个,并利用特殊的逻辑门连接可以保证不论当前选中哪个Bank,访问0x0000~0x7FFF时,A16/A17都为0(由逻辑门电路保证)。这样,所有Bank的Common区地址线都指向同一块物理存储区域。

好处是公共区域代码实际上只在物理上存储一份,三个bank线输出0选择bank0实际上就是公共区域,坏处是公共区域的大小就不是那么自由了,取决于物理连线,但总的来说利大于弊。
RAM并不排斥和ROM扩展使用同一个端口,因为经典的8051有蓝色框中PSEN/、RD/、WR/这几个专门的引脚用于控制外部的ROM和RAM,不会同时占用端口。
说到这里其实你就可以意识到现在能买到的51单片机实际上在技术上已经不具备使用bank技术的可能性,通常是把原本的外部扩展RAM和ROM直接封装进芯片上(都不会大于64KB),把P0、P2端口释放出来实现各种控制功能,几个专用的引脚也直接被砍掉了。
BL51链接器最多支持扩展32个bank,LX51链接器进一步增加到64个bank,并且LX51作为扩展8051添加了ecode、hdata,hconst等关键字。
![]() | ![]() |
|---|
在一些8051的变体中DPTR (指针)寄存器被扩展为 24 位寄存器,可以访问空间(16MB)变大了也就有诞生了扩展关键字,ecode,hdata。不过通过 LX51 链接器你甚至可以在经典 8051 设备(16位DPTR)上使用 HCONST 和 HDATA 关键字。
也要补充说明的是,RAM的bank功能也只有使用LX51时才可以启用,也叫variable banking。同时需要给LX51一些指令说明扩展的RAM布局。
LX51 BANK1 {A.OBJ}, ..., BANK7{G.OBJ} ... BANKAREA (0x8000,0xFFFF)
CLASSES (XDATA (X:0-X:0x7FFF),
HDATA (X:0x18000-X:0x1FFFF,X:0x28000-X:0x2FFFF,
X:0x38000-X:0x3FFFF,X:0x48000-X:0x4FFFF,
X:0x58000-X:0x5FFFF,X:0x68000-X:0x6FFFF,
X:0x78000-X:0x7FFFF),
HCONST (C:0x18000-C:0x1FFFF,C:0x28000-C:0x2FFFF,
C:0x38000-C:0x3FFFF,C:0x48000-C:0x4FFFF,
C:0x58000-C:0x5FFFF,C:0x68000-C:0x6FFFF,
C:0x78000-C:0x7FFFF))我不否认一些8051内核的芯片内部的空间是超过了64KB了,但是这种8051的变体对于开发者来说不太可能存在需要向上面一样手动连线扩展的情况,芯片厂商已经在内部做好了一切。
从技术上说通过引脚连接外部存储必然不如内部存储访问迅速,芯片上也失去了几个专用的控制引脚,从经济上来说一个51芯片加上外部的存储芯片是要比同等容量的cortex-m内核芯片要贵的,也需要更多的电路板空间,在现在讲究集成的时代真的很不合适。
我的建议是如果ROM和RAM在64KB以下因为业务需要还可以接受51芯片,超过64KB应该尽早换用cortex-m内核芯片。所以我在文章中也只是简单说了一下bank怎么回事,并没有很具体,如果你真的有需要可以去ARM官网查看。


评论已关闭