蚕丝蛋白面膜多少钱:Keil C51语言的用法介绍

来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 16:10:23
Keil C51语言的用法介绍-4强制类型转换运算符
        1.变量赋值时发生的隐式转换,“=”号右边的表达式的数据类型转换成左边变量的数据类型。如把浮点数赋值给整形变量,小数部分将丢失。
       2.所有 char 型的操作数转换成 int型。
       3.两个具有不同数据类型的操作数用运算符连接时,隐式转换会按以下次序进行:如有一操作数是 float 类型,则另一个操作数也会转换成float类型;如果一个操作数为long类型,另一个也转换成long;如果一个操作数是unsigned 类型,则另一个操作会被转换成unsigned 类型。
从上面的规则可以大概知道有那几种数据类型是可以进行隐式转换的。在C51中只有char, int, long及float这几种基本的数据类型可以被隐式转换。而其它的数据类型就只能用到显示转换。要使用强制转换运算符应遵循以下的表达形式:
    (类型) 表达式
用显示类型转换来处理不同类型的数据间运算和赋值是十分方便和方便的, 特别对指针变量赋值是很有用的。
表达式语句
       C语言是一种结构化的程序设计语言。C语言提供了相当丰富的程序控制语句。学习掌握这些语句的用法也是C语言学习中的重点。
表达式语句是最基本的一种语句。不同的程序设计语言都会有不一样的表达式语句,如VB就是在表达式后面加入回车就构成了VB的表达式语句,而在51单片机的C语言中则是加入分号“;”构成表达式语句。举例如下:
    b = b * 10;
    Count++;
    X = A;Y = B;
    Page = (a+b)/a-1;
以上的都是合法的表达式语句。
在 C 语言中有一个特殊的表达式语句,称为空语句,它仅仅是由一个分号“;”组成。有时候为了使语法正确,那么就要求有一个语句,但这个语句又没有实际的运行效果那么这时就要有一个空语句。空语句通常用会以下两种用法。
         (1)while,for 构成的循环语句后面加一个分号,形成一个不执行其它操作的空循环体。我会常常用它来写等待事件发生的程序。要注意的是“;”号作为空语句使用时,要与语句中有效组成部分的分号相区分,如 for (;a<50000;a++);第一个分号也应该算是空语句,它会使a赋值为0(但要注意的是如程序前有a值,则a的初值为a的当前值),最后一个分号则使整个语句行成一个空循环。
        (2)在程序中为有关语句提供标号,标记程序执行的位置,使相关语句能跳转到要执行的位置。这会用在 goto语句中。
复合语句
       在C中括号的分工较为明显,{}号是用于将若干条语句组合在一起形成一种功能块,这种由若干条语句组合而成的语句就叫复合语句。复合语句之间用{}分隔, 而它内部的各条语句还是需要以分号 “;”结束。复合语句是允许嵌套的,也是就是在{}中的{}也是复合语句。复合语句在程序运行时,{}中的各行单语句是依次顺序执行的。C语言中可以将复合语句视为一条单语句,也就是说在语法上等同于一条单语句。对于一个函数而言,函数体就是一个复合语句,也许大家会因此知道复合语句中不单可以用可执行语句组成,还可以用变量定义语句组成。要注意的是在复合语句中所定义的变量,称为局部变量,所谓局部变量就是指它的有效范围只在复合语句中,而函数也算是复合语句,所以函数内定义的变量有效范围也只在函数内部。
条件语句
      条件语句又被称为分支语句,也有人会称为判断语句,其关键字是由if构成,这大众多的高级语言中都是基本相同的。C语言提供了3种形式的条件语句:
      1: if (条件表达式) 语句
当条件表达式的结果为真时,就执行语句,否则就跳过。 如 if (a==b) a++; 当a 等于 b 时,a 就加 1
      2: if (条件表达式) 语句 1
       else 语句 2
当条件表达式成立时,就执行语句 1,否则就执行语句 2 。如
if (a==b)
a++;
       else
