工业计算机控制系统_第1页
工业计算机控制系统_第2页
工业计算机控制系统_第3页
工业计算机控制系统_第4页
工业计算机控制系统_第5页
已阅读5页,还剩94页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第1章C51语言基础

实例1-1:使P1.0的发光二极管闪烁(用户板1)

include<AT89X51.h>〃预处理命令

voidmain(void)〃主函数名

(

〃这是第一种注释方式

unsignedinta;〃定义变量a为int类型

/*这是第二种注释方式*/

do{//dowhile组成循环

for(a=0;a<50000;a++);//这是--个循环

Pl_0=0;〃设PIP口为低电平,点亮LED

for(a=0;a<50000;a++);〃这是一个循环

Pl_0=1;//设PIP口为高电平,熄灭LED

)

while(l);

一C51概述

(一1)C语言的特点

C语言简洁、紧装',使用方便、灵活。一共只有32个关键字

运算符丰富。共有34种。C把括号、赋值、逗号等都作为运算符处理。从而使C的运

算类型极为丰富,可以实现其他高级语言难以实现的运算。

数据结构类型丰富。

具有结构化的控制语句。

语法限制不太严格,程序设计自由度大。

生成目标代码质量高,程序执行效率高。

与汇编语言相比,用C语言写的程序可移植性好

C语言允许直接访问物理地址,能进行位(bit)操作,能实现汇编语言的大部分功能,

可以直接对硬件进行操作。因此有人把它称为中级语言。

(-)C51和汇编比较

编程调试灵活方便

高级语言的特点决定了它的灵活编程方式。当前几乎所有系列的单片机都有相应的C

语言级别的仿真调试系统,编程环境十分方便。

生成代码的编译效率高

当前较好的C语言编译效率已达到中高级程序开发人员的水平,用于较为复杂的单片

机应用系统时更具特色

完全模块化

一种功能由一个函数模块完成,有利于多人协同完成大系统项目开发。

同时,这种模块开发方式,可使程序模块不经修改而被其他项目所用

可移植性好

一种C语言环境下所编写的C程序,只需将部分与硬件相关的地方进行修改,就方便

的移植到另外一种系列的单片机上

便于项目维护管理

用C开发的代码便于开发小组计划项目,灵活管理、分工合作以及后期维护,基本杜

1

绝因开发人员变化而给项目进度或后期维护或升级所带来的影响

另外单片机C语言还具有如下优越性:

不懂得单片机的指令集,也能够编写完美的单片机程序;

无须懂得单片机的具体硬件,也能够编出符合硬件实际的专业水平的程序;

不同函数的数据实行覆盖,有效利用片上有限的RAM空间;

程序具有坚固性:数据被破坏是导致程序运行异常的重要因素。C语言对数据进行了

许多专业性的处理,避免了运行中间非异步的破坏;

C语言提供复杂的数据类型(数组、结构、联合、枚举、指针等),极大地增强了程序

处理能力和灵活性;

实例12Pl口接8个LED,使其循环点亮.(用户板1)

汇编程序如下:

ORG0000H

MOVR0,#0FEH

LO:MOVPl,RO

MOVA,RO

RLA

MOVRO,A

LCALLDELAY

AJMPLO

SJMP$

DELAY:MOVR1,#100

DEL2:MOVR2,#10

DEL1:MOVR3,#7DH

DELO:NOP

NOP

DJNZR3,DEL0

DJNZR2,DEL1

DJNZRLDEL2

RET

END

C51程序:

include<AT89X5l.h>〃预处理命令

voidmain(void)〃主函数名

(

unsignedinta;〃定义变量a为int类型

unsignedcharb;

b=Oxfe;

while(1)

(

Pl=b;

for(a=0;a<10000;a++);

b二〜b;

b=b«l;

if(b==O)b=OxOl;

b=~b;}

)

2

(三)KEILC上机步骤

(1)建立项目。点击Project菜单,选择弹出的下拉式菜单中的NewProject,建立一个C

程序项目名称,只要符合Windows文件规则的文件名都行。“保存”后的文件扩展名为uv2,

这是KEILuVision2项目文件扩展名。

(2)选择单片机类型,这里我们选择常用的Ateml公司的AT89C5E

(3)建立文件,编辑源文件,注意保存文件时后缀为.c

(4)向项目中添加刚编辑的C文件。

(5)编译。如发现错误根据输出窗口的信息进行修改。

(6)全速运行。此时打开串行窗口,进行观察串行调试窗口中不断的打出HelloWorld!”。

实例1-3:在串行调试窗口中不断的打出HelloWorld!"

include<AT89X51.H>

#include<stdio.h>

voidmain(void)

(

SCON=0x50;〃串口方式1,允许接收

TMOD=0x20;〃定时器I定时方式2

TCON=0x40;〃设定时器1开始计数

TH1=0xE8;//11.0592MHz1200波特率

TL1=0xE8;

TI=1;

TRI=1;〃启动定时器

while(l)

(

printf("HelloWorld!\n");〃显示HelloWorld

思考与练习

Pl口接8个LED,使其依次从低位到高位,再从高位到低位循环点亮.分别用汇编语言

和C语言两种方式实现.(用户板1)

汇编语言

ORG0000H

CONT:MOVR2,#07H

MOVA,#0FEH

NEXT:MOVP1,A

ACALLDELAY

RLA

DJNZR2,NEXT

MOVR2,#07H

NEXTkMOVPl,A

RRA

ACALLDELAY

DJNZR2,NEXT1

SJMPCONT

DELAY:MOVR3,#14H

MOVTMOD,#10H

3

MOVTH1,#3CH

MOVTL1,#OBOH

SETBTRI

LP1:JBCTF1,LP2

SJMPLP1

LP2:MOVTH1,#3CH

MOVTL1,#OBOH

DJNZR3,LP1

RET

END

C语言程序

include<AT89X5l.h>〃预处理命令

voidmain(void)〃主函数名

{unsignedinta;

unsignedcharb,ij;

while(1)

{b=0xfe;

for(i=0;i<8;i++)/*左移8位*/

{Pl=b;

for(a=0;a<10000;a++);

b=-b;

b=b«l;

b=〜b;}

b=0x7f;

for(j=O;j<8;j++)/*右移8位*/

{Pl=b;

for(a=0;a<10000;a++);

b二〜b;

b=b»l;

b=~b;}

二、数据类型

c语言的标识符和关键字

标识符用来标识源程序中某个对象(语句、数据类型、函数、变量、数组等)的名字。

标识符由字符串、数字、下划线等组成,第一个字符必须是字母或下划线开头的,C51中

有些库函数的标识符是以下划线开头,所以一般不要以下划线开头命名标识符。

在C51编译器中,只支持标识符的前32位为有效标识,故用户标识符不宜过长。

关键字则是编程语言保留的特殊标识符,它们具有固定名称和含义,在程序编写中不

允许标识符与关键字相同。在KEILuVision2中的关键字除了有ANSIC标准的32个关键

4

字外还根据51单片机的特点扩展了相关的关键字。

下表中列出了KEILuVision2C51编译器所支持的数据类型。

数据类型长度值域

unsignedchar单字节0-255

signedchar单字节-128〜+127

unsignedint双字节0-65535

signedint双字节-32768〜+32767

unsignedlong四字节0-4294967295

signedlong四字节-2147483648〜+2147483647

float四字节±L175494E-38〜±3・402823E+38

*1〜3字节对象的地址

bit位0或1

sfr单字节0-255

sfrl6双字节0〜65535

sbit位0或1

1.char字符类型

char类型的长度是一个字节,通常用于定义处理字符数据的变量或常量,分:

无符号字符类型unsignedchar表达的数值范围是0〜255。

有符号字符类型signedchar,用字节中最高位字节表示数据的符号,“0”表示正数,“1”

表示负数,负数用补码表示。所能表示的数值范围是-128〜+127。

默认值为signedchar类型。unsignedchar常用于处理ASCII字符或用「处理小于一或等

于255的整型数。

2.int整型

int整型长度为两个字节,用于存放一个双字节数据。分signedint,表示的数值范围

是-32768〜32767,

unsignedint,表示的数值范围是0〜65535。

默认值为signedint类型。

实例1-4:用户板1硬件仿真,看看unsignedchar和unsignedint用于

延时的不同效果:看P1口L0和L1发光二极管亮的时间。

include<AT89X51.h>〃预处理命令

voidmain(void)〃主函数名

(

unsignedinta;〃定义变量a为unsignedint类型

5

unsignedcharb;〃定义变量b为unsignedchar类型

do

{//dowhile组成循环

Pl_0=0;〃设P1.0口为低电平,点亮LED

for(a=0;a<65535;a++);〃空循环延时

Pl_0=1;//设P1.0口为高电平,熄灭LED

for(a=0;a<30000;a++);〃空循环延时

Pl」=0;〃设Pl.l口为低电平,点亮LED

for(b=0;b<255;b++);空循环延时,时间较短

Pl_l=1;〃设Pl.l口为高电平,熄灭LED

for(a=0;a<30000;a++);〃空循环延时

while(l);

3.long长整型

long长整型长度为四个字节,用于存放一个四字节数据。分

signedlong。表示的数值范围是-2147483648〜+2147483647,

unsignedlong,表示的数值范围是0-4294967295。

默认值为signedlong

4.float浮点型

float浮点型在十进制中具有7位有效数字,是符合IEEE-754标准的单精度浮点型数

据,占用四个字节。

5.*指针型

指针型本身就是一个变量,在这个变量中存放的指向另一个数据的地址。这个指针变

量要占据一定的内存单元,对不同的处理器长度也不尽相同,在C51中它的长度一般

为1〜3个字节。指针变量也具有类型,表示方法为

类型*指针变量名;例:char*pl;float*p2;

指针变量的类型表示该指针所指向地址中数据的类型,使用指针可方便地对8051各部

分物理地址直接操作。

6.bit位标量

bit位标量是C51编译器的一种扩充数据类型,利用它可定义一个位标量,但不能定义

位指针,也不能定义位数组。它的值是一个二进制位,不是0就是1,类似一些高级

语言中的Boolean类型中的True和False。

7.sfr特殊功能寄存器

sfr也是一种扩充数据类型,占用一个内存单元,值域为0~255。利用它可以访问51

单片机内部的所有特殊功能寄存器。

如用sfrP1=0x90这一句定P1为P1端口在片内的寄存器,在后面的语句中我们用以用

Pl=255(对Pl端口的所有引脚置高电平)之类的语句来操作特殊功能寄存器。

8.sfrl616位特殊功能寄存器

sfrl6占用两个内存单元,值域为0-65535。sfrl6和sfr一样用于操作特殊功能寄存器,

所不同的是它用于操作占两个字节的寄存器,如定时器T0和T1。

6

说明:

sfr和sfrl6可以直接对51单片机的特殊寄存器进行定义,定义方法如下:

sfr特殊功能寄存器名=特殊功能寄存器地址常数;

sfrl6特殊功能寄存器名=特殊功能寄存器地址常数;

我们可以这样定义AT89c51的Pl口

sfrPl=0x90;〃定义PlI/O口,其地址90H

sfrl6T2=OxCC;〃这里定义8052定时器2,1也址为T2L=CCH,T2H=CDH

9、sbit

sbit是C51中的一种扩充数据类型,利用它可以访问芯片内部的RAM中的可寻址位或

特殊功能寄存器中的可寻址位。

如先前我们定义了

sfrPI=0x90;〃因P1端口的寄存器是可位寻址的,所以我们可以定义

sbitpi.i=pr1;//Pl_l为Pl中的P1.1弓|脚

〃同痒我们可以用P1.1的地址去写,如sbitPl_l=0x91;

这样我们在以后的程序语句中就可以用P1-1来对PLI引脚进行读写操作了。

通常这些可以直接使用系统提供的预处理文件,里面已定义好各特殊功能寄存器的简

单名字。

这种方法其实和汇编是一样的,只是把特殊功能寄存器的位地址符号化了。

总之,如要访问P1.L定义方法有三:

(1)sbit位变量名=位地址

sbitPl_l=0x91;

这样是把位的绝对地址赋给位变量。同sfr一样sbit的位地址必须位于80H-FFH之间。

(2)Sbit位变量名=特殊功能寄存器名人位位置

sfrPl=0x90;

sbitPl_l=P1八1;〃先定义一个特殊功能寄存器名再指定位变量名所在的位置

当可寻址位位于特殊功能寄存器中时可采用这种方法

(3)sbit位变量名二字节地址八位位置

以一个常数(字节地址)作为基础,该常数必须在80H〜FFH之间。位位置是。〜7

的常数。

sbitPl.l=0x90A1;

举例:

sbitOV=0xD2;

sbitOV=OxDO八2;

sbitCY=0xD7;

sbitCY=OxDOA7;

sfrSCON=OX98;〃定义SCON〃

sbitRI=SCON八0;〃定义SCON的各位〃

sbitTI=SCONAl;

sbitRB8=SCON八2;

sbitTB8=SCONA3;

sbitREN=SCONA4;

sbitSM2=SCON八5;

sbitSMl=SCONA6;

sbitSMO=SCONA7;

7

注意:

*在KEILC中,头文件REG51.H已包含了51系列大部分内部资源的定义,使用时只要用

include关键字将其包含进来就可以了,具体如下:

REG51.H

Headerfileforgeneric80C51and80C31microcontroller.

Copyright(c)1988-2002KeilElektronikGmbHandKeilSoftware,Inc.

Allrightsreserved.

---------------------------------------------------------------------------*/

#ifndef_REG51_H_

#define_REG51_H_

/*BYTERegister*/

sfrP0=0x80;

sfrPl=0x90;

sfrP2=OxAO;

sfrP3=OxBO;

sfrPSW=OxDO;

sfrACC=OxEO;

sfrB=OxFO;

sfrSP=0x81;

sfrDPL=0x82;

sfrDPH=0x83;

sfrPCON=0x87;

sfrTCON=0x88;

sfrTMOD=0x89;

sfrTLO=0x8A;

sfrTLl=0x8B;

sfrTHO=0x8C;

sfrTH1=0x8D;

sfrIE=0xA8;

sfrIP=0xB8;

sfrSCON=0x98;

sfrSBUF=0x99;

/*BITRegister*/

/*PSW*/

sbitCY=0xD7;

sbitAC=0xD6;

sbitFO=0xD5;

sbitRSI=0xD4;

sbitRSO=0xD3;

sbitOV=0xD2;

sbitP=OxDO;

/*TCON*/

sbitTF1=0x8F;

sbitTRI=0x8E;

sbitTFO=0x8D;

sbitTRO=0x8C;

8

sbitIE1=0x8B;

sbitIT1=0x8A;

sbitIE0=0x89;

sbitITO=0x88;

/*IE*/

sbitEA=OxAF;

sbitES=OxAC;

sbitET1=0xAB;

sbitEXI=OxAA;

sbitETO=0xA9;

sbitEXO=0xA8;

/*ip*/

sbitPS=OxBC;

sbitPT1=OxBB;

sbitPX1=OxBA;

sbitPTO=0xB9;

sbitPXO=0xB8;

/*P3:7

sbitRD=0xB7;

sbitWR=0xB6;

sbitTl=0xB5;

sbitTO=0xB4;

sbitINTI=0xB3;

sbitINTO=0xB2;

sbitTXD=0xBl;

sbitRXD=OxBO;

/*SCON*/

sbitSMO=0x9F;

sbitSMI=0x9E;

sbitSM2=0x9D;

sbitREN=0x9C;

sbitTB8=0x9B;

sbitRB8=0x9A;

sbitTl=0x99;

sbitRI=0x98;

#endif

*用户还可以根据自己需要将数据类型重新定义

格式:typedef已有数据类型新的数据类型

例:typedefintword;/*将word定义为整型,即用word置换了int*/

wordi,j;/*将i,j定义为整型*/

例:用typedef定义结构类型

typedefstruct

{intmonth;

intday;

9

intyear;

}DATA;/*DATA作为一个新的数据类型(结构类型)名*/

DATAbirthday;

*在C语言程序的表达式或变量赋值运算中,有时会出现运算对象不一致的情况,则有两

种转换方式:

1隐式转换按下列优先级别自动转换:

bitfcharfintlongfloat

signed--unsigned

例:inta;

floatb=1.5;

a=b;〃执行结果a=l

2显式转换用()强制类型转换符,在给指针变量赋值时;该转换特别有用

例:

charxdata*p1;

pl=(charxdata*)ox8000;

*pl=W向外RAM0X8000单元内存字符'a«

总结

在C51程序设计中,变量数据类型的定义极其重要,因为在所有数据类型中只有bit

和unsignedchar两种数据类型可以直接支持机器指令,对于其他的数据类型C51编译器都

要进行一系列复杂的变量数据和变量类型的处理,而这种处理将会对应很长一段机器指令,

最终会使程序变得复杂、庞大,运行速度降低。

由此可见,在C51程序设计过程中,在满足数据要求的情况下,应尽可能使用unsigned

char变量和bit变量。signedchar变量虽然也只占用一个字节,但需要进行额外的操作来测

试代码的符号位,因此会降低代码执行效率。

三常量和变量

常量

常量是在程序运行过程中不能改变值的量,常量的数据类型有整型、浮点型、字符型、字

符串型和位标量。

1.整型常量可以表示为十进制如123,0,-89等。十六进制则以Ox开头如0x34,-0x3B

等。长整型就在数字后面加字母L,如104L,034L,0xF340等。

2.浮点型常量可分为十进制和指数表示形式。十进制由数字和小数点组成,如

0.888,3345.345,0.0等,整数或小数部分为0,可以省略但必须有小数点。指数表示形式

为[土]数字[.数字同±]数字,口中的内容为可选项,其中内容根据具体情况可有可无,

但其余部分必须有,如125e3,7e9,-3.0e-3o

3.字符型常量是单引号内的字符,如匕Td等,不可以显示的控制字符,可以在该

字符前面加一个反斜杠“\”组成专用转义字符。在下表给出了C51语言中由转义字符构

10

成的控制符

字符形式功能

\n换行

\t横向跳格(即跳到下一个输出区)

\v竖向跳格

\b退格

\r回车

\f走纸换页

\\反斜杠字符'

\单撇号字符

\"双撇号字符

4.字符串型常量由双引号内的字符组成,如“test”,“0K”等。当引号内没有字符时,

为空字符串。在使用特殊字符时同样要使用转义字符如双引号。在C中字符串常量是

作为字符类型数组来处理的,在存储字符串时系统会在字符串尾部加上\。转义字符以

作为该字符串的结束符。字符串常量“A”和字符常量,"是不同的,前者在存储时多占用

一个字节的字间。

5.位标量,它的值是一个二进制。

常量可用在不必改变值的场合,如固定的数据表,字库等。常量的定义方式有几

种,下面来加以说明。

#defineFalse0x0;//用预定义语句可以定义常量

#defineTrue0x1;〃这里定义False为0,True为1在程序中用到False编译时自动用

0替换,同理True替换为1

constunsignedintc=100:〃用const定义c为无符号int常量并赋值

以上两句它们的值都保存在程序存储器中,而程序存储器在运行中是不允许被修

改的,所以如果在这两句后面用了类似a=l10,a++这样的赋值语句,编译时将会出错。

举例

include<AT89X51.H>〃预处理文件里面定义了特殊寄存器的名称如P1口定义为P1

voidmain(void)

(

〃定义花样数据

constunsignedchardesign[32]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,

0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF,

0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,

0xE7,0xDB,0xBD,0x7E,0xFF};

unsignedinta;〃定义循环用的变量

unsignedcharb;〃在C51编程中因内存有限尽可能注意变量类型的使用

〃尽可能使用少字节的类型,在大型的程序中很受用

do{

for(b=0;b<32;b++)

(

for(a=0;a<30000;a++);〃延时一段时间

Pl=design[b];〃读已定义的花样数据并写花样数据到P1口

)

}while(l);

11

思考:

上述用常量数组实现显示效果的方式,对应在汇编中应该是如何实现的?

如要改变显示效果,如流水灯从中间向两侧扩散,或两侧向中间移动,程序该如何修

改。

变量

变量就是一种在程序执行过程中其值能不断变化的量。变量必须先定义后使用

标准c定义一个变量的格式如下:

[存储种类]数据类型变量名表

如autointa;〃存储种类分:auto,static,register,extern

C51定义一个变量的格式如下:

[存储种类]数据类型[存储器类型]变量名表

可选必选可选必选

存储器类型的说明就是指定该变量在C51硬件系统中所使用的存储区域,并在编译时

准确的定位。

存储种类

变量的存储种类有四种:auto(自动)、extern(外部)、static(静态)register(寄

存器)。

■auto定义的变量称为自动变量。自动变量作用的范围在定义它的函数体或复合语句

内部。在定义它的函数或复合语句被执行时,C51才为该变量分配内存空间,当函

数调用结束返回或复合语句执行结束时,自动变量所占用的内存空间被释放。可见

使用自动变量能有效使用单片机内存。变量定义若省略存储种类选项,则默认为

auto(自动)变量。

例:{

charc_var;

inti_var;

)

等价于

(

autocharc_var;

autointi_var;

)

■static定义的变量称为静态变量。静态变量分为静态局部变量和全局静态变量两

种。

局部静态变量是在两次函数调用之间仍能保持其值的局部变量。例如:用局部

静态变量计算输出卜10的阶乘值。

#include<stdio.h>

intfactorial(intn){

staticintfac=l;

fac=fac*n;

retum(fac);

)

voidmain(void){

inti;

for(i=l;i<l1;i++)

printf("%d!=%d\n",i,factorial(i));

12

全局静态变量是一种作用范围受限的外部变量。全局静态变量只能在定义它的程

序文件中才可以使用,其它文件不可改变其内容。占用固定的内存空间,不能作为别

的模块的外部变量。这点与单纯的全局变量不同。

■extern定义的变量称为外部变量。在一个函数体内,要使用一个已在该函数体外

或别的程序模块文件中定义过的外部变量时,该变量在本函数体内要用extern说

明。通常将多个函数或模块共享的变量定义为外部变量。外部变量是全局变量,在

程序执行期间一直占有固定的内存空间。

■register定义的变量称为寄存器变量。单片机访问寄存器的速度最快,通常将使用

频率最高的那些变量定义为寄存器变量。C51编译器能自动识别程序中使用频率最

高的变量,并自动将其作为寄存器变量,用户无需专门声明。

变量的存储器类型

存储器类型指明该变量所处的单片机的内存空间。对于每个变量可以准确地赋予其

存储器类型,使之能够在单片机系统中准确地定位。以下是KeilC51编译器所能识别的存

储器类型。

存储器类型说明

data直接访问内部数据存储器(128字节),访问速度最快

bdata可位寻址内部数据存储器(16字节),允许位与字节混合访问

idata间接访问内部数据存储器(256字节),允许访问全部内部地址

pdata分页访问外部数据存储器(256字节),用MOVX@Ri指令访问

xdata外部数据存储器(64KB),用MOVX@DPTR指令访问

code程序存储器(64KB),用MOVC@A+DPTR指令访问

变量定义的举例:

chardatavarl;/*在DATA区定义字符型变量varl*/

intidatavar2;/*在IDATA区定义整型变量var2*/

charcodetext]]="ENTERPARAMETER:“;

/*在CODE区定义字符串数组text[]*/

longxdataarray[100];

/*在XDATA区定义长整型数据变量array[]*/

externfloatidatax,y,z;

/*在idata区定义外部浮点型变量x,y,z*/

charbdataflags;/*在BDATA区定义字符型变量flags*/

sbitflagO=flagsAO;/*在BDATA区定义可位寻址变量flagO*/

sfrP0=0x80;/*定义特殊功能寄存器P0*/

13

三种存储器模式

如果在变量定义时省略了存储器类型标识符,C51编译器会选择默认的存储器类型.默

认的存储器类型由SMALL,COMPACT或LARGE存储模式指令决定.KeilC51编译器的三

种存储器模式对变量的影响如下:

SMALL存储模式:所有缺省变量参数均装入内部RAM(与使用显式的data关键字来定

义结果相同)。使用该模式的优点是访问速度快,缺点是空间有限,而且分配给堆栈的

空间比较少,遇到函数嵌套调用和函数递归调用时必须小心,该模式适用于较小的程

序。

COMPACT存储模式:所有缺省变量均位于外部RAM区的一页(与使用显式的pdata

关键字来定义结果相同),最多能够定义256字节变量。使用该模式的优点是变量定义

空间比SMALL模式大,但运行速度比SMALL模式慢。使用本模式时,程序通过@1^0

和@口来访问变量。

LARGE存储模式:所有缺省变量可放在多达64K字节的外部RAM区(与使用显式的

xdata关键字来定义结果相同),均使用数据指针DPTR来寻址。该模式的优点是空间大,

可定义变量多,缺点是速度较慢,一般用于较大的程序,或扩展了大容量外部RAM的

系统中。

例:若定义chars,在SMALL存储模式下,s被定位在DATA存储区;在COMPACT存储

模式下,s被定位在IDATA存储区:在LARGE存储模式下,s被定位在XDATA存储区。

注意:

■AT89C51芯片中RAM只有低128位,位于80H到FFH的高128位则在52芯片中

才有用,并和特殊寄存器地址重叠。

■如果省略存储器类型,系统则会按编译模式SMALL,COMPACT或LARGE所规定

的默认存储器类型去指定变量的存储区域。无论什么存储模式都可以声明变量在任

何的8051存储区范围,然而把最常用的命令如循环计数器和队列索引放在内部数

据区可以显著的提高系统性能。

■变量的存储种类与存储器类型是完全无关的。

外部RAM与扩展I/O地址的C51定义

MCS-51单片机扩展外部I/O口采用与片外RAM相同的寻址方法,所有扩展的I/O口

以及通过扩展I/O口连接的外设都与片外RAM统一编址,在汇编语言程序设计中,使用以

下指令访问外部I/O口地址:

MOVX@DPTR,A;寻址外部64K字节地址范围000H〜FFFFH

MOVXA,@DPTR

MOVX@Ri,A;寻址低256字节地址范围00H〜FFH

MOVXA,@Ri

而在C51程序设计中,如何定义外部RAM和扩展I/O口的地址呢?

C51提供了三种访问绝对地址的方法:

1.绝对宏:

14

在程序中,用"#include<absacc.h>"即可使用其中定义的宏来访问绝对地址,包括:

CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD

具体见以下ABSACC.H头文件:

Directaccessto8051,extended8051andPhilips80C51MXmemoryareas.

Copyright(c)1988-2002KeilElektronikGmbHandKeilSoftware,Inc.

Allrightsreserved.

---------------------------------------------------------------------------*/

#ifndef_ABSACC_H_

#define_ABSACC_H_

#defineCBYTE((unsignedcharvolatilecode*)0)

#defineDBYTE((unsignedcharvolatiledata*)0)

#definePBYTE((unsignedcharvolatilepdata*)0)

#defineXBYTE((unsignedcharvolatilexdata*)0)

#defineCWORD((unsignedintvolatilecode*)0)

#defineDWORD((unsignedintvolatiledata*)0)

#definePWORD((unsignedintvolatilepdata*)0)

#defineXWORD((unsignedintvolatilexdata*)0)

#ifdef_CX51_

#defineFVAR(object,addr)(*((objectvolatilefar*)(addr)))

#defineFARRAY(object,base)((objectvolatilefar*)(base))

#defineFCVAR(object,addr)("((objectconstfar*)(addr)))

#defineFCARRAY(object,base)((objectconstfar*)(base))

#else

#defineFVAR(object,addr)("((objectvolatilefar*)((addr)+0x10000L)))

#defineFCVAR(object,addr)("((objectconstfar*)((addr)+0x810000L)))

#defineFARRAY(object,base)((objectvolatilefar*)((base)+0x10000L))

#defineFCARRAY(object,base)((objectconstfar*)((base)+0x810000L))

#endif

在绝对地址访问头文件absacc.h中,定义了MCS-51单片机所有存储区域的绝对地址

访问关键字CBYTE、DBYTE、PBYTEWXBYTE,可以对相应的存储区域的绝对地址进

行字节寻址。其中包括,CBYTE寻址CODE区,DBYTE寻址DATA区,PBYTE寻址分

页XDATA区(低256字节),XBYTE寻址XDATA区。

例:

#include<absacc.h>

#include<reg5l.h>

#defineucharunsignedchar

#defineeeXBYTE[0x0005]

voidmain(void)

ucharuc_varl;

while(1)

ee=0x56;

uc_varl=XBYTE[0x0005J;

15

)

2at关键字

直窥在薮据定义后加上一at-const即可,但是注意:

(1)绝对变量不能被初使化;

(2)bit型函数及变量不能用_at_指定。

例如:

idatastructlinklist_at_0x40;指定list结构从40h开始。

xdatachartext[25b]_at_0xE000;指定text数组从0E000H开始

提示:如果外部绝对变量是7/0端口等可自行变化数据,需要使用volatile关键字进行描

述,请参考absacc.h。

3.连接定位控制

此法是利用连接控制指令codexdatapdata\databdata对“段”地址进行,如要指定某

具体变量地址,则很有局限性,不作详细讨论。

实例1-5:向串口(波特率为2400)不断发送Hi,可用串口调试窗口查看

#include"absacc.h"

#include<REG51.H>

#defineBUFXBYTE[0X1000]〃外RAM绝对地址声明

#defineBUF1XBYTE[0X10011

#defineBUF2XBYTEQX1002]

main()

{unsignedchar*p=&BUF,*q;

BUF=H';

BUF1=T;

BUF2='\0';

SCON=0X50;

TMOD=0X20;

THl=0Xf4;

TLl=0Xf4;

TR1=1;

while(l)

{q=p;

while(*q!=W)

{SBUF=*q;

q++;

while(!TI);

TI=0;

16

四运算符和表达式

运算符运算符解释结合方式

0[]->.括号(函数等),数组,两种结构成员由左向右

访问

否定,按位否定,增量,减量,正负由右向左

号,

*&(类型)

sizeof间接,取地址,类型转换,求大小

*/%乘,除,取模由左向右

+-加,减由左向右

«»左移,右移由左向右

<<=>=>小于,小于等于,大于等于,大于由左向右

==1=等于,不等于由左向右

&按位与由左向右

A按位异或由左向右

1按位或由左向右

&&逻辑与由左向右

11逻辑或由左向右

?:条件由右向左

一+———大一/一各种赋值由右向左

&=人=1=«=»=

逗号(顺序)由左向右

注:按照优先级大小由上向下排列,在同一行的运算符具有相同优先级。第二行是所有

的一元运算符。

运算符就是完成某种特定运算的符号,表达式则是由运算符及运算对象组成的具有特

定含义的一个式子.在任意一个表达式的后面加一个";"就构成了一个表达式语句.由运算符

和表达式可以组成C51程序的各种语句,C51的运算符与C语言的运算符基本一致。它把

除了控制语句和输入输出以外的几乎所有的基本操作都作为运算符处理,例如将赋值赋“=”

作为赋值运算符,方括号作为下标运算符。

C51的运算符具体有以下几类:

(1)算术运算符(+-*/%++--)

(2)关系运算符(<>==<=>=!=)

(3)逻辑运算符(!&&II)

(4)位运算符(<<>>〜&1八)

(5)赋值运算符(=及其扩展赋值运算符)

(6)条件运算符(?:)

17

(7)逗号运算符(,)

(8)指针运算符(*&)

(9)求字节运算符(sizeof)

(10)强制类型转换运算符(类型)

(11)下标运算符([])

(12)分量运算符(•)

(13)其它(如函数调用运算符())

算术运算符:□

+加法运算符,或正值运算符。如2+9=11,+6

-减法运算符,或负值运算符。如9-5=4,-5

*乘法运算符。如4*8=32

/除法运算符。如7/2=3,两个整数相除结果为整数,舍去小数

%求模运算符,或称求余运算符,要求两侧均为整型数。如9%2=1,9%5=4

自增自减运算符

++n表示在用该表达式的值之前先使n的值增1

n++表示在用该表达式的值之后再使n的值增1

-n表示在用该表达式的值之前先使n的值减1

n-表示在用该表达式的值之后再使n的值减1

例:inta=5,b=7,c,d;

c=a++;〃c=5

d=++d;//b=8

关系运算符口

>大于

<小于

>=大于等于(不小于)

<=小于等于(不大于)

==等于

关系,达式通常是用来判别某个条件是否满足。要注意的是用关系运算符的运算结果只有

0和1两种,也就是逻辑的真与假,当指定的条件满足时结果为1,不满足时结果为0,即关

系表达式的值是一个逻辑值。

例:inta=2,b=3,c;

c=a>b;//c=0

逻辑运算符:口

C51提供了三种逻辑运算符:

&&(逻辑与)II(逻辑或)!(逻辑非)

注意:参与逻辑运算的操作数为逻辑量,非0为1,0即为0,逻辑表达式的值为逻辑值。

例:inta=-l,b=0,=0,d;

d=a&&!b||c;//d=l

位运算符:

位运算本来属于汇编语言功能,由于C语言最初是为了编写系统程序而设计的,所以,它

提供了很多类似于汇编语言的处理能力,在C51中位运算结合8051单片机的具体特点得到

了进一步和加强。并专门定义了sbit可寻址位型(数据类型)。对于位操作对单片机的编程

非常重要,故对位操作符进行详细介绍。下表为位运算符的定义

18

&按与

&-位

-按或

《按位异

取反

~按位

移位

«左

移位

»右

运算

与”&

“按位

,

位是1

的对应

则结果

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论