单片机实验指导书

更新时间:2023-03-09 09:00:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验一 系统认识实验

一、实验目的

认识单片机基本系统的硬件设备,熟悉51仿真软件的使用,练习使用汇编语言的基本语句编制程序。 二、实验内容 1、硬件认识 2、软件认识 3、汇编语言练习 三、实验步骤 (一)、硬件认识:

在AEDK5196ET实验系统实验版上找到8051芯片,74LS373/273(锁存器),

数码管,8255,LED等硬件。

将AEDK5196ET实验系统设定为仿真51模式(即将K9的短路套插向51端,

K9在实验板右上角),并用与实验机配套的串行通讯电缆将9芯电缆的一端与实验机上的J9插座相连,另一端与PC机的串口相连(可参考附录一)。

开电源,AEDK5196ET机上将显示:AEDK.U51(51方式)

如为仿真96模式将显示:AEDK.U96(96方式) (二)、软件认识

根据所使用的硬件环境不同,实验室PC机上预装了AEDK仿真软件的DOS版

或WINDOWS版。学生可参考附录二,熟悉所用的软件环境。 (三)、汇编语言练习 具体内容:

1, BCD码转换

先将8051内部RAM的20H单元赋予一个8位二进制数(可随意设定),然后将

1

它转换成三位BCD码,将百位存放在FIRST单元(30H)中,十位和个位存放在SECOND(31H)中(高四位为十位)。 参考程序: FIRST

DATA

30H 31H

0A9H; 0100H;

等于BCD码169 开始

SECOND DATA RADOM DATA ORG START: MOV MOV

MOV DIV MOV MOV MOV DIV SWAP ORL MOV

20H,#RADOM;将RADOM的值存入20H单元中 A,20H; 取数 B,#64H; 除数为100 AB; 确定百位数 FIRST,A; 百位送FIRST A,B; 余数送A B,#0AH; 除数为10 AB; A;

确定十位数

十位数移至高四位

A,B; 并入个位数

SECOND,A;十位、个位存入SECOND NOP END

为方便调试

BREAKAT:

具体操作步骤:

当使用LCA软件时:

1)、运行LCA软件,设MODE为:

AEDK5196,8051,I,COM2,9600,EDIT(或PE3),EX1.ASM 保存设置(save option),初始化AEDK(initiate AEDK)

2)、选择DOS?EDIT FILE,编辑源程序(编辑时应注意全角标点和半角标

点之区分,编译环境只认识半角标点),保存为以.ASM为后缀的。

3)、进行编译,DOS?ASM51/ASM96,如果编译有错,返回步骤2)。 4)、选择FILE?LOAD FILE(EX1.1ST)?确认SEND TO AEDK。 5)、RUN?SET START ADDRESS(START)

2

RUN?SET END ADDRESS(BREAKAT) RUN?RUN

6)、WATCH?RAM?30?<逗号>?<逗号>。 你就会看到30:01-,69- (结果正确) 当使用LCA51ET软件时:

1)、启动LCA51ET软件,对LCA51ET的仿真机进行设定。

设置?仿真机?仿真机型号(AEDK5196ET),仿真机状态(I)?通讯?通讯口(COM1或COM2),波特率(9600)

然后对串口进行测试,直至测试串口通过。

设置?环境参数?调试?编译成功后自动加载到仿真机。

2)、选择:文件?新建,编辑汇编源程序,并以.ASM为后缀保存。 3)、进行编译,编译?编译当前文件。若无错误,则自动加载到仿真机中,若有错误,则将错误信息在输出窗口显示出来。根据提示将错误改正后进入4)。

4)、观察?添加观察项,取消自动识别标号复选框,然后在观察项中分别输入30H,31H。

5)、调试?通过型调试(或按F8),在程序的运行过程中,可以看到30H,31H单元中的内容发生改变,最终可以看到31H和30H中的值分别为69H和01H。

注:如果需要设置断点时应在运行前设定。 对以下两程序 采用与程序一类似的方法进行调试。 2, 16位二进制加法程序设计

将两个无符号16位二进制数存入RAM的20H~23H,利用工作寄存器进行取数,将两数相加,忽略最高位进位,并将结果存入24H、25H。其中20H、22H、24H存放三个数的低8位。 参考程序: MOV

20H,#0A9H

3

MOV 21H,#3FH MOV 22H,#7AH MOV 23H,#0D3H MOV R0,#20H MOV R1,#21H MOV A,@R0 CLR C INC R0 INC R0

MOV B,@R0 ADD A,B

MOV R0,#24H、 MOV @R0,A MOV A,@R1 INC R1 INC R1

MOV B,@R1 ADDC A,B INC R0

MOV @R0,A

END

3, 数据排序

将内部RAM70H~7FH中的16个数据按由小到大的顺序重新排序。参考程序: ORG 0000H LJMP MAIN ORG

0030H

MAIN: MOV 70H,#9FH MOV 71H,#0AH MOV 72H,#0A3H MOV 73H,#34H MOV 74H,#57H MOV 75H,#74H MOV 76H,#0D3H MOV 77H,#0E0H

MOV

78H,#95H

4

MOV 79H,#14H MOV 7AH,#26H MOV 7BH,#39H MOV 7CH,#93H MOV 7DH,#3FH MOV 7EH,#8AH

MOV 7FH,#2EH MOV

R2,#70H MOV R3,#71H L2: ACALL L1

INC R2 INC R3

CJNE R3,#80H,L2 L3: SJMP L3 NOP L1: MOV A,R2 MOV R0,A

MOV A,R3 MOV R1,A MOV A,@R0 L5: CLR C SUBB A,@R1 MOV A,@R0 JC L4

XCH A,@R1 MOV @R0,A L4: INC R1

CJNE R1,#80H,L5 MOV

@R0,A

RET

END

1. 8051系统的基本元件组成是什么,其功能是什么?2. 汇编语言源程序的基本结构是什么?

3. 汇编语言与C语言在程序设计上的区别有那些?

5

四、思考题:

实验二 利用8255进行输入输出的扩展

一,实验目的

1,了解8255的芯片结构及编程方法。 2,熟悉利用8255进行输入,输出扩展。 二,实验内容

1.利用8255实现对单片机端口的功能扩展,实现用单一端口于多外设的连接。使LED

的输出对应开关的按下。

2.在步骤一的基础下,将LED显示改为以二进制方式显示第几个开关被按下。 三,实验步骤

1,先根据实验连内容好电路:

将8255的CS(在8255的PA6旁边)接到74LS138的8400H(则命令地址字为8406H,PA口地址为8400H,PB口地址为8402H,PC口地址为8404H)。PA0~PA7接DL1~DL8(LED发光二极管),PB0~PB7接K1~K8(开关量)。

2,利用单片机编程实现下述功能:使发光二极管的点亮对应开关的状态。即当有开关

按下的时候,对应的发光二极管点亮。 编程指导:

将8255所接的按键组和发光二极管组认为是外部RAM,从而由硬件连线可以知道,按键组的地址为8402H,发光二极管组的地址为8400H。当单片机读地址8402H时,则将开关的状态获得,再将此数据写入8400H,则实现了对应二极管的点亮。反复执行程序,则实现了发光二极管的点亮与按键对应,有兴趣的同学可以将程序改为发光二极管的点亮与按键状态相反或其他对应关系。

3,实验硬件线路不变。将LED作为二进制显示器看待,认为点亮为1,熄灭为0,同