a--;
当 a 等于b时,a 加1,否则 a-1。
        3:if (条件表达式1) 语句1
         else if (条件表达式 2) 语句 2
         else if (条件表达式 3) 语句 3
         else if (条件表达式 m) 语句 n
         else 语句m
         这是由 if else 语句组成的嵌套,用来实现多方向条件分支,使用应注意 if 和 else的配对使用,要是少了一个就会语法出错,记住 else 总是与最临近的 if 相配对。
开关语句
        用多个条件语句可以实现多方向条件分支,但是可以发现使用过多的条件语句实现多方向分支会使条件语句嵌套过多,程序冗长,这样读起来也很不好读。这时使用开关语句同样可以达到处理多分支选择的目的,又可以使程序结构清晰。它的语法为下:
    switch (表达式)
    {
     case 常量表达式1: 语句1; break;
     case 常量表达式2: 语句2; break;
     case 常量表达式3: 语句3; break;
     case 常量表达式n: 语句n; break;
     default: 语句
    }
       运行中switch后面的表达式的值将会做为条件,与case后面的各个常量表达式的值相对比,如果相等时则执行case后面的语句,再执行break(间断语句)语句,跳出switch语句。如果case后没有和条件相等的值时就执行default 后的语句。当要求没有符合的条件时不做任何处理,则可以不写default 语句。
循环语句
        循环语句是几乎每个程序都会用到的,它的作用就是用来实现需要反复进行多次的操作。如一个12M的51芯片应用电路中要求实现1毫秒的延时,那么就要执行1000 次空语句才可以达到延时的目的(当然可以使用定时器来做,这里就不讨论),如果是写1000条空语句那是多么麻烦的事情,再者就是要占用很多的存储空间。我们可以知道这1000条空语句,无非就是一条空语句重复执行1000次,因此我们就可以用循环语句去写,这样不但使程序结构清晰明了,而且使其编译的效率大大的提高。在C语言中构成循环控制的语句有while, do-while, for和goto语句。同样都是起到循环作用,但具体的作用和用法又大不一样。
    goto 语句
        它是一个无条件的转向语句,只要执行到这个语句,程序指针就会跳转到goto后的标号所在的程序段。它的语法如下:
    goto 语句标号;
    其中的语句标号为一个带冒号的标识符。
while 语句
         while 语句的意思很容易理解,在英语中它的意思是“当…的时候…” ,在这里我们可以理解为“当条件为真的时候就执行后面的语句” ,它的语法如下:
    while (条件表达式) 语句;
        使用 while语句时要注意当条件表达式为真时,它才执行后面的语句,执行完后再次回到 while 执行条件判断, 为真时重复执行语句, 为假时退出循环体。当条件一开始就为假时,那么 while后面的循环体(语句或复合语句)将一次都不执行就退出循环。
do while 语句
       do while语句可以说是while语句的补充, while是先判断条件是否成立再执行循环体,而do while则是先执行循环体,再根据条件判断是否要退出循环。这样就决定了循环体无论在任何条件下都会至少被执行一次。它的语法如下:
    do 语句 while (条件表达式)
for 语句:

       在明确循环次数的情况下,for语句比以上说的循环语句都要方便简单。它的语法如下:
    for ([初值设定表达式];[循环条件表达式];[条件更新表达式])语句中括号中的表达式是可选的,这样for语句的变化就会很多样了。for语句的执行:先代入初值,再判断条件是否为真,条件满足时执行循环体并更新条件,再判断条件是否为真……直到条件为假时,退出循环。
continue 语句:
        continue 语句是用于中断的语句,通常使用在循环中,它的作用是结束本次循环,跳过循环体中没有执行的语句,跳转到下一次循环周期。语法为:
    continue;
        continue 同时也是一个无条件跳转语句,但功能和前面说到的 break 语句有所不同,continue 执行后不是跳出循环,而是跳到循环的开始并执行下一次的循环。
    return 语句:
        return 语句是返回语句,是用于结束函数的执行,返回到调用函数时的位置。语法有二种:
    return (表达式);
    return;
        语法中因带有表达式,返回时先计算表达式,再返回表达式的值。不带表达式则返回的值不确定。
