第3章单片机C51语言设计基础3.1C51的数据3.2C51对单片机主要资源的控制3.3C51的基本运算与流程控制3.4C51的数组与指针3.5C51函数3.6C51的预处理命令3.1C51的数据•3.1.1数据类型•3.1.2常量与变量•3.1.3数据存储类型•3.1.4局部变量与全局变量3.1.1数据类型3.1.2常量与变量•1.常量•C51语言中的常量是不接受程序修改的固定值,常量可以是任意数据类型。•C51中的常量有整型常量、实型常量、字符型常量、字符串常量符号常量等。(1)整型常量•在整型常量后加一个字母“L”或“l”,表示该数位长整型。例如23L、0Xfd4l等。•如果需要的是负值,则必须将负号“-”放置于常量表达式的最前面,例如-0x56、-9等。(2)实型常量•实型常量又称浮点常量,是一个十进制表示的符号实数。实型常量的值包括整数部分、尾数部分和指数部分。实型常量的形式如下:•[digits][.digits][E[+/-]digits]•一些实型常量的示例如下:•15.75、1.575E1、1575E-3、•-0.0025、-2.5e-3、25E-4。(3)字符型常量•字符型常量是指用一对单引号括起来的一个字符。如'a'、'9'、'!'等。字符常量中的单引号只起定界作用并不表示字符本身。•在C51语言中,字符是按其对应的ASCII码值来存储的,1个字符占1个字节(4)字符串常量•字符串常量是指用一对双引号括起来的一串字符,双引号只起定界作用,如China、123456等。(5)符号常量•C51语言中允许将程序中的常量定义为一个标识符,称为符号常量。•符号常量一般使用大写英文字母表示,以区别于一般用小写字母表示的变量。•符号常量在使用前必须先定义,定义的形式是:•#define标识符常量•#definePI3.14159262.变量•变量的定义:•数据类型变量名;•inti,j,k;•unsignedcharsi;•unsignedintui;•doublebalance,profit,loss;•C51中常用的:bit、char、int(1)整型变量(int)16位数据•有符号:•signedint•-32768~32767•无符号:•unsignedint•0~65535•0x1234存储形式例3-1P50•(2)长整型变量(longint)•长整型变量长度是32位,占用4个字节(byte),其他方面和整型变量(int)相似。(3)实型变量•分为单精度(float)型和双精度(double)型。•其定义形式为:•floatx,y;//指定x,y为单精度实数•doublez;//指定z为双精度实数•在一般系统中,一个float型数据在内存中占4个字节(32位),一个double型数据占8个字节(64位)。单精度实数提供7位有效数字,双精度实数提供15~16位有效数字。(5)字符变量char•字符变量用来存放字符常量。注意只能存放1个字符。•字符变量的定义形式如下:•char变量名;•例如:charc1,c2;•它表示c1和c2为字符变量,各存放1个字符。可以用下面的语句对c1、c2赋值:•c1='a';c2='b';•字符变量的长度是1字节(byte)即8位。这很适合于8051单片机,因为8051单片机每次可以处理8位数据。(6)位变量(bit)•变量的类型是位,位变量的值可以是1(true)或0(false)。•与8051硬件特性操作有关的位变量必须定位在8051单片机片内存储区(RAM)的可位寻址空间中。3.有符号/无符号问题说明•(1)尽量使用无符号变量•(2)在编程时,为了书写方便,经常使用简化的缩写形式来定义变量的数据类型:•#defineucharunsignedchar•#defineuintunsignedint3.1.3数据存储类型•数据时存放在51单片机的存储器中的,因此要规定数据的存储类型。•P53表3-4•常用:data、xdata、code•另外:bdata(1)data区•data区的寻址是最快的,所以应该把经常使用的变量放在data区,但是data区的空间是有限的,data区除了包含程序变量外,还包含了堆栈和寄存器组。•data区声明中的存储类型标式符为data,通常指片内RAM的低128字节的内部数据存储的变量,可直接寻址。•声明举例如下:•unsignedchardatasystem_status=0;•unsignedintdataunit_id[2];•chardatainp_string[16];(2)bdata•bdata实际是data中的位寻址区,在这个区中声明变量就可以进行位寻址。位变量的声明对状态寄存器来说是十分有用的,因为它可能仅仅需要某一位,而不是整个字节。•bdata区声明中的存储类型标识符为bdata,指内部可位寻址的16字节存储区(20H到2FH),数据类型是可位寻址变量的数据类型。•以下是在bdata区中声明的位变量和使用位变量的例子:••unsignedcharbdatastatus_byte;•unsignedintbdatastatus_word;•unsignedlongbdatastatus_dword;•sbitstat_flag=status_byte^4;•if(status_word^15)•{…}•stat_flag=1;(3)idata区•idata区也可以存放使用比较频繁的变量,使用寄存器作为指针进行寻址。idata区声明中的存储类型标识符为idata,指内部的256字节的存储区,但是只能间接寻址,速度比直接寻址慢。•声明举例如下:•unsignedcharidatasystem_status=0;•unsignedintidataunit_id[2];•charidatainp_string[16];•floatidataout_value;(4)pdata区和xdata区•pdata区和xdata区属于外部数据存储区,外部数据区是可读可写的存储区,最多可以有64KB。•在这两个区,变量的声明与在其他区的语法是一样的,但pdata区只有256字节而xdata区可达65536字节。声明举例如下:•unsignedcharxdatasystem_status=0;•unsignedintpdataunit_id[2];•charxdatainp_string[16];•floatpdataout_value;•外部地址段中除了包含存储器地址外,还包含I/O器件的地址。对外部器件寻址可以通过指针或C51提供的宏,使用宏对外部器件I/O口进行寻址更具可读性。(5)程序存储区code•程序存储区的数据是不可改变的,跳转向量和状态表对code段访问和对xdata区访问的时间是一样的。编译的时候要对程序存储区中的对象进行初始化,否则就会产生错误。程序存储区code声明的标识符为code,在C51语言编译器中可以用code存储区类型标识符来访问程序存储区。下面是程序存储区声明的例子:•unsignedcharcodea[]=•{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15};变量存储类型定义举例:•chardatavar1;•bitbdataflags;•floatidatax,y,z;•unsignedintpdatadimension;•unsignedcharxdatavector[10][4][4];3.1.4局部变量与全局变量•从变量的作用范围来区分,变量可以被分为全局变量和局部变量;•某些变量在程序运行过程中是始终存在的---全局变量。•某些变量只是在进入某个函数时才开始存在---局部变量。1.局部变量•局部变量是在某个函数中存在的变量,也可以称为内部变量,它只在该函数内部有效。•局部变量可以分为动态局部变量和静态局部变量,使用关键词auto定义动态局部变量(auto可以省略),使用关键词static定义静态局部变量,例如:•autointa;•staticunsignedcharj;•动态局部变量在程序执行完毕后其存储空间被释放,而静态局部变量在程序执行完成后其存储空间并不释放,而且其值保持不变。•如果该函数再次被调用,则该函数初始化后其初始值为上次的数值。•动态局部变量和静态局部变量的区别如下:•动态局部变量在函数被调用时分配存储空间和初始化,每次函数调用时都需要初始化;静态局部变量在编译程序时分配存储空间和初始化,仅初始化一次。•动态局部变量存放在动态存储区,在每次退出所属函数时释放;静态局部变量存放在静态存储区,每次调用后函数不释放,保持函数执行完毕之后的数值到下一次调用。•如果在建立时动态局部变量不初始为一个不确定的数,静态局部变量不初始化,则它们的值为0或者是空字符。2.全局变量•全局变量是在整个源文件中都存在的变量,又称为外部变量。全局变量的有效区间是从定义点开始到源文件结束,其中的所有函数都可以直接访问该变量,如果定义点之前的函数需要访问该变量,则需要使用extern关键词对该变量进行声明,如果全局变量声明文件之外的源文件需要访问该变量,也需要使用extern关键词进行声明。全局变量有以下特点:•全局变量是整个文件都可以访问的变量,可以用于在函数之间共享大量的数据,存在周期长,在程序编译时就存在,如果两个函数需要在不互相调用时共享数据,则可以使用全局变量进行参数传递;•C51语言程序的函数只支持一个函数返回值,如果一个函数需要返回多个值,除了使用指针外,还要使用全局变量;•使用全局变量进行参数传递可以减少从实际参数向形式参数传递时所必需的堆栈操作;•在一个文件中,如果某个函数的局部变量和全局变量同名,则在这个局部变量的作用范围内局部变量不起作用,全局变量起作用;•全局变量一直存在,占用了大量的内存单元,并且加大了程序的耦合性,不利于程序的移植或复用。•静态局部变量的作用范围仅仅是在定义的函数内,不能被其他的函数访问,全局变量的作用范围是整个程序,静态全局变量的作用范围是该变量定义的文件;•静态局部变量是在函数内部定义,全局变量是在所有函数外定义;•静态局部变量仅仅在第1次调用时被初始化,再次调用时使用上次调用结束时的数值,全局变量在程序运行时建立,值为最近一条访问该全局变量的语句执行的结果。•另外,main函数虽然是.c文件的主文件,但也是一个函数,在其内部定义的变量也属于局部变量。全局变量一般在.c文件的开始部分定义或在.h文件中定义,由.c文件引用。C51语言程序多使用全局变量传递参数,因为这样可以降低程序处理的难度,加快程序执行的速度,提高程序的时效性。3.2C51对单片机资源的控制•3.2.1特殊功能寄存器的C51语言定义•3.2.2绝对地址的访问•3.2.3位变量的C51语言定义3.2.1特殊功能寄存器的C51定义•21个特殊功能寄存器。两种方式:•1.使用关键字sfr定义•sfr特功器名字=特功器地址;•sfrSCON=0x98;•/*串口控制寄存器地址98H*/•sfrTMOD=0X89;•/*定时器/计数器方式控制寄存器地址89H*/2.通过头文件访问SFR•#includereg51.h•//使用的单片机为Intel公司的MCS-51•voidmain(void)•{TL0=0xb0;•TH0=0x3c;•TR0=1;//启动定时器0•...•}3.SFR中位定义—3种方式•(1)第1种方法•sbit位名=特殊功能寄存器名^位置;•(2)第2种方法•sbit位名=字节地址^位置;•(3)第3种方法•sbit位名=位地址;例:•sfrPSW=0xD0;•sbitOV=PSW^2;•sbitOV=0xD0^2;•sbitOV=0xD2;•unsignedcharbdataflag;•sbitflag0=flag^0;•sfrP1=0x90;•s