时对开关加以编号,使其依次为开关1,2,3??7,8,当只有一个开关为高电平时,LED以二进制方式显示第几个开关被按下,当有两个或以上的开关被按下时,

6

LED全亮。 编程提示:

对于开关按下的数量的判断,可以采用对A按位相加的方式进行检测,若结果为01H,则只有一个按键被按下,否则则有多个按键被按下。然后再对具体是哪一位被按下进行判断。 四,实验线路图 五,思考题:

1,单片机是以何种方式对外设进行访问的?在这种方式下需要添加那些外设以实现

对外设的访问?在访问外设时,单片机有那些动作? 2,51单片机的寻址能力如何?由什么决定?

7

实验三 单片机中断系统实验

一,实验目的

熟悉单片机内,外中断系统的应用。 二,实验内容

1,走马灯电路的实现(定时器中断的应用) 2,程序暂停的实现(外部中断的应用) 3,计数器的应用(计数器中断应用) 三,实验步骤

单片机和外部设备交换数据经常采用的方式有两种:查询方式和中断方式,而最常用的还是中断方式。因为中断方式具有CPU效率高,适合于实时控制系统等特点。51系统可以软件控制中断系统的屏蔽或开放,从而决定单片机系统是否对中断作出反应。对于中断,又有优先级高低之分,单片机优先响应优先级高的中断。单片机的中断响应子程序根据中断的不同有各自不同的程序入口,在单片机执行中断服务子程序时,为保证主程序的数据不丢失,应在执行子程序之前将主程序的有用数据推入堆栈,即进行断点保护。在单片机系统响应完中断后,只对部分中断申请自动撤除,这一点应注意。

51单片机的中断系统中共有5个中断,即:外部中断(INT0,INT1),定时/计数器中断(ET0,ET1),串行口(ES)。本实验设计了三个实验,分别练习使用三种中断。

1,走马灯电路

本实验目的是为了练习使用单片机的定时器中断。将单片机的P1口(紧靠8051芯片)与8只发光二极管相连接,用P1口驱动发光二极管。利用定时器产生中断,在定时器中断子程序中使P1口的输出数据改变(例如可以左移、右移),从而使发光二极管有规律的点亮,从而使它看上去象走马灯。 线路连接:只需将单片机的P1口与DL1~8连接即可。 编程提要:

8

主程序中主要完成开中断,设定定时器的工作方式,对定时器置数。 中断子程序中主要完成对P1口的操作。 2,程序暂停的实现

本实验主要使用51单片机的外部中断。在上一步实验的硬件基础上,将P3口与八个开关相连,利用八个开关中对应P3.3或P3.2的按键中的一个或多个作为程序暂停的控制开关。修改上一程序,使外部中断的优先级高于定时器中断,从而当有外部中断的时候,单片机优先响应外部中断。利用外部中断实现对程序的暂停控制。 编程提要:

修改上一程序,主程序中要同时开放定时器中断和外部中断,并要设定外部中断的优先级高于定时器中断。在设定外部中断触发方式时,建议设为下降沿触发。 添加外部中断的中断服务程序,在外部中断的服务程序中实现对程序暂停的处理,包括断点保护等动作。同时,为了实现程序暂停的解除,可以在中断服务子程序中加入一条判断转移语句,从而根据P3.X的状态决定是否退出中断程序,解除走马灯的暂停状态。 3,计数器中断实验

本实验主要应用51单片机的计数器中断。硬件上以上一步实验为基础,硬件上将开关接到P3.4或P3.5(根据程序设定决定)。设定中断方式为计数器中断,并将计数器模值设定为2或其他(即FDH或其他),触发方式设定为下降沿触发,在主程序中以P1口所接的发光二极管作为输出,进行中断计数(即发生了几次中断,输出为二进制形式)。 编程提要:

主程序中开放计数器中断,设定计数器触发方式为下降沿触发,设定ACC的初值为0。

中断子程序中对ACC中的值进行加一,将结果由P1口输出,从而将计数的结果

9

显示出来。

四,实验线路图:

五,思考题

1,单片机的中断有哪几种?其中断服务程序的入口地址各是什么?如何设定中断的

优先级?

2,定时器有哪几种工作方式?具体如何设定?

3,如何根据单片机的时钟频率计算定时器的设定时间? 4,如何设定计数器的计数值?

5,试述下降沿触发与电平触发的区别。

10

实验四 A/D、D/A转换的应用

一,实验目的

1,了解A/D、D/A转换的原理。

2,掌握ADC0809、DAC0832的性能及编程方法。 3,了解单片机中扩展A/D、D/A转换的基本方法。 二,实验内容

1,利用ADC0809实现AD转换功能

2,利用DAC0832产生三角波,并使用示波器观察 三,实验步骤

注:在进行A/D、D/A转换实验时应给仿真机供给正负12V电源。 1、A/D转换:

实验板上的电位器提供模拟量输入到ADC0809,由ADC0809转换成数字量,并由发光二极管将转换结果以二进制形式输出。

A/D转换器大致有三类:双积分转换器,精度高,抗干扰性好,价格便宜,但是速度慢;逐次逼近法A/D转换器,精度,速度,价格适中;并行A/D转换器,速度快,价格贵。ADC0809属于MOS工艺的逐次比较型八位A/D转换器,其主要控制信号有:

START启动信号:加上正脉冲后,A/D转换开始。

ALE地址锁存信号:高电平有效时把三个地址信号送入地址锁存器,并经译码器得到地址输出,以选择相应的模拟输入通道。

EOC转换结束信号:是芯片的输出信号。转换一开始,EOC信号变低,转换结束后返回高电平。这个信号可以作为A/D转换的状态信号来查询,也可以直接用作中断申请信号。

CLOCK时钟信号:最高允许值为640KHz。 实验连线:

11

实验时,将单片机的P1口经74LS240与发光二极管相连,用来输出转换结果(实验机内部P0口已经经74LS273与ADC0809相连)。并将ADC0809的EOC(内部已经反向器)与单片机的INT0(P3.2)相连。单片机将ADC0809作为外部RAM来读取。实验时74LS273的CS/接8300H,ADC0809的CS/接8100H。W1接ADC0809的IN0。

编程提要:

主程序中要开放外部中断,并应在主程序中完成对ADC0809的转换功能开启。 子程序中完成对ADC0809的查询并由P1口输出。

实验线路见图4.1。 2、D/A转换:

DAC0832是DAC0800系列的一种,为8位D/A转换器。其主要控制信号有: ILE输入锁存允许信号:高电平有效。

CS片选输入,低电平有效,控制输入寄存器的写入。 WR1写信号1,低电平有效,控制输入寄存器的写入。 WR2写信号2,低电平有效,控制DAC寄存器的写入。

XFER传送控制信号,低电平有效。控制数据从输入寄存器到DAC寄存器的传送。 控制关系:当ILE,CS,WR1都有效时,数据由输入端存入输入寄存器。而当WR2,XFER有效时,数据从输入寄存器传送到DAC寄存器,并进行数字到模拟的转换。

三角波的产生过程如下:

由单片机输出一个数据给DAC0832,则DAC0832对应输出一个模拟量,其值与数字量成正比。若使单片机的输出数值与时间成正比,则ADC0832的输出为一倾斜直线,其斜率由单片机控制,不断循环,则输出为三角波。应注意,三角波应分两段(上升和下降)来产生。此外,单片机把DAC0832当作外部RAM来进行写操作,故应注意给DAC0832分配适当的地址(CS/接8000H)。