函数
① 函数的定义
        通常C语言的编译器会自带标准的函数库,这些都是一些常用的函数,Keil C中也不例外。标准函数已由编译器软件商编写定义,使用者直接调用就可以了,而无需定义。但是标准的函数不足以满足使用者的特殊要求,因此C语言允许使用者根据需要编写特定功能的函数,要调用它必须要先对其进行定义。定义的模式如下:
函数类型 函数名称(形式参数表)

函数体

        函数类型是说明所定义函数返回值的类型。返回值其实就是一个变量,只要按变量类型来定义函数类型就行了。如函数不需要返回值函数类型可以写作“void”表示该函数没有返回值。注意的是函数体返回值的类型一定要和函数类型一致,否则会造成错误。函数名称的定义在遵循C语言变量命名规则的同时,不能在同一程序中定义同名的函数这将会造成编译错误(同一程序中是允许有同名变量的,因为变量有全局和局部变量之分)。形式参数是指调用函数时要传入到函数体内参与运算的变量,它可以有一个、几个或没有,当不需要形式参数也就是无参函数,括号内可以为空或写入“void”表示,但括号不能少。函数体中可以包含有局部变量的定义和程序语句,如函数要返回运算值则要使用return语句进行返回。在函数的{}号中也可以什么也不写,这就成了空函数,在一个程序项目中可以写一些空函数,在以后的修改和升级中可以方便的在这些空函数中进行功能扩充。
② 函数的调用
       函数定义好以后,要被其它函数调用了才能被执行。C 语言的函数是可以相互调用的,但在调用函数前,必须对函数的类型进行说明,就算是标准库函数也不例外。标准库函数的说明会被按功能分别写在不同的头文件中,使用时只要在文件最前面用#include 预处理语句引入相应的头文件。调用就是指一个函数体中引用另一个已定义的函数来实现所需要的功能,这时函数体称为主调用函数,函数体中所引用的函数称为被调用函数。一个函数体中可以调用数个其它的函数,这些被调用的函数同样也可以调用其它函数,也可以嵌套调用。调用函数的一般形式如下:
    函数名 (实际参数表)
    “函数名”就是指被调用的函数。实际参数表可以为零或多个参数,多个参数时要用逗号隔开,每个参数的类型、位置应与函数定义时所的形式参数一一对应,它的作用就是把参数传到被调用函数中的形式参数,如果类型不对应就会产生一些错误。调用的函数是无参函数时不写参数,但不能省后面的括号。
    在以前的一些例子我们也可以看不同的调用方式:
1.函数语句
2.函数参数
    3.函数表达式
       前面说到调用函数前要对被调用的函数进行说明。标准库函数只要用#include引入已写好说明的头文件,在程序就可以直接调用函数了。如调用的是自定义的函数则要用如下形式编写函数类型说明:
类型标识符 函数的名称(形式参数表);
这样的说明方式是用在被调函数定义和主调函数是在同一文件中。 你也可以把这些写到文件名.h 的文件中用#include "文件名.h"引入。如果被调函数的定义和主调函数不是在同一文件中的,则要用如下的方式进行说明,说明被调函数的定义在同一项目的不同文件之上,其实库函数的头文件也是如此说明库函数的,如果说明的函数也可以称为外部函数。
    extern 类型标识符 函数的名称(形式参数表);
        函数的定义和说明是完全不同的,在编译的角度上看函数的定义是把函数编译存放在ROM的某一段地址上,而函数说明是告诉编译器要在程序中使用那些函数并确定函数的地址。如果在同一文件中被调函数的定义在主调函数之前,这时可以不用说明函数类型。也就是说在main函数之前定义的函数,在程序中就可以不用写函数类型说明了。可以在一个函数体调用另一个函数(嵌套调用),但不允许在一个函数定义中定义另一个函数。还要注意的是函数定义和说明中的“类型、形参表、名称”等都要相一致。
