
C51语言程序设计基础.ppt
77页第3章 单片机C51语言设计基础3.1 C51的数据的数据3.2 C51对单对单片机主要片机主要资资源的控制源的控制3.3 C51的基本运算与流程控制的基本运算与流程控制3.4 C51的数的数组组与指与指针针3.5 C51函数函数3.6 C51的的预处预处理命令理命令3.1 C51的数据3.1.1 数据数据类类型型 常量与常量与变变量量3.1.3 数据存数据存储类储类型型3.1.4 局部局部变变量与全局量与全局变变量量 3.1.1 数据类型3.1.2 常量与变量1.常量.常量 C51语语言中的常量是不接受程序修改的固定言中的常量是不接受程序修改的固定值值,常量可以是任意数据,常量可以是任意数据类类型 C51中的常量有中的常量有整型常量、整型常量、实实型常量、字符型常量、字符串常量符号型常量、字符型常量、字符串常量符号常量常量等((2))实实型常量型常量 在整型常量后加一个字母在整型常量后加一个字母“L”或或“l”,表示,表示该该数位数位长长整型例如例如23L、、0Xfd4l等 如果需要的是如果需要的是负值负值,,则则必必须须将将负负号号“-”放置于常量表达式放置于常量表达式的最前面,例如的最前面,例如-0x56、、-9等。
等实型常量又称型常量又称浮点常量浮点常量,是一个十,是一个十进制表示的符号制表示的符号实数实型常量的型常量的值包括整数部分、尾数部分和指包括整数部分、尾数部分和指数部分实型常量的形式如下:型常量的形式如下:[digits][.digits][E[+/-]digits]一些一些实型常量的示例如下:型常量的示例如下:、、、、1575E-3、、、、、、25E-4(3)字符型常量 字符型常量是指用一字符型常量是指用一对对单单引号引号括起来的一个字符如括起来的一个字符如'a'、、'9'、、'!!'等字符常量中的字符常量中的单单引号只起定界作用并不表示字符本身引号只起定界作用并不表示字符本身 在在C51语语言中,字符是按其言中,字符是按其对应对应的的ASCII码值码值来存来存储储的,的,1个字符占个字符占1个个字字节节 字符串常量是指用一字符串常量是指用一对双引号括起来的一串字符,双引号只起定界作用,双引号括起来的一串字符,双引号只起定界作用,如如"China"、、"123456"等 (5)符号常量 C51语言中允言中允许将程序中的常量定将程序中的常量定义为一个一个标识符,称符,称为符号常量符号常量。
符号常量一般使用符号常量一般使用大写大写英文字母表示,以区英文字母表示,以区别于一般用小写字母表于一般用小写字母表示的示的变量符号常量在使用前必符号常量在使用前必须先定先定义,定,定义的形式是:的形式是: #define 标识符符常量常量2.变量变变量的定量的定义义:: 数据数据类类型型 变变量名量名; int i,j,k; unsigned char si; unsigned int ui; double balance,profit,loss; C51中常用的:中常用的:bit、、char、、int(1)整型变量(INT)16位数据有符号:有符号:signed int -32 768~~32 767 无符号:无符号:unsigned int 0~~65 535 0x1234存存储形式形式((3))实实型型变变量量((2))长长整型整型变变量(量(long int)) 长长整型整型变变量量长长度是度是32位,占用位,占用4个字个字节节((byte),其他),其他方面和整型方面和整型变变量(量(int)相似。
相似分分为单精度(精度(float)型和双精度()型和双精度(double)型其定其定义形式形式为:: float x,y; //指定指定x,y为单精度精度实数数 double z; //指定指定z为双精度双精度实数数在一般系在一般系统中,一个中,一个float型数据在内存中占型数据在内存中占4个字个字节((32位),一个位),一个double型数据占型数据占8个字个字节((64位)单精精度度实数提供数提供7位有效数字,双精度位有效数字,双精度实数提供数提供15~~16位有效位有效数字(4)字符变量CHAR字符字符变变量用来存放字符常量注意只能存放量用来存放字符常量注意只能存放1个字符字符字符变变量的定量的定义义形式如下:形式如下:char 变变量名量名;例如:例如: char c1,c2;它表示它表示c1和和c2为为字符字符变变量,各存放量,各存放1个字符可以用下面的个字符可以用下面的语语句句对对c1、、c2赋赋值值::c1='a';c2='b';字符字符变变量的量的长长度是度是1字字节节((byte)即)即8位这这很适合于很适合于8051单单片机,因片机,因为为8051单单片机每次可以片机每次可以处处理理8位数据位数据。
变量的量的类型是位,位型是位,位变量的量的值可以是可以是1((true)或)或0((false)与与8051硬件特性操作有关的位硬件特性操作有关的位变量必量必须定位在定位在8051单片机片内存片机片内存储区区((RAM)的可位)的可位寻址空址空间中3.有符号/无符号问题说明((1)尽量使用无符号)尽量使用无符号变变量量((2)在)在编编程程时时,,为为了了书书写方便,写方便,经经常使用常使用简简化的化的缩缩写形式来定写形式来定义义变变量的数据量的数据类类型:型: #define uchar unsigned char #define uint unsigned int3.1.3 数据存储类型 数据数据时时存放在存放在51单单片机的存片机的存储储器中的,因此要器中的,因此要规规定数据的定数据的存存储类储类型P53 表表3-4 常用:常用:data、、xdata、、code 另外:另外:bdata((1))DATA区区data区的区的寻寻址是最快的,所以址是最快的,所以应该应该把把经经常使常使用的用的变变量放在量放在data区,但是区,但是data区的空区的空间间是是有限的,有限的,data区除了包含程序区除了包含程序变变量外,量外,还还包包含了堆含了堆栈栈和寄存器和寄存器组组。
data区声明中的存区声明中的存储类储类型型标标式符式符为为data,通,通常指片内常指片内RAM的低的低128字字节节的内部数据存的内部数据存储储的的变变量,可直接量,可直接寻寻址声明声明举举例如下:例如下: unsigned char data system_status=0; unsigned int data unit_id[2]; char data inp_string[16];bdata实际实际是是data中的位中的位寻寻址区,在址区,在这这个区中声个区中声明明变变量就可以量就可以进进行位行位寻寻址位变变量的声明量的声明对对状状态态寄存器来寄存器来说说是十分有用的,因是十分有用的,因为为它可能它可能仅仅仅仅需要某一位,而不是整个字需要某一位,而不是整个字节节bdata区声明中的存区声明中的存储类储类型型标识标识符符为为bdata,指,指内部可位内部可位寻寻址的址的16字字节节存存储储区(区(20H到到2FH),),数据数据类类型是可位型是可位寻寻址址变变量的数据量的数据类类型 (2) BDATA区区以下是在BDATA区中声明的位变量和使用位变量的例子: unsigned char bdata status_byte; unsigned int bdata status_word; unsigned long bdata status_dword; sbit stat_flag=status_byte^4; if(status_word^15) {…} stat_flag=1;(3)IDATA区idata区也可以存放使用比区也可以存放使用比较频较频繁的繁的变变量,使用寄存器作量,使用寄存器作为为指指针进针进行行寻寻址。
址idata区声明中的存区声明中的存储类储类型型标识标识符符为为idata,指内部的,指内部的256字字节节的存的存储储区,区,但是只能但是只能间间接接寻寻址,速度比直接址,速度比直接寻寻址慢声明声明举举例如下:例如下:unsigned char idata system_status=0;unsigned int idata unit_id[2];char idata inp_string[16];float idata out_value;pdata区和区和xdata区属于外部数据存区属于外部数据存储区,外部数据区是可区,外部数据区是可读可写的可写的存存储区,最多可以有区,最多可以有64KB在在这两个区,两个区,变量的声明与在其他区的量的声明与在其他区的语法是一法是一样的,但的,但pdata区只区只有有256字字节而而xdata区可达区可达65 536字字节声明举例如下:unsigned char xdata system_status=0;unsigned int pdata unit_id[2] ;char xdata inp_string[16] ;float pdata out_value;外部地址段中除了包含存外部地址段中除了包含存储储器地址外,器地址外,还还包含包含I/O器件的地址器件的地址。
对对外部器件外部器件寻寻址可以通址可以通过过指指针针或或C51提供的宏,使用宏提供的宏,使用宏对对外部器件外部器件I/O口口进进行行寻寻址更具可址更具可读读性((5)程序存)程序存储储区区CODE 程序存程序存储储区的数据是不可改区的数据是不可改变变的,跳的,跳转转向量和状向量和状态态表表对对code段段访问访问和和对对xdata区区访问访问的的时间时间是一是一样样的编译编译的的时时候要候要对对程序存程序存储储区中的区中的对对象象进进行初始行初始化,否化,否则则就会就会产产生生错误错误程序存储储区区code声明的声明的标标识识符符为为code,在,在C51语语言言编译编译器中可以用器中可以用code存存储储区区类类型型标识标识符来符来访问访问程序存程序存储储区下面是程序存区下面是程序存储储区声明的例子:区声明的例子:unsigned char code a[ ]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15};变量存储类型定义举例:char data var1;bit bdata flags;float idata x,y,z;unsigned int pdata dimension;unsigned char xdata vector[10][4][4];3.1.4 局部局部变变量与全局量与全局变变量量 从从变变量的作用范量的作用范围围来区分,来区分,变变量可以被分量可以被分为为全局全局变变量和局部量和局部变变量量;; 某些某些变变量在程序运行量在程序运行过过程中是始程中是始终终存在的存在的---全局全局变变量量。
某些某些变变量只是在量只是在进进入某个函数入某个函数时时才开始存在才开始存在---局部局部变变量1.局部变量局部局部变变量量是在某个函数中存在的是在某个函数中存在的变变量,也可以称量,也可以称为为内部内部变变量,它只在量,它只在该该函数内部有效函数内部有效局部局部变变量可以分量可以分为为动态动态局部局部变变量量和和静静态态局部局部变变量量,使用关,使用关键词键词auto定定义义动态动态局部局部变变量(量(auto可以省略),使用关可以省略),使用关键词键词static定定义义静静态态局部局部变变量,量,例如例如::auto int a;static unsigned char j;动态局部局部变量量在程序在程序执行完行完毕后其存后其存储空空间被被释放,而放,而静静态局部局部变量量在在程序程序执行完成后其存行完成后其存储空空间并不并不释放,而且其放,而且其值保持不保持不变如果如果该函数再次被函数再次被调用,用,则该函数初始化后其初始函数初始化后其初始值为上次的数上次的数值动态局部局部变量和静量和静态局部局部变量的区量的区别如下:如下: 动态动态局部局部变变量在函数被量在函数被调调用用时时分配存分配存储储空空间间和和初始化,每次函数初始化,每次函数调调用用时时都需要初始化;静都需要初始化;静态态局部局部变变量在量在编译编译程序程序时时分配存分配存储储空空间间和初始化,和初始化,仅仅初始化一次。
初始化一次 动态动态局部局部变变量存放在量存放在动态动态存存储储区,在每次退出区,在每次退出所属函数所属函数时释时释放;静放;静态态局部局部变变量存放在静量存放在静态态存存储储区,每次区,每次调调用后函数不用后函数不释释放,保持函数放,保持函数执执行行完完毕毕之后的数之后的数值值到下一次到下一次调调用 如果在建立如果在建立时动态时动态局部局部变变量不初始量不初始为为一个不确一个不确定的数,静定的数,静态态局部局部变变量不初始化,量不初始化,则则它它们们的的值值为为0或者是空字符或者是空字符2.全局.全局变变量量 全局全局变变量是在整个源文件中都存在的量是在整个源文件中都存在的变变量,又称量,又称为为外部外部变变量全局变变量的有效区量的有效区间间是从定是从定义义点开始到源文件点开始到源文件结结束,其中的所有函数都可束,其中的所有函数都可以直接以直接访问该变访问该变量,如果定量,如果定义义点之前的函数需要点之前的函数需要访问该变访问该变量,量,则则需要需要使用使用extern关关键词对该变键词对该变量量进进行声明,如果全局行声明,如果全局变变量声明文件之外的量声明文件之外的源文件需要源文件需要访问该变访问该变量,也需要使用量,也需要使用extern关关键词进键词进行声明。
行声明全局变量有以下特点: 全局全局变量是整个文件都可以量是整个文件都可以访问的的变量,可以用于在函数之量,可以用于在函数之间共享共享大量的数据,存在周期大量的数据,存在周期长,在程序,在程序编译时就存在,如果两个函数需要就存在,如果两个函数需要在不互相在不互相调用用时共享数据,共享数据,则可以使用全局可以使用全局变量量进行参数行参数传递;; C51语言程序的函数只支持一个函数返回言程序的函数只支持一个函数返回值,如果一个函数需要返回,如果一个函数需要返回多个多个值,除了使用指,除了使用指针外,外,还要使用全局要使用全局变量;量; 使用全局使用全局变量量进行参数行参数传递可以减少从可以减少从实际参数向形式参数参数向形式参数传递时所必需的堆所必需的堆栈操作;操作; 在一个文件中,如果某个函数的局部在一个文件中,如果某个函数的局部变量和全局量和全局变量同名,量同名,则在在这个局部个局部变量的作用范量的作用范围内局部内局部变量不起作用,全局量不起作用,全局变量起作用;量起作用; 全局全局变量一直存在,占用了大量的内存量一直存在,占用了大量的内存单元,并且加大了程序的耦元,并且加大了程序的耦合性,不利于程序的移植或复用。
合性,不利于程序的移植或复用 静静态态局部局部变变量的作用范量的作用范围仅仅围仅仅是在定是在定义义的函数内,不的函数内,不能被其他的函数能被其他的函数访问访问,全局,全局变变量的作用范量的作用范围围是整个程序,是整个程序,静静态态全局全局变变量的作用范量的作用范围围是是该变该变量定量定义义的文件;的文件; 静静态态局部局部变变量是在函数内部定量是在函数内部定义义,全局,全局变变量是在所有量是在所有函数外定函数外定义义;; 静静态态局部局部变变量量仅仅仅仅在第在第1次次调调用用时时被初始化,再次被初始化,再次调调用用时时使用上次使用上次调调用用结结束束时时的数的数值值,全局,全局变变量在程序运行量在程序运行时时建立,建立,值为值为最近一条最近一条访问该访问该全局全局变变量的量的语语句句执执行的行的结结果 另外,另外,main函数函数虽虽然是然是.c文件的主文件,但也是一个文件的主文件,但也是一个函数,在其内部定函数,在其内部定义义的的变变量也属于局部量也属于局部变变量全局变变量量一般在一般在.c文件的开始部分定文件的开始部分定义义或在或在.h文件中定文件中定义义,由,由.c文件引用。
文件引用C51语语言程序多使用全局言程序多使用全局变变量量传递传递参数,因参数,因为这样为这样可以降低程序可以降低程序处处理的理的难难度,加快程序度,加快程序执执行的速度,行的速度,提高程序的提高程序的时时效性3.2 C51对单对单片机片机资资源的控制源的控制3.2.1 特殊功能寄存器的特殊功能寄存器的C51语语言定言定义义3.2.2 绝对绝对地址的地址的访问访问3.2.3 位位变变量的量的C51语语言定言定义义3.2.1 特殊功能寄存器的特殊功能寄存器的C51定定义义21个特殊功能寄存器两种方式:个特殊功能寄存器两种方式:1.使用关.使用关键键字字sfr定定义义 sfr 特功器名字特功器名字=特功器地址特功器地址; sfr SCON=0x98; /*串口控制寄存器地址串口控制寄存器地址98H*/ sfr TMOD=0X89; /*定定时时器器/计计数器方式控制寄存器地址数器方式控制寄存器地址9H*/2.通.通过头过头文件文件访问访问SFR#include
口可以有两种方式:可以有两种方式:用用#include<>可使用其中声明的宏来可使用其中声明的宏来访问绝对地址,地址, DBYTE以字以字节形式形式对data区区寻址;址; DWORD以字形式以字形式对data区区寻址;址; XBYTE以字以字节形式形式对xdata区区寻址;址; XWORD以字形式以字形式对xdata区区寻址;址;另外:另外: CBYTE以字以字节形式形式对code区区寻址;址; CWORD以字形式以字形式对code区区寻址;址; PBYTE以字以字节形式形式对pdata区区寻址;址; PWORD以字形式以字形式对pdata区区寻址例例3-5( P61 )#include <> #define PA XBYTE[0xffec]//将将PA定定义为义为外部外部I/O口,地址口,地址为为0xffec#define NRAM DBYTE[0x40]/*将将NRAM定定义为义为片内片内RAM,地址,地址为为40H,,长长度度为为8位位*/ void main( ){PA=0x3A;NRAM=0x01; }#include<>#define PORTA XBYTE[0xFFC0]/*将将PORT定定义为外部外部I/O口,地址口,地址为0xFFC0,,长度度为8位位* */#define NRAM DBYTE[0x40]/*将将NRAM定定义为片内片内RAM,地址,地址为40H,,长度度为8位位* */例例3-6((P62)data unsigned char x1 _at_ 0x40;/*在在data区定义字节变量区定义字节变量x1,它的地址为它的地址为40H*/xdata unsigned int x2 _at_ 0x2000; /*在在xdata区定义字变量区定义字变量x2,它的地址为它的地址为2000H*/void main(void){x1=0xff;x2=0x1234H;...while(1); }可以使用关可以使用关键字字_at_对指定的存指定的存储器空器空间的的绝对地址地址进行行访问。
一般格式如下:一般格式如下:【【存存储类型型】】 数据数据类型符型符 变量名量名 _at_ 地址常数地址常数;3.2.3 位位变变量的量的C51语语言定言定义义1.位.位变变量的量的C51语语言定言定义义 采用关采用关键键字字bit进进行定行定义义例如: bit direction_bit;/* 将将direction_bit定定义为义为位位变变量量 */ bit lock_pointer;/* 将将lock_pointer定定义为义为位位变变量量 */ bit display_invers;/* 将将display_invers定定义为义为位位变变量量 */2.可位.可位寻寻址址对对象象 可位可位寻寻址址对对象指可以字象指可以字节节或位或位寻寻址的址的对对象该对该对象象应应位于位于8051片内可位片内可位寻寻址址RAM区中,区中,C51语语言言编译编译器允器允许许数据数据类类型型为为idata的的对对象放入象放入8051片内可位片内可位寻寻址址RAM区 位位变变量的存量的存储类储类型只能是型只能是bdata 在程序在程序设计时设计时,,对对于可位于可位寻寻址的址的对对象,即可以字象,即可以字节寻节寻址也可以位址也可以位寻寻址的址的变变量,但量,但其存其存储类储类型只能是型只能是bdata。
使用使用时应时应先先说说明字明字节变节变量的数据量的数据类类型和存型和存储类储类型,然后可使用型,然后可使用bit定定义义可独立可独立寻寻址址访问访问的的对对象位例如:例如:bdata int ibase; /* ibase定定义为bdata整型整型变量量**/bdata char bary[4]; /* bary定定义为bdata字符型数字符型数组**/sbit mybit0=ibase^0; /* mybit0定定义为ibase的第的第0位位* */sbit mybit15=ibase^15; /* mybit15定定义位位ibase的第的第15位位* */sbit Ary07=bary[0]^7; /* Ary07定定义为bary[0]的第的第7位位* */sbit Ary37=bary[3]^7; /*Ary37定定义为bary[3]的第的第7位位* */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~~313.3 C51的基本运算与流程控制的基本运算与流程控制3.3.1 基本运算基本运算3.3.2 选择选择(分支)控制(分支)控制语语句句3.3.3 循循环结环结构流程控制构流程控制语语句句3.3.4 break语语句、句、continue语语句、句、goto语语句句3.3.1 基本运算(运算符)运算符运算符是表示特定的算是表示特定的算术术或或逻辑逻辑运算的符号,也称运算的符号,也称操作符操作符•把需要把需要进进行运算的各个量通行运算的各个量通过过运算符运算符连连接起来,便构成接起来,便构成表达式表达式•算算术术运算符、关系运算符、运算符、关系运算符、•逻辑逻辑运算符、位运算符、运算符、位运算符、•赋值赋值运算符、特殊运算符运算符、特殊运算符算算术运算的操作符:运算的操作符:+ (加法运算符)、(加法运算符)、- (减法运算符)(减法运算符)* * (乘法运算符)、(乘法运算符)、/ (除法运算符)(除法运算符)%% (模运算或取余运算符)(模运算或取余运算符)++为自增运算符自增运算符- -为自减运算符。
自减运算符注意:注意:/::结结果的整数部分;果的整数部分;%::结结果的余数部分;果的余数部分;-::除除进进行减法外,行减法外,还还可以可以进进行取行取负负操作表示自增表示操作数加操作数加1X++ 等同于等同于X=X+1X 表示先加表示先加1,再取,再取值值;;X++表示先取表示先取值值,再加,再加1例例3-8:自增和自减运算符的程序:自增和自减运算符的程序#include <>void main( ){ int x, y, z1, z2; x=10; y=21; z1=(x++)+(x++); printf(“x=%d, z1=%d\n”, x, z1); z2=(++y)+(++y); printf(“y=%d, z2=%d\n”, y, z2); }二、关系运算—成立或不成立主要用于比主要用于比较较操作数的大小关系操作数的大小关系包括:包括:< (小于)、(小于)、<= (小于等于)、(小于等于)、> (大于)、(大于)、>= (大于等(大于等于)、于)、= = (等于)、(等于)、!!= (不等于)(不等于)看看关系是否成立关系是否成立。
结结果:果:0或或1例3-9 关系运算符运算的程序示例#include <>void main( ){ int a, b, c, d; a=-2.3>0; b=71==32; c=7!=0; d=-12<=0; printf(“a=%d, b=%d, c=%d,d=%d\n”, a, b, c, d);}三、逻辑运算—结果是真或假进进行行逻辑逻辑运算的操作符包括:运算的操作符包括:&& ((逻辑逻辑与)、与)、|| ((逻辑逻辑或)、!(或)、!(逻辑逻辑非)非)看看结结果是否果是否为为真真结结果:果:0或或1例3-10 逻辑运算的程序示例#include <>void main( ){ int a, b, c, d, e ; a=!0 ; b=15&&22 ; c=35&&0 ; d=17.3||0 ; e=17.3||2.6 ;printf(“a=%d, b=%d,c=%d, d=%d, e=%d\n”, a, b, c, d, e);}四、位运算四、位运算将两个操作数按二将两个操作数按二进进制数展开,然后制数展开,然后对应对应位位进进行行逻辑逻辑运算。
包括:运算包括:&(按位与)、(按位与)、|(按位或)、(按位或)、^^(按位异或)、(按位异或)、~~(按位取反)、(按位取反)、<<(位左移)、(位左移)、>>(位右移)(位右移)位运算的操作位运算的操作对对象只能是整型和字符型数据象只能是整型和字符型数据这这些位运算和些位运算和汇编语汇编语言言中的位操作指令十分中的位操作指令十分类类似位操作指令是位操作指令是单单片机的重要特点,所以位运算在片机的重要特点,所以位运算在C51语语言控制言控制类类程序程序设计设计中的中的应应用比用比较较普遍例例3-11 位运算程序示例将位运算程序示例将A值循循环右移右移2位位main( )main( ){ {unsigned char a=0xc3,b,c;unsigned char a=0xc3,b,c;int n=2;int n=2;b=a<<(8-n);b=a<<(8-n);c=a>>n;c=a>>n;a=c|b;a=c|b;} }例3-12 位运算程序示例#include <>void main( ){ int a, b,c; a=23; b=217; c=a&b; printf(“a&b=%d\n”, c); c=a|b; printf(“a|b=%d\n”, c); c=a^b ; printf(“a^b=%d\n”, c); c=~a ; printf(“~a =%d\n”, c); c=a<<3 ; printf(“a<<3=%d\n”, c); c= b>>2 ; printf(“b>>2=%d\n”, c);}五、五、赋值赋值运算运算变变量名量名=表达式表达式;例如:例如:a=(b=4)+(c=6);该该表达式的表达式的值为值为10,,变变量量a的的值为值为10。
复合复合赋值运算符:运算符:赋值符号前加上其他运算符构成复合运算符符号前加上其他运算符构成复合运算符C51语言提供以言提供以下下10种复合运算符:种复合运算符:+=,,-=,,* *=,/,/=,%,%=,,﹠﹠=,,︱︱=,,^=,,<<=,,>>=例如:例如:a+=b; //等价于等价于a=(a+b)x*=a+b; //等价于等价于x=(x*(a+b))a&=b; //等价于等价于a=(a&b)a<<=4; //等价于等价于a=(a<<4)算术运算符、逻辑运算符、关系运算符、赋值运算符的优先级3.3.2 选择(分支)控制语句 通通过选择结过选择结构,可以使构,可以使计计算机具有决策能力,从而使算机具有决策能力,从而使计计算机能算机能够够按照按照我我们们的意志在的意志在某个特定条件下完成相某个特定条件下完成相应应的操作的操作,能,能够够“随机随机应变应变”包括:if语语句、句、switch语语句句一、IF语句 if语句用来判定所句用来判定所给定的条件是否定的条件是否满足,根据判定足,根据判定结果决定果决定执行行给出的两种操作之一出的两种操作之一。
if语句的基本句的基本结构如下:构如下: if(表达式表达式) { 语句句; }括号中的表达式成立括号中的表达式成立时,程序,程序执行大括号内的行大括号内的语句,句,否否则程序跳程序跳过大括号中的大括号中的语句部分而直接句部分而直接执行下面其他行下面其他语句C51语言提供言提供3种形式的种形式的if语句:句:形式一: IF(表达式){语句;}if(x>y){ max=x; min=y; }形式二: IF(表达式){语句1;} ELSE {语句2;}if(x>y) { max=x;}else { min=y;}形式三:if(表达式表达式1){语语句句1;}else if(表达式表达式2){语语句句2;}else if(表达式表达式3){语语句句3;}......else if(表达式表达式m){语语句句m;}else {语语句句n;}if(x>1000) { y=1; }else if(x>500) { y=2;}else if(x>300) { y=3;}else if(x>100) { y=4;}else{ y=5;}例3-13 分支编程示例#include<>main ( ){ int x,y; scanf("%d",&x); if(x<0) y=-1; else {if (x==0) y=0;else y=1; } printf("x=%%d,y=%%d\n",x,y);}例3-14:#include<>void main( ){ int a,b; a=200; b=321; if(a==b) {a++;b++; } printf("a=%d,b=%d\n",a,b);}例3-15:#include<>void main( ){ int a,b; a=12;b=21; if(a==b) { a++;b++; } { a--;b--;} printf("a=%d,b=%d\n",a,b);}例3-16:#include<>void main( ){ int score; char grade; score=45; if(score>=90) grade='A'; else if(score>=80) grade='B'; else if(score>=70) grade='C'; else if(score>=60) grade='D'; else grade='E'; printf("score=%d,grade=%c\n",score,grade);}二、SWITCH语句switch语语句是多分支句是多分支选择语选择语句一般形式如下:句一般形式如下:switch(表达式表达式){case 常量表达式常量表达式1:{语语句句1;} break;case 常量表达式常量表达式2:{语语句句2;} break;...case 常量表达式常量表达式n:{语语句句n;} break;default:{语语句句n+1;}}例3-173.3.3 循循环结环结构流程控制构流程控制语语句句四种形式:四种形式: if goto while do--while for一、基于IF和GOTO构成的循环 1、采用、采用if和和goto可以构成可以构成“当型当型”循循环环loop: if(表达式表达式) {语句语句;goto loop; }2、采用、采用if和和goto也可以构成也可以构成“直到型直到型”循循环环程序程序 loop: {语句语句;if(表达式表达式) goto loop; }3、、goto语语句句为为无条件无条件转转向向语语句句 goto 语语句句标标号号;二、WHILE while(表达式表达式) { 语语句句; }例:#include<>void main( ){ int i, s; i=100; s=0; while(i>0) { s=s+i; i=i-1; } printf(“1+2+…+100=%d\n”,s);}注意:注意:先判断,后先判断,后执执行;行;如果循如果循环环体内只有一个体内只有一个语语句,可以不用句,可以不用{ }While循循环环体体{ }后无分号;后无分号;三、DO-WHILEdo{ 语句语句; } while (表达式)(表达式);例:#include<>void main( ){ int i, s; i=100;s=0; do { s=s+i; i=i-1; } while(i>0); printf(“1+2+…+100=%d\n”,s);}注意:注意:先先执执行行, 后判断;后判断;如果循如果循环环体内只有一个体内只有一个语语句,可以不用句,可以不用{ }循循环环体体{ }后无分号;后无分号;while(表达式)后的分号不能省;表达式)后的分号不能省;四、FORfor(表达式表达式1;表达式表达式2;表达式表达式3){语语句句; }for(y=0;;y<=99;;y=y+3){delay(33); px=~~px;}例:#include<>void main( ){ int i, s; s=0; for(i=0;i<=100;i++) { s=s+i; } printf(“1+2+…+100=%d\n”,s);}注意:注意:3个表达式都是可个表达式都是可选项选项,可以任意省略,但,可以任意省略,但“;;”不能省。
不能省省省1是不是不对对循循环变环变量量赋赋初初值值;;省省2是不判断循是不判断循环环条件的真假;条件的真假;省省3是不是不对对循循环变环变量操作for( ; ;)表示无限循表示无限循环环无限循环的实现: ((1))for(; ;){ 代代码码段;段;}((2))while(1) { 代代码码段;段; }((3))do{ 代代码码段;段; } while((1););3.3.4 BREAK语语句、句、CONTINUE语语句、句、GOTO语语句句在循在循环语环语句句执执行行过过程中,程中, 如果需要在如果需要在满满足循足循环环判定条件的情况下跳出代判定条件的情况下跳出代码码段,可以使用段,可以使用break或或continue语语句;句; 如果要从任意地方跳如果要从任意地方跳转转到代到代码码的某个地方,可以使用的某个地方,可以使用goto语语句1、BREAKbreak语句用于从循句用于从循环代代码中退出,然后中退出,然后执行循行循环语句之后的句之后的语句,句,不再不再进入循入循环 形式: break;;注意:注意:一个一个break只能跳出一只能跳出一层循循环例:#include<>void main( ){ int i, s; i=0; s=0; while(1) { s=s+iI; i++; if(i>100) break; } printf(“1+2+…+100=%d\n”,s);}2、CONTINUE continue语语句用于退出当前循句用于退出当前循环环,不再,不再执执行本行本轮轮循循环环,程序代,程序代码码从下一从下一轮轮循循环环开始开始执执行,直到判断条件不行,直到判断条件不满满足足为为止。
止与与break的区的区别别是是该语该语句不是退出整个循句不是退出整个循环环形式: continue;例:例:#include<>void main( ){ char ch[ ]={‘a’,’ B’,’c’,’D’,’e’,’F’}; int i=-1; while(i<5) { if ( ch[i]>=‘a’&& ch[i]<=‘z’) continue; printf(“ch[%d]=%c\n”, i, char[i] ); }}3、GOTO goto是一个无条件是一个无条件转转移移语语句当执执行行goto语语句句时时,将程序指,将程序指针针跳跳转转到到goto给给出出的下一条代的下一条代码码,基本格式如下:,基本格式如下: goto 标标号号;例:例:void main(void){unsigned char counter;int sum ; sum=0;sumadd: sum=sum+counter; counter++; if(counter<101) {goto sumadd; }}3.4 C51的数组与指针 C51语语言的构造数据言的构造数据类类型主要有数型主要有数组组、指、指针针和和结结构等。
在构等在单单片机系片机系统统中,数中,数组组的的应应用比用比较较广泛,指广泛,指针则针则次之,次之,结结构用的相构用的相对较对较少这这里我里我们们只只讨论讨论数数组组和指和指针针3.4.1 数组数数组是同是同类型型变量的一个有序集合量的一个有序集合 数数组用一个名字来用一个名字来标识,称,称为数数组名数数组中的每个中的每个变量称量称为数数组元素数数组有一有一维、二、二维、三、三维和多和多维数数组之分C51语言中常用的一言中常用的一维、二、二维数数组和字符数和字符数组数数组中各元素的中各元素的顺序用下序用下标表示,下表示,下标为N的元素可以表示的元素可以表示为数数组名名[N]改改变[ ]中的下中的下标就可以就可以访问数数组中所有的元素中所有的元素1.一维数组 类类型型说说明符明符 数数组组名名[元素个数元素个数]; int demo1[10];初始化:初始化: int a[5]={1,2,3,4,5}; int b[6]={1,2,6}; 例3-23:2.二维数组或多维数组类类型型说说明符明符 数数组组名名[行数行数][列数列数];float demo2[3][4];//demo2 数数组组有有3 行行4 列共列共12 个个实实型元素型元素int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};//全部初始化全部初始化3.字符数组若一个数若一个数组的元素是字符型的,的元素是字符型的,则该数数组就是一个字符数就是一个字符数组。
例如:例如: char a[12]={"Chong Qing"};//字符数字符数组 char add[3][6]={"weight","height","width"};//字符串数字符串数组4.查表#define uchar unsigned charuchar code tempt[]={32,34,36,37,39,41};/*数数组组,设设置在置在EPROM中中,长长度度为实际输为实际输入的数入的数值值数数 */uchar ftoc(uchar degc){return tempt[degc];}void main( ){uchar x;x=ftoc(5);/* 得到与得到与5℃℃相相应应的的华华氏温度氏温度值值 */}共阴极共阴极LED的的显显示字符段示字符段码码表表 char code SEG[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};3.5 C51函数函数是指能函数是指能够执够执行特定功能和任行特定功能和任务务的程序代的程序代码码段 一个完整的一个完整的C51程序是由一个主函数和若干个其他函程序是由一个主函数和若干个其他函数数组组成。
成 主函数是主函数是main( )函数有且只有一个函数有且只有一个main( )函数使用函数时注意:函数数目不限制;函数数目不限制; main( )函数是主函数,可以函数是主函数,可以调用其他函数,而不允用其他函数,而不允许被其他函数被其他函数调用除主函数外,其他函数之除主函数外,其他函数之间允允许互相互相调用一、函数分类可以从不同的角度分可以从不同的角度分类类::((1)有无返回)有无返回值值角度角度((2)数据)数据传传送角度送角度((3)函数定)函数定义义角度角度(1)有无返回值角度无返回无返回值函数、有返回函数、有返回值函数函数无返回无返回值函数函数::执行完成后不向主行完成后不向主调函数返回函数函数返回函数值类型型说明符明符为::void有返回有返回值函数函数::执行完成后向主行完成后向主调函数返回一个函数返回一个执行的行的结果果—返回返回值((2)数据)数据传传送角度送角度有参函数和无参函数有参函数和无参函数无参函数:无参函数:主主调调函数和被函数和被调调函数之函数之间间不不进进行参数的行参数的传递传递有参函数:有参函数:主主调调函数和被函数和被调调函数之函数之间间存在参数的存在参数的传递传递。
形式参数形式参数和和实际实际参数参数((3)函数定)函数定义角度角度主函数、自定主函数、自定义函数、函数、库函数函数自定自定义函数:函数:是用是用户根据自己的需要而根据自己的需要而编写的函数从函数定写的函数从函数定义的的形式上可以将其划分无参函数、有参函数和空函数形式上可以将其划分无参函数、有参函数和空函数 无参函数无参函数 有参函数有参函数 空函数空函数二、函数定义有参函数和无参函数定有参函数和无参函数定义义1)无参函数的定)无参函数的定义义方法方法—P60无参函数的定无参函数的定义义形式形式为为::返回返回值类值类型型标识标识符符 函数名函数名( ){函数体函数体;}无参函数一般不无参函数一般不带带返回返回值值,因此函数返回,因此函数返回值类值类型型标识标识符可以省略符可以省略2)有参函数的定)有参函数的定义方法方法有参函数的定有参函数的定义形式形式为::P61返回返回值类型型标识符符函数名函数名(形式参数列表形式参数列表)形式参数形式参数说明;明;{函数体函数体;}函数定函数定义举义举例:例:#include<>int max(x1,x2)int x1,x2;{ if(x1>x2) return x1; else return x2; }void main( ){ int x1=17;x2=9; printf(“x1=%d,x2=%d”,x1,x2); printf(“max(x1,x2)=%d\n”,max(x1,x2)); }在程序中定义函数应注意:(1)可将形参可将形参类类型型说说明放在形参列表中,如:明放在形参列表中,如:int max(int x1,int x2){……..}(2)函数位置与声明函数位置与声明3.5.2 中断函数中断函数函数函数类类型型 函数名函数名 interrupt n using n3.6 C51的的预处预处理命令理命令 C51语语言中提供了各种言中提供了各种预处预处理命令,其作用理命令,其作用类类似于似于汇汇编编程序中的程序中的伪伪指令。
指令 预处预处理命令通常只理命令通常只进进行一些符号的行一些符号的处处理,并不理,并不执执行具行具体的硬件操作体的硬件操作C51的的预处预处理命令包括文件包含命令、理命令包括文件包含命令、宏定宏定义义指令条件指令条件编译编译指令预处预处理命令前要加一个理命令前要加一个“#”3.6.1 文件包含文件包含#include<文件名文件名> 或或 #include "文件名文件名“#include ” ” //引用自定引用自定义文件文件myfile#include <>//引用引用库函数文件函数文件stdio#include
引入源文件 一个一个#include命令只能指定一个被包含文件,命令只能指定一个被包含文件,如果程序中需要包含多个文件如果程序中需要包含多个文件则则需要使用多个需要使用多个包含命令包含命令 采用采用<文件名文件名>格式格式时时,在,在头头文件目文件目录录中中查查找指找指定文件,采用定文件,采用"文件名文件名"格式格式时时,在当前目,在当前目录录中中查查找指定文件找指定文件 #include命令末尾不需要分号命令末尾不需要分号“;;”结结束 #include命令只能命令只能调调入入ASCII文本文件文本文件3.6.2 宏定义指令1..简单简单的宏定的宏定义义简单简单的宏定的宏定义义格式格式为为::#define 宏替宏替换换名名 宏替宏替换换体体3.6.3 条件条件编译编译1..#if型型格式如下:格式如下:#if 常量表达式常量表达式代代码码1;#else代代码码2;#endif。