12

编程提要:程序主要由一个循环实现,为产生数字输出建议使用查表程序。

图4.1A/D转换连线

13

图4.2D/A转换连线

五,思考题

1,单片机在操作对A/D、D/A时有那些动作?其顺序如何? 2,A/D转换有那几类?其工作原理是什么? 3,A/D、D/A转换的精度由什么决定?

14

实验五 C51编程练习

一,实验目的

熟悉C51的编程环境

练习使用C51语言进行单片机程序设计,学习使用C51的常用语句 二,实验内容

1、用C51语言编写程序,实现对8051单片机内部RAM中的数据进行排序2、用C51语言编写程序,实现实验二的两个程序的功能 三,实验步骤

1、数据排序

将内部RAM中的5个数据按由小到大的顺序重新排序。 参考程序: # include

# define uchar unsigned char main( ) {

uchar *point; uchar i, j, t; point=0x20; *point=56; point++; *point=64; point ++; *point=94; point ++; *point=82; point++; *point=15; point=0x20;

for (j=0;j<=3;j++)

for (i=0;i<=4-j;i++)

15

if (*(point+j)>*(point+j+i))

{t=*(point+j);*(point+j)=*(point+i+j);*(point+i+j)=t;} }

具体操作步骤:

当使用LCA51ET软件时:

1)、启动LCA51ET软件,对LCA51ET的仿真机进行设定。

设置?仿真机?仿真机型号(AEDK5196ET),仿真机状态(I)?通讯?通讯口(COM1或COM2),波特率(9600)

然后对串口进行测试,直至测试串口通过。

设置?环境参数?调试?编译成功后自动加载到仿真机。

2)、选择:文件?新建,编辑源程序,并保存为.C为后缀的文件。保存时应避免在文件名中出现连字符“-”和下划线“_”以免编译出错。

3)、进行编译,编译?编译并连接。若无错误,则自动加载到仿真机中,若有错误,则将错误信息在输出窗口显示出来。根据提示将错误改正后进入4)。

4)、观察?添加观察项,在观察项中分别输入20H??24H,point,i,j,t。此时可以看到这几个内存单元中的值。

5)、调试?通过型调试(或按F8),在程序的运行过程中,可以看到内存

的内容发生改变,最终可以看到排序的结果。

注:如果需要设置断点时应在运行前设定。

2、利用8255实现对单片机端口的功能扩展,实现用单一端口于多外设的连接。使LED的输出对应开关的按下。

实验线路连接:

16

8255的CS接74LS138的8400H(则命令地址字为8406H,PA口地址为8400H,

图5.1 单片机外接8255

PB口地址为8402H,PC口地址为8404H)。PA0~PA7接DL1~DL8(LED发光二极管),PB0~PB7接K1~K8(开关量)。实验线路图见图5.1。

参考程序:

# include

# include # include # define ADD8255

XBYTE[0x8406] /*8255状态命令口地址*/

17

# define ADD8255A # define ADD8255B

XBYTE[0x8400] /*8255PA口地址*/ XBYTE[0x8402] /*8255PB口地址*/

# define uchar unsigned char # define uint unsigned int main( )

{

uchar bdata A,P0; add8255=0x82; while(1)

{A=ADD8255B; ADD8255A=A; } }

3、在上一步骤的基础上,将LED显示改为以二进制方式显示第几个开关被按下。线路连接同上。

参考程序:

# include # include # define ADD8255 # define ADD8255A # define ADD8255B

XBYTE[0x8406] /*8255状态命令口地址*/ XBYTE[0x8400] /*8255PA口地址*/ XBYTE[0x8402] /*8255PB口地址*/

# define uchar unsigned char # define uint unsigned int main( ) {

uchar bdata A,B,P0; ADD8255=0x82; while (1)

{A=ADD8255B; switch (A) {

case 1: B=1;break; case 2: B=2;break; case 4: B=3;break; case 8: B=4;break; case 16: B=5;break;

18

case 32: B=6;break; case 64: B=7;break; case 128:B=8;break; default: B=255;break; } ADD8255A=B; } }

1、比较C51与汇编语言,指出C51语言的优点。 2、C51是如何对外设进行操作的?

3、C51的数据类型有那些?C51如何为数据分配存储空间?4、8255的地址是固定的吗?

19

四,思考题: 实验六 单片机中断系统实验(C51)

一,实验目的

学习使用C51语言进行单片机的中断系统编程 二,实验内容

1,走马灯电路的实现(定时器中断的应用) 2,程序暂停的实现(外部中断的应用) 3,计数器的应用(计数器中断应用) 实验步骤

三,1,走马灯电路

本实验目的是为了练习使用单片机的定时器中断。将单片机的P1口(在51芯片的左边)与8只发光二极管相连接,用P1口驱动发光二极管。利用定时器产生中断,在定时器中断子程序中使P1口的输出数据改变(例如可以左移、右移),从而使发光二极管有规律的点亮,从而使它看上去象走马灯。 编程提要:

主函数中主要完成开中断,设定定时器的工作方式,对定时器置数。 中断服务函数中主要完成对P1口的操作。 2,程序暂停的实现

本实验主要使用51单片机的外部中断。在上一步实验的硬件基础上,将P3口的P3.2或P3.3与一个开关相连,将此开关作为程序暂停的控制开关。修改上一程序,使外部中断的优先级高于定时器中断,从而当有外部中断的时候,单片机优先响应外部中断。利用外部中断实现对程序的暂停控制。 编程提要:

修改上一程序,主函数中要同时开放定时器中断和外部中断,并要设定外部中断的优先级高于定时器中断。在设定外部中断触发方式时,建议设为下降沿触发。

20

添加外部中断的中断服务程序,在外部中断的服务程序中实现对程序暂停的处理,包括断点保护等动作。同时,为了实现程序暂停的解除,可以在中断服务函数中加入一条判断转移语句,从而根据P3.X的状态决定是否退出中断程序,解除走马灯的暂停状态。 3,计数器中断实验

本实验主要应用51单片机的计数器中断。硬件上以上一步实验为基础,硬件上将开关接到P3.4或P3.5(根据程序设定决定)。设定中断方式为计数器中断,并将计数器模值设定为2或其他(即FDH或其他),触发方式设定为下降沿触发,在主程序中以P1口所接的发光二极管作为输出,进行中断计数(即发生了几次中断,输出为二进制形式)。 编程提要:

主函数中开放计数器中断,设定计数器触发方式为下降沿触发,设定ACC的初值为0。

中断服务函数中对ACC中的值进行加一,将结果由P1口输出,从而将计数的结果显示出来。

四、实验线路图:

见图6。 五、思考题

1,C51语言的中断服务函数的格式如何?

2,什么叫做单片机的中断扩展?如何对单片机进行中断扩展?

3,C51在默认状态下执行中断服务程序时会对主程序的那些数据进行保护? 4,外部中断、定时器中断和计数器中断的中断标志位会自动清零吗?

21

图6 中断练习

22

实验七 A/D、D/A实验(C51)

一,实验目的

练习使用C51语言进行单片机程序设计 学习使用C51语句进行A/D、D/A转换 二,实验内容

1,利用ADC0809实现数字电压表

2,利用DAC0832产生三角波,并使用示波器观察 三,实验步骤

1、数字电压表

由实验四可以得到如下启发:ADC0809输出的数字量与模拟量之间有一个比例系数,计算出此比例系数,再对数字量进行相应的变换,则得到的数字量即为输入信号的电压值,从而实现了数字电压表的功能。