③ 中断函数
        中断服务函数是编写单片机应用程序不可缺少的。中断服务函数只有在中断源请求响应中断时才会被执行,这在处理突发事件和实时控制是十分有效的。例如:电路中一个按键,要求按键后LED点亮,这个按键何时会被按下是不可预知的,为了要捕获这个按键的事件,通常会有三种方法:一是用循环语句不断的对按键进行查询,二是用定时中断在间隔时间内扫描按键,三是用外部中断服务函数对按键进行捕获。在这个应用中只有单一的按键功能,那么第一种方式就可以胜任了,程序也很简单,但是它会不停的在对按键进行查询浪费了CPU的时间。实际应用中一般都会还有其它的功能要求同时实现,这时可以根据需要选用第二或第三种方式,第三种方式占用的 CPU时间最少,只有在有按键事件发生时,中断服务函数才会被执行,其余的时间则是执行其它的任务。
         C51语言扩展了函数的定义使它可以直接编写中断服务函数,你可以不必考虑出入堆栈的问题,从而提高了工作的效率。扩展的关键字是interrupt,它是函数定义时的一个选项,只要在一个函数定义后面加上这个选项,那么这个函数就变成了中断服务函数。在后面还可以加上一个选项using,这个选项是指定选用益统单片机内部4组工作寄存器中的哪个组。初学者可以不必去做工作寄存器设定,而由编译器自动选择,避免产生不必要的错误。定义中断服务函数时可以用如下的形式。
       函数类型 函数名 (形式参数) interrupt n [using n]
    interrupt关键字是不可缺少的,由它告诉编译器该函数是中断服务函数,并由后面的n 指明所使用的中断号。n的取值范围为 0-31,但具体的中断号要取决于芯片的型号,像益统新款单片机实际上就使用0-4号中断。每个中断号都对应一个中断向量,具体地址为8n+3,中断源响应后处理器会跳转到中断向量所处的地址执行程序,编译器会在这地址上产生一个无条件跳转语句,转到中断服务函数所在的地址执行程序。下表5是益统芯片的中断向量和中断号。

中断号

中断源

中断向量

0

外部中断

0003H

1

定时器/计数器

000BH

2

外部中断

0013H

3

定时器/计数器

001BH

4

串行口

0023H

表5 益统芯片的中断向量和中断号
使用中断服务函数时应注意:中断函数不能直接调用中断函数;不能通过形参传速参数;在中断函数中调用其它函数,两者所使用的寄存器组应相同。
数组的使用
      数组不过就是同一类型变量的有序集合。形象的可以这样去理解,就像一个学校在操场上排队,每一个级代表一个数据类型,每一个班级为一个数组,每一个学生就是数组中的一个数据。数据中的每个数据都可以用唯一的下标来确定其位置,下标可以是一维或多维的。就如在学校的方队中要找一个学生,这个学生在I年级H班X组Y号的,那么可以把这个学生看做在I类型的H数组中(X,Y)下标位置中。数组和普通变量一样,要求先定义了才可以使用,下面是定义一维或多维数组的方式:
    数据类型 数组名 [常量表达式];
    数据类型 数组名 [常量表达式 1]...... [常量表达式 N];
    “数据类型”是指数组中的各数据单元的类型,每个数组中的数据单元只能是同一数据类型。“数组名”是整个数组的标识,命名方法和变量命名方法是一样的。在编译时系统会根据数组大小和类型为变量分配空间,数组名可以说就是所分配空间的首地址的标识。“常量表达式”是表示数组的长度和维数,它必须用“[]”括起,括号里的数不能是变量只能是常量。
    unsigned int xcount [10]; //定义无符号整形数组,有10个数据单元
    char inputstring [5]; //定义字符形数组,有5个数据单元
    float outnum [10],[10]; //定义浮点型数组,有100个数据单元
在C语言中数组的下标是从0开始的而不是从1开始,如一个具有10个数据单元的数组count,它的下标就是从count[0]到count[9],引用单个元素就是数组名加下标,如count[1]就是引用count 数组中的第2个元素,如果错用了count[10]就会有错误出现了。还有一点要注意的就是在程序中只能逐个引用数组中的元素,不能一次引用整个数组,但是字符型的数组就可以一次引用整个数组。
        数组也是可以赋初值的。在上面介绍的定义方式只适用于定义在内存DATA存储器使用的内存,有的时候我们需要把一些数据表存放在数组中,通常这些数据是不用在程序中改变数值的,这时就要把这些数据在程序编写时就赋给数组变量。因为单片机的片内 RAM很有限,通常会把 RAM分给参与运算的变量或数组,而那些程序中不变数据则应存放在片内的CODE存储区,以节省宝贵的RAM。赋初值的方式如下:
        数据类型 [存储器类型] 数组名 [常量表达式] = {常量表达式};
