为了赞扬我最近出版的MCS-48程序员盾牌,我认为基于其中之一构建一些有用的东西会很有趣。MCS-48完成于1976年,在撰写本文时已经44岁了,这让我们有机会回到嵌入式开发的遥远过去,剥离了我们通常漂浮在Arduino和Raspberry Pi等产品之上的多层硬件和软件。
随着基于第一个微控制器-TMS1000徘徊在零之上的微弱优势来建立自己的小玩意儿的前景,MCS-48给我们提供了一个像样的安慰。
与几乎同样古老的MCS-51拒绝死亡不同,工业界过去决定离开MCS-48。从细节上看,MCS-48项目的努力似乎进入了MCS-51,然而两者既没有指令集,也没有管脚兼容性。因此,MCS-48没有任何现代后代或工具。在如此有限的指令集和没有数据堆栈的情况下,为其编写3GL编译器将是具有挑战性的,生成的代码将非常浪费其有限的资源。
纯汇编语言微控制器的市场在20世纪90年代收缩,到那时MCS-51已经取而代之,提供了能够支持高级语言编译器的完整指令集。我的一位朋友告诉我,尽管朝着C开发的方向发展,但直到20世纪90年代,一些工程师仍在大量涌入印在绿色条上的MCS-48/51组装清单。
对于一个只有GPIO、一个定时器、1K程序空间和64字节数据内存(32字节取决于您的计数方式)的微控制器来说,要想用它来做一些有用的事情可能有点夸张。这个双温度传感器不需要更多的东西,我几乎可以忍受用它的汇编语言编程的想法,因为没有其他选择。
正如我前面所暗示的,没有针对MCS-48的C编译器,这使得为这些设备编写软件具有挑战性。维基百科上说有一个PL/M编译器可以用来处理这些问题,但是我找不到它,也没有任何其他的提及。雪上加霜的是,这里也没有硬件的乘法、除法或减法。甚至没有比较两个数字的说明。所有这些都必须用原始的逻辑指令拼凑在一起。在我努力完成实现的过程中,我不断告诉自己事情会变得更容易。但事实并非如此。
即使配备了适当的逻辑分析仪,使用现代的PC、编辑器和非常容易使用的程序员,编写这方面的软件仍然是非常困难的。我花了将近三周的时间才完成它,而我7年前完成的这个项目的8051版本(C/Keil实现)在不到两天的时间里就完成了。
在这个项目中,我使用了一个由现代爱好者构建的汇编器-ASM48,这有点作弊。
早在1977年,当它们第一次可以买到的时候,还没有PC或DOS来编写软件。使用的是一台专门建造的机器,英特尔MDS-II(微处理器开发平台),其汇编器也来自英特尔。我找到的一些扫描手册显示,汇编程序输出以下版本字符串:
这可能是它的复印件。MDS-II运行一种名为ISIS-II的特殊操作系统。有人怀疑(尽管未证实)IBM也在其中一台机器上开发了原始的PC BIOS(他们肯定不是在PC上开发的),这里有一条关于这一点的有趣线索,其中详细说明了恢复这些早期开发工具的挑战。
还有一个用于ISIS-II平台的模拟器。一次未来可能有趣的重访。
内部EPROM MCS-48不能在标准EPROM编程器中编程。他们需要一个专门设计的程序员。然而,硬件仍然是可以买到的,并不是特别便宜。我不辞辛劳地以Arduino盾牌的形式构建了自己的程序员。
除编程器外,还需要EPROM擦除器。我的是20世纪80年代的经典设计,然而,这些天在eBay上有大量廉价的中国产品出售。
现代微控制器上使用的典型调试技术(例如printf()或在线调试)是不可能的。仿真器几乎没有什么实际用途,因为这些设备几乎总是需要就地调试。
假设您构建的产品不会因为停止处理器而造成物理损坏,那么DataBook推荐的“严谨”方法是使用带有单步电路的无ROM版本,结合SS(单步)引脚,通过连接到外部EPROM地址/数据信号的外部逻辑分析仪来逐步检查您的代码。
这样,您就可以看到程序计数器达到了什么程度,但是您不知道CPU内部的任何寄存器都包含什么。如果您需要看到其中的一个,您必须将其复制到累加器中,然后将其写出到总线上,假设这样做不会导致某种灾难,然后使用逻辑分析器捕获它。
当时装备精良的工程师可能已经拥有了上述其中之一。ICE-48模拟器取代了40针MCS-48进行连接,允许工程师查看内部寄存器的内容、设置断点和单步执行。与我的经历相比,这是相当奢侈的。
我发现调试MCS-48最简单的方法就是根本不调试它。相反,我在脑海里一遍又一遍地重复着这些指示,并试图在第一次就把它做对。这比任何其他方法耗费的时间要少得多。
在这个项目开始的时候,我在eBay上买了一个MCS-48数据阅读器(我只是想要一个)。我收到的是1976年的原版,里面有错误。该死的易趣垃圾又来了。
上面是所述的MCS-48引脚,这是不正确的。RD/WR针脚显示已交换。我对原理图的第一次修订包括了这个错误,因为我是从这本书开始工作的。当我第一次尝试在我的逻辑分析器上调试它时,这导致了很多令人费解的事情。
在现代微控制器上,GPIO很容易实现。我们的寄存器可以使一对P/nch FET用作输出,通常能够吸收和产生相当可观的电流,通常足以为LED和小型继电器供电。
在MCS-48上,我们使用的是准双向GPIO。数据薄展示了很多这些东西是多么的奇妙和创新,但从使用过现代的“真正的”GPIO的角度来看-它们是一个令人头疼的问题。
本质上,这些同时是输入和输出。输入部分只是一个总是对外部引脚进行采样的缓冲器,输出部分是一个将引脚拉低的N-ch FET,内部50K上拉提供逻辑“高”。还有一个阻抗为5K的微小P-ch FET,它在一个时钟周期内被断言,以提供良好的上升时间,但在此之后,我们完全挂起了50K上拉,这将不允许我们在没有缓冲的情况下获得足够的电流来做任何有用的事情。
为什么不让5K上拉一直保持在赛道中呢?因为在输出保持较低的情况下,该设计将被判持续浪费大量电力。您可以设置一个强大的上拉来提供更大的电流源,但是您遇到了另一个问题,因为N-ch场效应管的阻抗为300V,因此如果上拉为1K,您最终会得到1.15V的“低”电压。不太理想。
这些管脚的特性非常适合驱动FET。5K的上拉“脉冲”意味着闸门将快速充电,而50K将使其保持充电。Ω的低端也运行良好。在当今时代,从MCS-48(和MCS-51)上的GPIO获得大驱动电流只需将所需极性的MOSFET直接拍打到引脚上(您可以添加栅极电阻来减少振铃,但不太可能需要)。
这在当时是不可能做到的(晶体管和经过仔细计算的基极电阻会被使用),但这正是我在设计中所做的。正如数据薄中反复说明的那样,这些引脚能够毫无问题地驱动其他TTL逻辑的输入,这在我的设计中也有发现。
与只有掩蔽ROM的TMS1000不同,MCS-48有不同的ROM选项和大小。
我经常看到它说8048/8049的变种是“动态口令”(一次性可编程)。这(某种程度上)是真的。它们实际上是掩模ROM编程的。
这些设备的屏蔽ROM代码由客户以穿孔卡片的形式提供给英特尔。数据薄解释了如何格式化这些内容。
我制作了一个带有EPROM插座的小PCB,用于运行无ROM设备。包括去反弹复位电路,以及用于外部总线的具有锁存的低位地址线的标头。这主要是为了帮助我在开发期间对软件进行调试(我确实使用了逻辑分析器进行一些调试)。本页末尾包含了它的Gerber。
不厌其烦地只遗漏了MCS-48的这一引人注目的变种是不公平的。第一个通用外设接口是8041,随后是8042(以及8741和8742版本的EPROM)。
UPI与常规型号MCS-48的不同之处在于,其总线接口是从机,而8×48/8×49则是主机。它的指令集也与普通的MCS-48略有不同。它们旨在创建连接到另一种微处理器的总线上的智能外设。
UPI最著名的应用是在IBMAT中,使用8042作为其键盘控制器(它还做了一些其他奇怪的事情),最初是用IBM“1503033”ROM映像编程的。在接下来的几年里,它的代码被扩展到支持PS/2小鼠。8042是最近才从PC体系结构中退役的。现代个人电脑仍在模仿它,以允许传统操作系统使用USB键盘。
UPI 8042是MCS-48系列中唯一实现代码安全(防止读取编程部件的代码)的成员。正因为如此,基于8042的键盘控制器的代码很难获得。
我想做个实验,看看我能不能让UPI-41除了在防静电泡沫上看起来漂亮之外,还能做些别的事情,这会很有趣。因为我的温度传感器的主操作模式不需要总线,所以它可以在8741或8742上运行,只要有主软件映像就行了。但那太无聊了。
所以我不厌其烦地为它写了另一个小程序,接受来自“主”温度传感器的数据。
在上面的演示中,主板(在这种特殊情况下配有8039)连接了四个DS18B20温度传感器,并将传感器3和4的读数写入第二块板,第二块板只是主板总线上的一个外围设备,上面有两组额外的显示器。
好的,所以不是特别有用,但确实演示了这个概念。此操作的代码链接到本页末尾。UPI的概念在现代微控制器上是重复的,例如,在PIC上它被实现为PSP(并行从属端口)。
下面,我已经提供了构建本文中显示的板所需的所有内容。