实验连线

将单片机的P1口(在51的左边)与74LS240的DL1~DL8相连,从而使P1口经74LS240与发光二极管相连,用来输出转换结果。将ADC0809的EOC(已经过反向器)与单片机的INT0(P3.2)相连,单片机将ADC0809作为外部RAM来读取。将74LS273的CS/接8300H,ADC0809的CS/接8100H。W1接ADC0809的IN0。

编程提要:

主函数中要开放外部中断,并应在主程序中完成对ADC0809的转换功能开启。 中断服务函数中完成对ADC0809的查询,数值换算并将结果由P1口输出。 2、三角波的产生过程如下:

由单片机输出一个数据给DAC0832,则DAC0832对应输出一个模拟量,使单片机的输出数值与时间成正比,则ADC0832的输出为一倾斜直线,其斜率由单片机控制。不断循环,则输出为三角波。应注意:三角波应分两段来产生。此外,单片机把DAC0832当

23

作外部RAM来进行写操作,故应注意给DAC0832分配适当的地址(CS/接8000H)。

编程提要:程序主要由一个循环实现,其中三角波的生成数据部分可以放在数组中,循环输出。 四,实验线路图

同实验四。 五,思考题

1,能否将D/A的输出接到A/D的输入,从而用A/D来监测D/A的输出?如果能,具

体如何设计?

2,基于上一思路,你受到了什么启发?可以将这一思路应用于那些具体设计?

24

实验八 单片机实验设计

一,实验目的

巩固已学知识,激发对单片机以及电气工程的学习兴趣 二,实验内容

根据AEDK5196ET实验板上的硬件资源(如LED灯,数码管,8255,键盘,A/D,D/A等),利用所学的汇编及C51程序设计知识,自行设计一个实验,并完成。 三,实验步骤

到本次实验为止,我们已经完成了七个实验,其中四个为汇编语言程序设计,三个为C51程序设计,通过这些实验,相信大家对8051单片机的主要功能、编程方法、外部扩展方式都有了一定的了解,大家都具备了一定的单片机开发设计能力。为了体现实验中学生的主动地位,培养学生的想象力、创造力以及分析问题解决问题的能力,本次实验对实验内容不作具体要求,由学生自己设计。 四,设计要求

1、内容要求

要求实验内容以单片机为核心,以单片机的实用为目的,完成一定的功能,同时应

最大限度的利用51单片机的资源,应为51单片机多种功能的综合。

2、硬件要求

硬件以AEDK5196ET实验机为基础,不能附加其它设备。 3、语言要求

具体由教师规定,这里不做硬性规定。

五,评分标准

根据设计,具体从以下几个方面考察: 1、立意的新颖程度;

2、程序设计的完善程度,代码的效率高低;

25

3、设计的难度;

4、硬件的利用情况,在基本相同的情况下,硬件使用多者由于使用少者; 5、完成的速度。

注:AEDK5196ET实验机的P0口只能读入,不能输出!

26

附录一:AEDK5196ET硬件资料

AEDK5196ET实验系统可以工作在二种模式下:

(1),AEDK5196ET实验系统工作在串行模式

用户根据实验要求进行MCS51单片机实验时(8032芯片已经插在D3插坐上),K9的短路套插向51端.进行MCS96单片机实验时,将CPU96S/CPU96E卡插入J5插座,K9的短路套插向96端.

用实验机配套的串行通讯电缆,将9芯电缆的一端与实验机上的J9插座相连,另一端与PC机的串口相连.

开电源, AEDK5196ET机上将显示:AEDK.U51(51方式) AEDK.U96(96方式) (2), AEDK5196ET实验系统工作在独立运行模式

用户根据实验要求进行MCS51单片机实验时(8032芯片已经插在D3插坐上),K9的短路套插向51端.进行MCS96单片机实验时,将CPU96S/CPU96E卡插入J5插座,K9的短路套插向96端.

开电源, AEDK5196ET机上将显示:AEDK.U51(51方式) AEDK.U96(96方式)

AEDK5196ET系统各开关初始状态

K9: 短路套向上插,实验机处于MCS51状态. K10: 短路套向右插.键盘由8279控制. K11: 短路套插上,与蜂鸣器相连. K12: K12-2 为ON,其余为OFF.

K13: K13拨向右边OFF端,切断外部电源. K14: 短路套插上,接通继电器指示灯显示.

27

K15: 短路套插上,实验机+5V通过J6的40脚接至用户板. K16: 短路套插上,VB电压接至J10第22脚.

注:AEDK5196ET实验机的P0口只能读入,不能输出!

当实验机打开后,实验者如果触到键盘的按键,可能会使实验机报警,此时只要按下RST键即可!

若实验机和PC不能通讯时,可以按下RST键,使仿真机复位后再试。

28

附录二 实验软件介绍

本实验采用AEDK系列仿真机,在进行汇编语言的编程时,DOS版软件采用LCA仿真机调试软件,WINDOWS版采用LCA51仿真软件,下面分开介绍。 ?

LCA软件

LCA软件为DOS应用程序,启动时可以直接在DOS提示符下键入LCA后回车或在WINDOWS界面下点击LCA应用程序图标。进入后屏幕显示如附图2.1。

附图2.1

? 选中MODE下拉菜单,可进行以下设定:

AEDK TYPE:用于设定仿真机型号,本实验所用仿真机为AEDK 5196ET,故将其设定为AEDK 5196。

CPU:用于设定所仿真的CPU,本实验设定为8051。

COMMUNICATION:用于设定仿真机与PC通讯时的通讯端口。依AEDK5196ET与

29

计算机的具体连接情况可设为 COM1或COM2。

BAUD:用于设定仿真机与PC通讯时的速度,建议设为9600。

AEDK STATUS:用于设定仿真机的状态,仿真8051时有I,O,B三种状态,建议设定为I。AEDK5196ET实验系统地址空间状态分I状态和O状态,I状态时程序存储器和数据存储器由本系统的RAM区提供,RAM最大可用空间未1.75K。O状态时程序和数据存储器由用户系统提供。在I状态下地址分布如下:

0000H~7F3FH:实验机上RAM区,可作程序区或数据区。 7F40H~7FFFH:实验机上RAM区,由监控占用,用户不得使用。 8000H~BFFFH:可供寻址的程序、数据空间。用户可在此空间扩展器件 C000H~FDFFH:监控程序用。

FE00H~FFFFH:实验机上固定地址的I/O。

EDITER NAME:用于设定编译器所用程序,本实验为PE3。 FILE NAME:用于设定原文件名,根据用户文件名设定为***.ASM。

SAVE OPTION:用于保存MODE菜单中的设定值,可将设定值保存在LCA.CFG中。 INITIATE AEDK:用于初始化仿真机。选择此选项后,软件会询问是否需要外部复位,选择Y,并按下仿真机上的复位按钮,初始化后的显示如附图2.2。 ? 选中DOS菜单,在DOS菜单中有以下功能选项:

ASM51/ASM96:编译器,用于把汇编源文件编译成最终可用于加载于仿真机上运行的文件。

DOS SHELL:DOS 环境。

EDIT FILE:文件编辑器,可用于编写汇编源文件。

DIR:用于改变LCA的工作路径。LCA只能找到此路径下的文件。使用者可以根据需要将其设定为需要的目录。

ASCII TABLE:二进制字符代码表,用于查阅。