数据类型 [存储器类型] 数组名 [常量表达式 1]...... [常量表达式 N]={{常量表达式}...{常量表达式 N}};
在定义并为数组赋初值时,初学的朋友往往会搞错初值个数和数组长度的关系,而致使编译出错。初值个数必须小于或等于数组长度,不指定数组长度则会在编译时由实际的初值个数自动设置。
unsigned char LEDNUM[2]={12,35}; //一维数组赋初值
int Key[2][3]={{1,2,4},{2,2,1}}; //二维数组赋初值
unsigned char IOStr[]={3,5,2,5,3}; //没有指定数组长度,编译器自动设置
    unsigned char code skydata[]={0x02,0x34,0x22,0x32,0x21,0x12}; //数据保存在 code 区
指针的使用
       指针就是指变量或数据所在的存储区地址。如一个字符型的变量STR存放在内存单元DATA区的51H这个地址中,那么DATA区的51H地址就是变量STR的指针。在C语言中指针是一个很重要的概念,正确有效的使用指针类型的数据,可以更有效的表达复杂的数据结构,可以更有效的使用数组或变量,可以方便直接的处理内存或其它存储区。指针之所以可以这么有效的操作数据,是因为无论程序的指令、常量、变量或特殊寄存器都要存放在内存单元或相应的存储区中,这些存储区是按字节来划分的,每一个存储单元都可以用唯一的编号去读或写数据,这个编号就是常说的存储单元的地址,而读写这个编号的动作就叫做寻址,通过寻址就可以访问到存储区中的任一个可以访问的单元,而这个功能是变量或数组等是不可能代替的。C语言也因此引入了指针类型的数据类型,专门用来确定其他类型数据的地址。用一个变量来存放另一个变量的地址,那么用来存放变量地址的变量称为“指针变量”。如用变量STRIP来存放文章开头的STR变量的地址51H,变量STRIP就是指针变量。
      变量的指针就是变量的地址,用取地址运算符‘&’取得赋给指针变量。&STR就是把变量STR的地址取得。用语句STRIP=&STR就可以把所取得的STR指针存放在STRIP指针变量中。STRIP的值就变为51H。可见指针变量的内容是另一个变量的地址,地址所属的变量称为指针变量所指向的变量。
要访问变量STR除了可以用‘STR’这个变量名来访问之外,还可以用变量地址来访问。方法是先用&STR 取变量地址并赋于STRIP指针变量,然后就可以用*STRIP 来对STR进行访问了。‘*’是指针运算符,用它可以取得指针变量所指向的地址的值。
    使用指针变量之前也和使用其它类型的变量那样要求先定义变量,而且形式也相类似,一般的形式如下:
       数据类型 [存储器类型] * 变量名;
        unsigned char xdata *pi    //指针会占用二字节,指针自身存放在编译器默认存储区,指向 xdata 存储区的 char类型
    unsigned char xdata * data pi; //除指针自身指定在data区,其它同上
       int * pi; //定义为一般指针,指针自身存放在编译器默认存储区,占三个字节
        在定义形式中“数据类型”是指所定义的指针变量所指向的变量的类型。“存储器类型”是编译器编译时的一种扩展标识,它是可选的。在没有“存储器类型”选项时,则定义为一般指针,如有“存储器类型”选项时则定义为基于存储器的指针。
指针变量最大的值为 0xFFFF,这样就决定了一般指针在内存会占用 3 个字节,第一字节存放该指针存储器类型编码,后两个则存放该指针的高低位址。而基于存储器的指针因为不用识别存储器类型所以会占一或二个字节, idata , data, pdata存储器指针占一个字节,code, xdata则会占二个字节。由上可知,明确的定义指针,可以节省存储器的开销,这在严格要求程序体积的项目中很有用处。  
结构、联合和枚举的使用
        为了更有效的处理更复杂的数据,C语言引入了构造类型的数据类型。构造类型就是将一批各种类型的数据放在一起形成一种特殊类型的数据。之前讨论过的数组也算是一种构造类型的数据,C51中的构造类型还有结构、枚举和联合。
