F351(3):Forth点灯,照亮AI单片机学习之路
据说开始学习单片机最好方法是先点亮一盏灯,星星点灯,照亮以后的路程。本文通过使用Forth语言来点亮STC8H开发板打狗棍上的LED灯这样一个最简单的例子,介绍F51汇编语言编程的基本步骤和方法。一、金湖X51 F51编译器的安装(1)金湖X51 Forth编译器是一个通用的编译器,通过安装不同“编译库”来实现对不同指令集计算机的支持,比如安装“X86编译库”就支持用8086指令集 Forth汇编语言编程,安装“F51编译库”就支持用8051指令集 Forth汇编语言编程。(2)在安装里前文中的金湖X51 Forth编译器后, VB6.0运行是需要的控件就已经安装到现在的Windows系统中了。安装“F51编译库”只需要将压缩包解压,直接双击其中的“金湖x51_V31.exe”可执行文件就可以启动“金湖X51 Forth编译器”了。下图是解压“附件1_金湖x51_V31.rar”后“0010_金湖x51_V31”子目录里的文件:
其中“data”子目录下的文件“金湖X51_F51编译器.LIB”就是Forth 8051编译库。(3)本文的范例程序见“附件2_星星点灯_STC8H.rar”,解压后的子目录下有两个程序:
其中“F351_Demo_01_8051.wdf”是本文的Forth范例程序,“Del_Hex.Bat”批处理文件,执行它可以删除HEX烧录文件。由于通常的编译器编译前不会删除原来的HEX烧录文件,初学者最容易入的坑之一就是不注意看编译信息,有时编译出错并没有生成新的HEX烧录文件,就错把旧的HEX烧录进去,结果以为程序没有修改成功,越改越乱。所以在进行重大的编程或者修改程序前记得将旧的HEX文件删除是一种好的编程习惯。
二、动手进行Forth语言编程前的顶层设计(4)Forth编程的方法是“自上而下的设计,自下而上的实现”。首先要设计项目要实现的功能目标,本范例的功能目标是在STC打狗棍开发板上用一个500毫秒的软件延时器控制连接在P0、P1和P2端口上的LED灯交通闪烁。(5)CODE空间设计。本范例的CODE分配设计如下:
段名称段地址范围段的内容
中断矢量段0000H - 03FFH预留中断矢量空间
子程序段0400H - 07FFH主程序要用到的各种子程序
系统引导段0800H ----设置单片机的运行环境
主程序段---- 0FFFH用户主程序
1)由于范例程序简单,故设计整个CODE空间大小为1000H(4KB)。通常CODE空间按照每个粒度为4KB来分配,比如AI8052U的可执行RAM就是4KB大小。2)对于8051/80251内核,从地址0003H开始的是中断矢量区,每个中断矢量占8个字节。对于STC单片机,通常留1KB(0400H)大小的矢量空间,可以支持127个中断矢量(0~126号中断),可以满足STC单片机未来几年的发展了。3)就像盖房子要先打基础一样,在中断矢量保留区后面通常用于存放各种主程序用到的子程序。对于Forth系统,通常按照1KB(一个Block)来分配存储空间,故本范例也分配了1KB(0400H - 07FFH)大小。4)任何计算机和单片机的程序在进入用户程序之前都有对CPU进行设置,然后才会进入用户主程序(比如C语言的main()函数)。因此系统引导(BOOT)程序从0800H开始,长短根据具体需要而定。5)用户主函数紧跟在引导程序后面,CPU执行完BOOT程序后就可以继续进入主函数开始运行了。(6)DATA/IDATA空间设计。对于8051单片机,一般DATA/IDATA的空间分配设计如下:
段名称段地址范围段的内容
CPU寄存器段00H - 1FH这32个字节是保留给8051寄存器BANK用的
BIT变量区20H - 2FH这16个字节是留给位变量用的,对应的位变量地址为00H~7FH
DATA变量区30H - 7FHDATA空间指用MOV指令可以直接寻找的空间,由于80H - FFH的DATA空间被指定做SFR空间了,所以DATA变量区到7FH为止
SFR区(DATA空间)80H - FFH8051单片机规定的SFR区
系统堆栈段(IDATA空间)80H - FFH供系统堆栈(SP)使用
(7)由于范例程序简单,没有使用XDATA空间,不需要进行分配设计。
三、Forth 8051汇编语言范例程序解读(8)通常Forth 8051汇编语言程序分为4个部分,下面是第1个部分编译器的设置和SFR定义:
(9)第9行程序是加载Forth 8051编译库,金湖X51编译器执行了这一行程序后,就变成了一个“8051汇编语言编译器”了,就可以将下面程序中的Forth 8051指令编译为8051指令集的二进制机器码了。(10)本范例是为STC8H和STC8051U系列单片机写的,而“金湖X51_F51编译器”只支持标准的8051单片机,因此还需要对STC8H特有的端口模式寄存器进行定义。上面第24行的“Hex”Forth字指定下面程序的数字按十六进制解释。(11)第27行到第32行是端口模式SFR定义,以第27行为例:1)“DOPR”是关键字,表示这时一个“目的操作数”的定义。2)SFR的名称是“P0M1,”,注意逗号和前面的字母是连在一起的。在8051指令集中,目的操作数是左操作数,在8051汇编语言中其后面跟着个逗号。3)最前面的数字93是十六进制的地址,关键字“DIRECT”表示这是一个位于DATA空间的可直接寻址地址(SFR)。4)第38行程序是从地址0000H开始将编译器内部目标机的4KB的CODE空间预先都填满“00”数据(NOP指令)。5)第41行是在Forth中定义了一个“常数”,常数名称为“Boot_Begin”,常数值是BOOT区域的开始地址。
(12)下面是范例程序的第2个部分,复位和子程序部分:
1)与一般的编译器不同,金水X51编译器是在“用户程序的控制下”进行编译工作的。比如第45行程序,就是要求编译器将代码编译指针-程序计数器(PC)的值设置为“0000H”,这样编译器就将下面的汇编语言指令编译成的机器码从地址0000H开始存放。2)第48行是长跳转指令“LJMP”。按规范,CODE空间的0000H开始的3个字节是一条长跳转指令“LJMPXXXX”,其中XXXX是系统的BOOT地址。这行程序相当于8051汇编语言“LJMP0800H”。3)第54行定义了一个标号“Delay_MS()”,这时软件延时函数的开始地址。在Forth语言中,对定义标号和变量名的标识符的组成并没有什么特别的限制,只要组成名字的字符它们连在一起就行了。这里在名称末尾加了一对括号,是想望而知义,表明这是一个函数的名称。4)第55行程序通常在每一个函数开头都有,它由3个Forth字组成:“Hex”让编译器把后面的数字作为十六进制数解释,“LBL_CLR” 让编译器将“局部标号”清零,“OP-RESET” 让编译器将“操作数”复位。5)Forth 汇编语言中预先定义了10个局部标号“0$”到“9$”,上面程序中的第62、66、68和78行就是局部标号的定义,第68、71、74和75就是对局部标号的引用。有了固定的局部标号,就可以避免通常8051汇编语言中在需要费脑筋定义多个不同的标号,特别适合像“SJMP”、“JZ”和“JNZ”这样的短跳转指令。6)第54行到第79行程序用3重循环完整实现了500毫秒的延时。
(13)下面是范例程序的第3和第4个部分,BOOT、主程序部分以及烧录部分:
其中第85行程序将编译器代码编译指针-程序计数器(PC)的值设置为“0800H”,这样编译器就将下面的BOOT程序从地址0800H开始存放,配合前面复位地址0000H的跳转指令,单片机的Forth程序从这里开始执行。(14)第89行到第91行是系统引导程序,这里只进行了3个最重要的设置。虽然第89和90行是STC单片机加电时的缺席状态,但是单片机系统运行异常也可能导致系统复位,这两行设置程序仍然是必须的。(15)第94到第99行程序是将P0、P1和P2设置为准双向口模式,第102行到第113行是LED灯闪烁的主循环Forth程序。(16)纵观整个主程序部分,对比C语言的LED灯闪烁程序,每行程序对应一个类似“P0=0x55;”的语句,对比8051汇编语言的的LED灯闪烁程序,它们之间一一对应,只是8051汇编语言的“操作符在前面”,比如“MOVP0, # 55H”,而Forth汇编语言的“操作符在后面”,比如“P0, 55 MOV#”。
四、生成HEX烧录文件和退出编译(17)与一般的编译器不同,金湖X51编译器是在Forth语言程序的控制下进行的。第116行程序是让编译器生成HEX烧录文件。其中“OutMap_Hex”是一个编译器命令,其命令格式为:<烧录长度>OutMap_Hex <烧录文件名>这个命令从地址0000H开始,将指定长度的代码转换为HEX的烧录格式文件。(18)第119行程序退出对本文件的编译。
下面是本文范例在STC8H单片机是运行的效果:
页:
[1]