HEX/DEC CACULATOR:十进制到十六进制的转换计算器。

30

51/96 INSTRUCTION SET:51/96单片机的结构及资源表。 QUIT:退出LCA软件。

使用者可以使用EDIT FILE进行文件编辑,若已经完成了汇编源文件的编辑,则可以直接运行ASM51/ASM96进行编译。若编译无错,则屏幕显示:“PRESS ANY KEY TO CONTINUE??”,按任意键回到LCA主界面。

当完成了汇编文件的编译后,就可以将生成的文件传送到仿真机中进行运行了。具体操作如下:

? 选择FILE 菜单,有以下选项:

LOAD FILE:用于载入文件到LCA程序中。选中此选项后,程序载入LCA,并且LCA询问是否将文件加载到仿真机,回车后开始发送。传送成功后,会显示“SENDING OK!!!”,按任意键继续。

OPEN FILE:用于在LCA中打开文件,此选项并不会将文件传送到仿真机中。 SEND TO AEDK:将打开的文件送到仿真机。 RECEIVE AEDK:用于LCA从仿真机中取得程序。 SEND HEX DATA:传送十六进制数据。

31

附图2.2

当文件加载到仿真机中后,就可以运行了。具体操作如下: ? 选中RUN菜单,有以下选项:

SET START ADDRESS:用于设定起始地址。

SET END ADDRESS:用于设定结束地址。这两个命令在调试程序时十分有用,可以使单片机只运行程序的一部分。

CLEAR ALL BREAKPOINTS:用于取消上述两语句设定的断点。

RUN;运行全部语句,此时全部程序都将被运行,也可以使用快捷键F9来运行。一般运行时均选择此选项。

当程序运行时,LCA窗口内显示“RUNNING,PLEASE WAIT??”。待程序运行结束后,可以使用WATCH?RAM 来查看运行结果。

32

? LCA51仿真软件

LCA51为运行在WINDOWS界面下的仿真软件,启动后界面如附图2.3。 在LCA主界面中包含多个窗口,其具体功能介绍如下:

? 编辑窗口

为源文件编辑器,它不受文件大小的限制,可无限制的撤销/重复,支持汇编、C51和PL/M51语言。

? 输出窗口

用于显示编译连接过程中的输出信息,双击某条编译出错信息提示即可直接定位到源文件的对应行。

编辑窗口 内部数据窗口 观察窗口 对话窗口 输出窗口 附图2.3

33

? 观察窗口

用于显示调试过程中观察的变量项,在该窗口中单击右键,可以击活菜单进行添加、删除、修改、刷新观察项。

? 数据窗口

用于显示仿真机中相应存储区的内容,并可以对数据进行修改,可以单击右键击活功能菜单。

? 对话窗口

在此窗口中可以直接用监控命令和仿真机对话。

菜单介绍

文件:和文件有关的操作,如打开、关闭、打印等文件操作。 编辑:包括拷贝、剪切、粘贴、书签、查找、替换等操作。 编译:用于对源文件进行编译、连接,生成OBJ文件。 ?

编译当前文件 ALT+F9

选择该菜单项将对当前窗口文件进行编译,编译后的有关信息将在输出窗口中显示。LCA51会自动识别目标文件和源文件日期相关性,如果目标文件比源文件新,将不再编译。可以编译的文件类型必须以.C、.PLM、.ASM、.A51结尾。 ?

连接

选择该菜单项将对当前窗口编译产生的目标文件进行连接,有关编译和连接的信息将在输出窗口显示。此菜单项仅对高级语言有效。 ?

编译并连接

选择该菜单项将对当前窗口的高级语言源程序同时进行编译和连接,有关编译和连接的信息将在输出窗口显示。此菜单项仅对高级语言有效。 ?

全部编译

选择该菜单项将对当前窗口文件进行编译,编译后的有关信息将在输出窗口显示。该命令与其他命令的区别是:该命令不识别目标文件和源文件日期的相关性,

34

不管目标文件是否比源文件旧,无条件编译源文件。

调试:可将生成的目标文件加载到仿真机中进行调试,可控制仿真机单步运行,运行到指定点,或者全速运行以及设置短点、清仿真机等。

?

加载调试

选择该菜单项,将弹出一个加载对话框,如附图2.4。该命令加载最新编译连接生成的目标文件到仿真机中进行调试。对话框中显示加载的文件名,文件信息,实际目标代码长度,加载空间和加载进度等。加载完毕后,对话框自动关闭,此时切换到调试状态。

附图2.4

?

加载目标文件

选择该菜单项,弹出一个加载目标文件对话框。可以加载到仿真机中的文件的扩展名为.OBJ、.HEX、.OMF。 ?

跟踪型单步

选择此菜单,仅从当前PC指针行执行源文件的一行语句,然后停止。如果该行语句是调用一函数,则跟踪进入函数中,在执行函数的第一条源语句行前停止。 ?

通过型单步

选择此菜单项,仅从当前PC指针行执行源文件的一行语句,然后停止。如果该行

35

语句是调用一函数,则一次运行完整个函数。 ?

全速运行

全速运行程序,遇到用户断点或按暂停键停止。 观察:在观察窗口添加观察变量或对观察变量进行修改等。

设置:用于设定AEDK仿真机的型号、通讯口、编译、连接、调试模式等环境参数的设置。

?

仿真机

用于设定仿真机型号,仿真机状态等。对于本实验,仿真机型号应设定为AEDK5196,仿真机状态应设定为I状态。AEDK5196ET实验系统地址空间状态分I状态和O状态,I状态时程序存储器和数据存储器由本系统的RAM区提供,RAM最大可用空间未1.75K。O状态时程序和数据存储器由用户系统提供。在I状态下地址分布如下:

0000H~7F3FH:实验机上RAM区,可作程序区或数据区。 7F40H~7FFFH:实验机上RAM区,由监控占用,用户不得使用。 8000H~BFFFH:可供寻址的程序、数据空间。用户可在此空间扩展器件 C000H~FDFFH:监控程序用。

FE00H~FFFFH:实验机上固定地址的I/O。 ?

通讯

可设定通讯口、波特率,并可对串口进行测试。对于通讯口应根据仿真机与PC机的实际连接情况进行设定,波特率可设定为9600。而对于延时因子,可不进行改动,当测试串口通不过时,可将延时因子置高。如通讯串口测试通过而出现调试时初始化失败或通讯不可靠时,可将延时因子置高。

注意:无论是LCA还是LCA51软件均不支持WINDOWS长路径格式!

36

附录三 C51语言简介

一、8051的编程语言

对于8051单片机,现在有四种语言支持,即:汇编、PL/M、C和BASIC。

BASIC通常附在PC机上,是初学编程的第一种语言,由于逐行解释所以很慢,不能做到实时性。BASIC为简化变量,所有变量全部采用浮点值,故程序复杂且执行时间长。8052单片机内固化有解释BASIC语言,适用于编程简单且对运行速度要求不高的场合。

PL/M是Intel从8080微处理器开始为其系列产品开发的汇编语言。它很像PASCAL,是一种结构化语言,但它使用关键字去定义结构。PL/M编译器像汇编语言的编译器一样可以产生紧凑代码。PL/M总的来说是“高级汇编语言”,可详细控制代码生成。但对8051系列,PL/M不支持复杂的算术运算、浮点变量,也无丰富的库函数支持。学习PL/M语言无异于学习一种新的语言。