结构:
结构是一种数据的集合体,它可以按需要将不同类型的变量组合在一起,整个集合体用一个结构变量名表示,组成这个集合体的各个变量称为结构成员。理解结构的概念,可以用班级和学生的关系去理解。班级名称就相当于结构变量名,它代表所有同学的集合,而每个同学就是这个结构中的成员。使用结构变量时,要先定义结构类型。一般定义格式如下:
struct 结构名 {结构元素表};
例子:struct FileInfo
{
   unsigned char FileName[4];
   unsigned long Date;
   unsigned int Size;
}
       上面的例子中定义了一个简单的文件信息结构类型,它可用于定义用于简单的单片机文件信息,结构中有三个元素,分别用于操作文件名、日期、大小。因为结构中的每个数据成员可以使用不同的数据类型,所以要对每个数据成员进行数据类型定义。定义好一个结构类型后,可以按下面的格式进行定义结构变量,要注意的是只有结构变量才可以参与程序的执行,结构类型只是用于说明结构变量是属于那一种结构。
struct 结构名 结构变量名1,结构变量名 2……结构变量 N;
例子:struct FileInfo NewFileInfo, OldFileInfo;
        通过上面的定义NewFileInfo和OldFileInfo都是FileInfo结构,都具有一个字符型数组一个长整型和一个整形数据。定义结构类型只是给出了这个结构的组织形式,它不会占用存储空间,也就说结构名是不能进行赋值和运算等操作的。结构变量则是结构中的具体成员,会占用空间,可以对每个成员进行操作。
枚举:
    在程序中经常要用到一些变量去做程序中的判断标志。 如经常要用一个字符或整型变量去储存1和0做判断条件真假的标志, 但我们也许会疏忽这个变量只有当等于 0或1才是有效的,而将它赋上别的值,而使程序出错或变的混乱。这时可以使用枚举数据类型去定义变量,限制错误赋值。枚举数据类型就是把某些整型常量的集合用一个名字表示,其中的整型常量就是这种枚举类型变量的可取的合法值。枚举类型的二种定义格式如下:
    enum 枚举名 {枚举值列表} 变量列表;
    例: enum TFFlag {False, True} TFF;
    enum 枚举名 {枚举值列表};
    emum 枚举名 变量列表;
联合
        联合同样是C语言中的构造类型的数据结构。它和结构类型一样可以包含不同类型的数据元素,所不同的是联合的数据元素都是从同一个数据地址开始存放。结构变量占用的内存大小是该结构中数据元素所占内存数的总和, 而联合变量所占用内存大小只是该联合中最长的元素所占用的内存大小。如在结构中定义了一个int和一个char,那么结构变量就会占用3个字节的内存,而在联合中同样定义一个int和一个char,联合变量只会占用2个字节。这种能充分利用内存空间的技术叫‘内存覆盖技术’ ,它可以使不同的变量分时的使用同一个内存空间。使用联合变量时要注意它的数据元素只能是分时使用,而不能同时使用。举个简单的例子,程序先为联合中的int 赋值1000,后来又为char赋值10,那么这时就不能引用int了,否则程序会出错,起作用的是最后一次赋值的元素,而上一次赋值的元素就失效了。使用中还要注意定义联合变量时不能对它的值初始化、可以使用指向联合变量的指针对其操作、联合变量不能作为函数的参数进行传递,数组和结构可以出现在联合中。
         联合类型变量的定义方法和结构的定义方法差不多,只要把关键字 struct 换用 union 就可以了。联合变量的引用方法除也是使用‘.’成员运算符。

为了您的安全,请只打开来源可靠的网址

打开网站    取消

来自: http://hi.baidu.com/jin%5Fhaiqing/blog/item/e4eb574697813b47500ffe04.html