C是一种源于编写UNIX操作系统的语言,它是一种结构化语言,可产生紧凑代码。C结构是以{}而不是字和特殊符号的语言。C可以进行许多机器级函数控制而不用汇编语言。与汇编相比,有如下优点:

对单片机的指令系统不要求了解,仅要求对8051的存储器结构有初步了解; 寄存器分配、不同存储器的寻址及数据类型等细节可由编译器管理; 程序有规范的结构,可分为不同的函数,这种方式可使程序结构化; 具有将可变的选择与特殊操作组合在一起的能力,改善了程序的可读性; 关键字及运算函数可用近似人的思维过程方式使用; 编程及程序调试时间显著缩短,从而提高效率;

提供的库包含许多标准子程序,具有较强的数据处理能力;

已编好的程序可容易的植入新程序,因为它具有方便的模块化编程技术。

37

8051系列单片机作为工业标准地位,从1985年开始就有8051单片机的C语言编译器,简称C51。许多公司都开发了自己的C51编译器,本书主要介绍FRANKLIN C51编译器。实验时采用AEDK实验机的LCA51ET软件环境,它的C51编译器采用FRANKLIN的C51编译器。

FRANKLIN

它的鼻祖是Keil,在代码生成方面领先,可产生最少的代码。它支持浮点和长整数、重入和递归。它不提供库源代码,不能产生能汇编的汇编代码,仅产生混合代码,只能修改后汇编。若使用汇编语言,必须分开汇编程序,然后手工连接。若使用单片模式它是最好的选择。Keil/Franklin专业级开发工具PK51,支持DOS和WINDOW环境。

二、C51数据与运算 1、数据类型

位型(bit) 字符型(char) 整型(int) 长整型(long) 浮点型(float) 双精度浮点型(double) 数组类型(array) 结构体类型(struct) 共用体(union) 枚举(enum) 基本类型 数据类型 构造类型 指针类型 表1. Franklin C51的数据类型

数据类型 bit unsigned Char signed char Unsigned int Signed int unsigned long signed long 长度(bit) 1 8 8 16 16 32 32 长度(byte) 1 1 2 2 4 4 值域范围 0,1 0~255 -128~127 0~65535 -32768~32767 0~4294967295 -2147483648~2147483647 38

Float 32 Double 64 一般指针 24 注:sbit为可位寻址的bit型。 4 8 3 士1.176E-38 ~士3.40E+38 士1.176E-38 ~士3.40E+38 0~65535 编译的数据类型(如结构)包含表上所列的数据类型。由于8051系列是8位机,因而不存在字节校准问题。这意味着数据结构成员是顺序放置的。

数据类型的转换:当计算结果隐含着另外一种数据类型时,数据类型可以自动进行转换,例如,将一个位变量赋给一个整型变量时,位型值自动转换为整值,有符号的变量的符号也能自动进行处理。这些转换也可以用C语言的标准指令进行人工转换。

与计算机相比,8051系列单片机对变量类型或数据类型的选择更具有关键性的意义。在表中所列出的数据类型中,只有bit、sbit和unsigned char两种数据类型可以直接支持机器指令。对于C这样的高级语言,不管使用何种数据类型,虽然某一行程序从字面上看,其操作十分简单,然而,实际上C系统的编译器需要用一系列机器指令对其进行复杂的变量类型、数据类型的处理。特别是当使用浮点变量时,将明显地增加运算时间和程序的长度。当程序必须保证运算精度时,C编译器将调用相应的子程序库,把它们加到程序中去。所以在编写C程序时应避免使用不必要的变量类型,以免导致C编译器相应地增加所调用的库函数的数量,使程序变得过于庞大,运行速度减慢,所以必须特别慎重地进行变量和数据类型的选择。

位变量(bit)——变量的类型是位,位变量的值可以是1(true)或0(false)。与8051硬件特性操作有关的位变量必须定位在8051 CPU片内存贮区(RAM)的可位寻址空间中。

字符变量(char)——字符变量的长度为1byte即8位。这很适合8051单片机,因为8051单片机每次可处理8位数据。

下面就有符号/无符号(signed/unsigned)问题作一些说明。在编写程序时,如果使用signed和unsigned两种数据类型,那么就得使用两种格式类型的库函数,这将使占用的存贮空间成倍增长。因此在编程时,如果只强调程序的运算速度而又不进行负数运算时,最好采用无符号(unsigned)格式。

39

无符号字符类型的使用:无论何时,应尽可能地使用无符号字符变量,因为它能直接被8051所接受。基于同样的原因,也应尽量使用位变量。有符号字符变量(signed char)虽然也只占用一个字节,但需要进行额外的操作来测试代码的符号位。这无疑会降低代码效率。

最后要提到的是使用缩写形式定义数据类型。在编程时,为了书写方便,经常使用简化的缩写形式来定义变量的数据类型。其方法是在源程序开头使用#define语句。

例如:

#define uchar unsigned char #define uint unsigned int

这样,在以后的编程中,就可以用uchar代替unsigned char,用uint代替unsigned int来定义变量。

三、C51数据的存储类型与8051存储器结构

在8051系列单片机中,程序存贮器与数据存贮器严格分开,特殊功能寄存器与片内数据存贮器统一编址,这是单片机与一般微机的存贮器结构有所不同的两个特点。

Franklin C51编译器完全支持8051单片机的硬件结构,可完全访问8051硬件系统的所有部分。该编译器通过将变量、常量定义成不同的存贮类型(data,bdata,idata,pdata,xdata,code)的方法,将它们定位在不同的存贮区中。

存贮类型与8051单片机实际存贮空间的对应关系如表2所示。

表2. C51存储类型与8051存储空间的对应关系

存储类型 data bdata idata pdata xdata 与存储空间的对应关系 直接寻址片内数据存储区,访问速度快(128字节) 可位寻址片内数据存储区,允许位与字节混合访问(16字节) 间接寻址片内数据存储区,可访问片内全部RAM地址空间(256字节) 分页寻址片外数据存储区(256字节)由MOVX@R0访问 片外数据存储区(64K),由MOVX@DPTR访问 40

code 代码存储区(64K),由MOVC@DPTR访问

当使用存贮类型data,bdata定义常量和变量时,C51编译器会将它们定位在片内数据存贮区中(片内RAM),这个存贮区根据8051单片机CPU的型号不同,其长度分别为64,128,256或512字节。以今天的标准来看,这个存贮区不是很大,但它能快速收发各种数据。外部数据存贮器从物理上讲属于单片机的一个组成部分,但用这种存贮器存放数据,在使用前必须将它们移到片内数据存贮区中。片内数据存贮区是存放临时性传递变量或使用频率较高的变量的理想场所。

当使用code存贮类型定义数据时,C51编译器会将其定义在代码空间(ROM或EPROM),这里存放着指令代码和其它非易变信息。调试完成的程序代码被写入8051单片机的片内ROM/EPROM或片外EPROM中。在程序执行过程中,不会有信息写入这个区域,因为程序代码是不能进行自我改变的。

当使用xdata存贮类型定义常量、变量时,C51编译器会将其定位在外部数据存贮空间(片外RAM),该空间位于片外附加的8K,16K,32K或64K RAM芯片中(如一般常用的6264,62256等)。其最大可寻址范围为64K。在使用外部数据区的信息之前,必须用指令将它们移动到内部数据区中,当数据处理完之后,将结果返回到片外数据存贮区。片外数据存贮区主要用于存储不常使用的变量,或收集等待处理的数据,或存放要被发往另一台计算机的数据。

pdata存贮类型属于xdata类型,它的一字节地址(高8位)被妥善保存在P2口中,用于I/O操作。

idata存贮类型可以间接寻址内部数据存贮器(可以超过127个字节)。

访问片内数据存贮器(data,bdata,idata)比访问片外数据存贮器(xdata,pdata)相对要快一些,因此可将经常使用的变量置于片内数据存贮器,而将规模较大的,或不常使用的数据置于片外数据存贮器中。

C51存贮类型及其大小和值域如表3所示。

41

表3 C51存贮类型及其大小和值域

存储类型 data idata pdata code xdata 长度(bit) 8 8 8 16 16 长度(byte) 1 1 1 2 2

变量的存贮类型定义举例: char data varl; bit bdata flags;

/*item1*/

/*item2*/ /*inte3*/

/*item4*/

值域范围 0-255 0-255 0-255 0-65535 0-65535 float idata x,y,z;

unsigned int pdata dimension;

unsigned char xdata vector[l0][4][4] /*item5*/

item1:字符变量char varl被定义为data存贮类型,C5l编译器将把该变量定位在8051片内数据存贮区中(地址:00H~0FFH)。

item2:位变量flags被定义为bdata存贮类型,C51编译器将把该变量定位在8051片内数据存贮区(RAM)中的位寻址区(地址:20H~2FH)。

item3:浮点变量x,y,z被定义为idata存贮类型,C5l编译器将把该变量定位在805l片内数据存贮区,并只能用间接寻址的方法进行访问。

Item4:无符号整型变量dimension被定义为pdata存贮类型,C5l将把该变量定位在片外数据存贮区(片外RAM),并用操作码MOVX@Ri访问。

item5:无符号字符三维数组变量unsigned char vector[10][4][4]被定义为xdata存贮类型,C5l编译器将其定位在片外数据存贮区(片外RAM)中,并占据10X4X4=160个字节存贮空间存放该数组变量。

如果在变量定义时略去存贮类型标志符,编译器会自动选择默认的存贮类型。默认的存贮类型进一步由SMALL,COMPACT和LARGE存贮模式指令限制。例如,若声明char varl,

42

在SMALL存贮模式下,varl被定位在DATA存贮区;在使用COMPACT模式下,则varl被定位在IDATA存贮区中;在使用LARGE模式情况下,varl被定位在XDATA存贮区中。

存贮模式:存贮模式决定了变量的默认存贮类型,参数传递区和无明确存贮类型的说明。在固定的存贮器地址上进行变量的传递,是C5l的标准特征之一。在SMALL模式下,参数传递是在片内数据存贮区中完成的。LARGE和COMPACT模式允许参数在外部存贮器中传递。C5l同时也支持混合模式,例如,在LARGE模式下,生成的程序可将一些函数放人SMALL模式中,从而加快执行速度。关于存储模式的详细说明见表4。

表4 存储模式及说明

存贮模式 说 明 SMALL 参数及局部变量放入可直接寻址的片内存贮器(最大128字节,默认存贮类型是DATA),因此访问十分方便。另外所有对象,包括栈,都必须嵌入片内RAM。栈长很关键;因为实际栈长依赖于不同函数的嵌套层数。 COMPACT 参数及局部变量放入分页片外存贮区(最大256字节,默认的存贮类型是PDATA),通过寄存器R0和Rl(@R0,@Rl)间接寻址,栈空间位于8051系统内部数据存贮区中。 LARGE 参数及局部变量直接放人片外数据存贮区(最大64K,默认存贮类型为XDATA)使用数据指针DPTR来进行寻址。用此数据指针进行访问效率较低,尤其是对二个或多个字节的变量,这种数据类型的访问机制直接影响代码的长度。另一不方便之处在于这种数据指针不能对称操作。

C5l甚至允许在变量类型定义之前,指定存贮类型。因此定义data char x与定义char data x是等价的,但应尽量使用后一种方法。

四、8051特殊功能寄存器及其C51定义

805l单片机片内有21个特殊功能寄存器(SFR),它们分散在片内RAM区的高128字节中,地址为80H~0FFH,对SFR的操作,只能用直接寻址方式。

8051单片机中,除了程序计数器PC和4组通用寄存器组之外,其它所有的寄存器,均称为SFR,并位于片内特殊寄存器区。为了能直接访问这些特殊功能寄存器SFR,

43

Franklin C51提供了一种自主形式的定义方法,这种定义方法与标准C语言不兼容,只适用于对8051系列单片机进行C编程。这种定义的方法是引入关键字“sfr”,语法如下:

sfr sfr_name’=’int constant ’;’ 例:

sfr SCON=0x98; /*串口控制寄存器地址98H*/

sfr TMOD=0x89; /*定时/计数器模式控制寄存器地址89H*/

注意:“sfr”后面必须跟一个特殊寄存器名,“=”后面的地址必须是常数,不允许带有运算符的表达式,这个常数值的范围必须在特殊功能寄存器地址范围内,位于0x80到OxFF之间。

8051系列单片机的寄存器的数量与类型是极不相同的,因此建议将所有特殊的“sfr”定义放入一个头文件中,该文件应包括8051单片机一系列成员中的SFR定义。可由用户自己用一文本编辑器编写。

对SFR的16位数据的访问:在新的8051系列产品中,SFR在功能上经常组合为16位值,当SFR的高端地址直接位于其低端地址之后时,对SFRl6位值可以进行直接访问。例如8052的定时器2就是这种情况。为了有效地访问这类SFR,可使用关键字“sfr16”,16位SFR定义的语法与8位SFR相同,16位SFR的低端地址必须作为“sfrl6”的定义地址。

例:

sfrl6 T2=0xCC;/*定时器2:T2低8位地址=0CCH T2高8位地址=0CDH

定义中名字后面不是赋值语句,而是一个SFR地址,其高字节必须位于低字节之后,这种定义适用于所有新的SFR;但不能用于定时/计数器0和l。

在典型的8051应用问题中,经常需要单独访问SFR中的位,C51的扩充功能使之成为可能。特殊位(sbit)的定义,像SFR一样不与标准C兼容,使用关键字“sbit”可以访问位寻址对象。

44

与SFR定义一样,用关键字“bit”定义某些特殊位,并接受任何符号名,“=”号后将绝对地址赋给变量名,这种地址分配,有三种方法:

第一种方法:

sfr_name ’^’ int_constant

当特殊寄存器的地址为字节(8位)时,可使用这种方法。 sfr_name必须是已定义的SFR的名字。’^’后的语句定义了基地址上的特殊位的位置,该位置值必须是0—7的数,

如:

sfr PSW=0xD0; sbit OV=PSW^2; sbit CY=PSW^7; 第二种方法:

int_constant^int_constant

这种方法以一个整常数作为基地址,该值必须在0x80~0xFF之间,并能被8整除,确定位置的方法同上。

如:

sbit OV=0xD0^2; sbit CY=0xD0^7; 第三种方法: int_constant

这种方法将位的绝对地址赋给变量,地址必须位于0x80到0xFF之间。 如:

sbit OV=0xD2; shit CY=0xD7;

特殊功能位代表了一个独立的定义类,不能与其它位定义和位域互换。

45

/*定义PSW寄存器地址为0xD0*/ /*定义OV位为PSW.2地址为0xD2*/ /*定义CY位为PSW.7地址为0xD7*/

/* OV位地址为0xD2*/ /* CY位地址为0xD7*/

五、8051并行接口及其C5l定义

8051单片机芯片内带有4个8位的并行口,共32根I/O线。每个口主要由四部分组成:端口锁存器,即SFR中的P0口—P3口;输入缓冲器;输出缓冲器;引至芯片外的端口引脚。我们把这四个并行口统称为P0一P3,其中P1口、P2口和P3口为准双向口,PO口为双向三态口。

8051系列单片机的内部口是可以位寻址的,而大部分外部I/O口是字节寻址的,在给口指定硬件扩展电路时,可以在内部口中设置I/O控制线和信号线,而将外部口定义为字节宽度I/O口,这样在编程时可以大大简化寻址,并避免使用许多逻辑屏蔽位。

当使用C51进行编程时,8051片内I/O口与片外扩展I/O口可以统一在头文件中定义,也可以在程序中(一般在开始的位置)进行定义,其方法如下:

对于8051片内I/O口用关键字sfr来定义。 例

sfr P0=0x80; /*定义P0口,地址80H*/ sfr Pl=0x90; /*定义PI口,地址90H*/

对于片外扩展I/O口,则根据其硬件译码地址,将其视为片外数据存贮器的一个单元,使用#define语句进行定义:

#include

#define PORTA XBYTE[0xffc0]/*将PORTA定义为外部I/O口,地址为Oxffc0,长度为8位。

一旦在头文件或程序中对这些片内外I/O口进行定义以后,在程序中就可以自由使用这些口了。

定义口地址的目的是为了便于C51编译器按8051实际硬件结构建立I/O变量名与其实际地址的联系,以便使程序员能用软件模拟8051的硬件操作。

46

六、位变量及其C51定义

除了通常的C数据类型外,C51编译器支持“bit”数据类型,对此说明如下: 1.位变量的C51定义的语法及语义

bit direction_bit; /*将direction_bit定义为位变量*/ bit lock_pointer; /*将lock_pointer定义为位变量*/ bit display_invers; /*将display_invers定义为位变量*/ 2.函数可包含类型为“bit”的参数,也可以将其作为返回值; 例

bit func(bit bO,bit b1) { /*??*/ return(b1); }

3.对位变量定义的限制

位变量不能定义成一个指针,如不能定义:bit *bit_pointer。 不存在位数组,如不能定义bit b_array[ ]。

在位定义中,允许定义存贮类型,位变量都被放人一个位段,此段总位于8051内部RAM中,因此存贮类型限制为DATA或IDATA,如果将位变量的存贮类型定义成其它类型都将导致编译出错。

可位寻址对象 可位寻址对象指可以字节或位寻址的对象,该对象应位于8051片内可位寻址RAM区中,C51编译器允许数据类型为idata.的对象放人8051片内可位寻址RAM区中。

先定义变量的数据类型和存贮类型:

47

bdata int ibase, /*ibase定义为bdata整型变量*/ bdata char bary[4] /*bary [4]定义为bdata字符型数组*/ 然后可使用“sbit”定义可独立寻址访问的对象位;

sbit mybit0=ibase^0; /* mybit0定义为ibase的第0位*/ sbit mybitl5=ibase^15; /* mybitl5定义为ibase的第15位*/ sbit Ary07=bary[0]^7; /* Ary07定义为bary[0]的第7位*/ sbit Ary37=bary[3]^7; /* Ary37定义为bary[3]的第7位*/ 象“ibase”和“bary”也可以字节寻址。 例:

Ary37=0;

/*bary[3]的第7位赋值为0*/

Bary[3]=’a’; /*字节寻址:bary[3]赋值为’a’*/

sbit定义要求基址对象的存贮类型为“bdata”,否则只有绝对的特殊位定义(sbit)是合法的。位置(‘^’操作符)后的最大值依赖于指定的基类型,对于char/uchar而言是0-7,对于int/uint 而言是0-15,对于long/ulong而言是0-31。

六、C51运算符、表达式及其规则

C51具有与C语言相同的算术运算符、关系运算符、逻辑运算符和优先级。除次之外,还需要对C51的位操作及其表达式进行着重介绍,因为它在C51的实际编程中具有重要的地位。

C51提供了如下位操作运算符: & 按位与; ? 按位或; ^ 按位异或; ~ 按位取反;

48

<< 位左移; >> 位右移。

除了按位取反运算符~以外,以上位操作运算符都是两目运算符,即要求运算符两侧各有一个运算对象。

位运算符只能是整型或字符型数,不能为实型数据。

七、C51的构造数据类型

C51具有和C一样的数组类型,如一维数组,二维数组、字符数组等。这里着重介绍数组的一个非常有用的用途之一——查表。

许多专家希望单片机、控制器能对他们提出的公式进行高精度的数学运算。但对大多数实际应用来说,这并不是完全必要的。在许多嵌入式控制系统应用中,人们更愿意采用表格而不是数学公式计算。特别是那些对于传感器的非线性转换需要进行补偿的场合(例如水泵的流量传感器的非线性补偿),使用查表法(如有必要再加上线性插值法)将比采用复杂的曲线拟合所需要的数学方法有效得多,因为表格查找执行起来速度更快,所用代码较少。表可以事先计算好后装入EPROM中,使用内插法可以增加查表值的精度,减少表的长度。

数组的使用非常适合于这种查表方法。下面举一个将摄氏温度转换成华氏温度的例子来说明这个问题。

例:

#define uchar unsigned char

uchar code tempt[ ]={32,34,36,37,39,41};/*数组设置在EPROM中,长度为

实际输入的数值数*/

uchar ftoc(uchar dege) {

49

return tempt[degc];/*返回华氏温度值*/ } main( ) {

x=ftoc(5);/*得到5℃的华氏温度值*/ }

在程序的开始处,uchar code tempt[ ]={32,34,36,37,39,41};定义了一个无符号字符型数组tempt[ ],并对其进行初始化,将摄氏温度0,l,2,3,4,5对应的温度32,34,36,37,39,4l赋予数组tempt[ ],类型代码code指定编译器将此表定位在EPROM中。在主程序main()中调用函数ftoc(char degc)从tempt[ ]数组中查表获取相应的温度转换值。x=ftoc(5);执行后,x的结果为5℃相应的华氏温度41F?。

当程序中设定了一个数组时,C编译器就会在系统的存贮空间中开辟一个区域用于存放该数组的内容。数组就包含在这个由连续存贮单元组成的模块的存贮体内。对字符数组而言,它占据了内存中一串连续的字节位置。对整型(int)数组而言,它们将在存贮区中占据一串连续的字节对的位置。对长型(long)或浮点型(float)数组,一个成员将占有4个字节的存贮空间。对于多维数组来说,一个10X10X10的三维浮点数组需要大约4K字节的存贮空间,而一个25X25X25的三维浮点数组就需要大于64K的存贮空间(8051单片机的最大可寻址空间只有64K)。

当数组,特别是多维数组中大多数元素没有被有效地利用时,就会浪费大量的存贮空间。8051单片机这样的嵌入式控制器,不象复用式系统那样拥有大型的存贮区,其存贮资源极为有限,因此无论如何不能被不必要地占用。因此在进行C51编程开发时要仔细地根据需要来选择数组的大小。

关于Franklin C51的指针类型:

Franklin C51支持“基于存贮器的”指针和“一般”指针两种指针类型。基于存贮器的指针类型由C源代码中存贮器类型决定,并在编译时确定,用这种指针可以高效访问

50

本文来源:https://www.bwwdw.com/article/f2br.html

Top