第5章08C语言及第课件.ppt

上传人(卖家):晟晟文业 文档编号:5177689 上传时间:2023-02-16 格式:PPT 页数:49 大小:545.50KB
下载 相关 举报
第5章08C语言及第课件.ppt_第1页
第1页 / 共49页
第5章08C语言及第课件.ppt_第2页
第2页 / 共49页
第5章08C语言及第课件.ppt_第3页
第3页 / 共49页
第5章08C语言及第课件.ppt_第4页
第4页 / 共49页
第5章08C语言及第课件.ppt_第5页
第5页 / 共49页
点击查看更多>>
资源描述

1、第第5章章 08C语言及第一个语言及第一个08C工程工程l本章首先讲述了嵌入式中选用本章首先讲述了嵌入式中选用C语言编程的优越性,讲述嵌入语言编程的优越性,讲述嵌入式式C语言的编程方法,比较了语言的编程方法,比较了08C语言和标准语言和标准C的差异,然后阐的差异,然后阐述了述了08C的一些特殊用法,接下来通过实例讲述的一些特殊用法,接下来通过实例讲述08C语言编程框语言编程框架,最后结合我们的实际开发经验,总结了架,最后结合我们的实际开发经验,总结了08C中的一些编程中的一些编程技巧。技巧。l使用使用C语言进行嵌入式程序开发,它的编程方法和编程手段与语言进行嵌入式程序开发,它的编程方法和编程手

2、段与PC机上使用机上使用C语言还是有很大差别,只有对嵌入式体系结构和语言还是有很大差别,只有对嵌入式体系结构和硬件资源作详尽了解,才能写出高质量高效率的硬件资源作详尽了解,才能写出高质量高效率的C语言程序。语言程序。读者在实际学习过程中,要多加练习,从实际编程中体会嵌入读者在实际学习过程中,要多加练习,从实际编程中体会嵌入式的式的C语言编程方法。语言编程方法。5.1标准标准C语言的基本语法语言的基本语法 l C语言是在语言是在70年代初问世的。年代初问世的。1978年美国电话电报公司年美国电话电报公司(AT&T)贝尔贝尔实验室正式发表了实验室正式发表了C语言。同时由语言。同时由B.W.Kern

3、ighan和和D.M.Ritchit合著合著了著名的了著名的THE C PROGRAMMING LANGUAGE,简称为,简称为K&R,也有人称之为,也有人称之为K&R标准。但是,在标准。但是,在K&R中并没有定中并没有定义一个完整的标准义一个完整的标准C语言,后来由美国国家标准学会在此基础上制定语言,后来由美国国家标准学会在此基础上制定了一个了一个C语言标准,于语言标准,于1983年发表,通常称之为年发表,通常称之为ANSI C或标准或标准C。l 本节简要介绍本节简要介绍C语言的基本知识,特别是一些和单片机编程密切相语言的基本知识,特别是一些和单片机编程密切相关的基本知识,未学过标准关的基本

4、知识,未学过标准C语言的读者可以通过本节了解语言的读者可以通过本节了解C语言,语言,对于对于C语言很熟悉的读者,可以跳过本节。语言很熟悉的读者,可以跳过本节。5.1.1数据类型数据类型 C语言的数据类型有基本类型和构造类型两大类。基本数据类型如表5-1所示。注注:08C语言的double类型长度为4字节。构造类型构造类型有数组、结构、联合、枚举、指针和空类型。结构和联合是基本数据类型的组合。枚举是一个被命名为整型常量的集合。空类型字节长度为0,主要有两个用途:一是明确地表示一个函数不返回任何值;二是产生一个同一类型指针(可根据需要动态地分配给其内存)。表表5-1 C语言基本数据类型语言基本数据

5、类型数据类型数据类型简明含义简明含义位数位数字节数字节数值域值域signed char有符号字节型有符号字节型81-128+127unsigned char无符号字节型无符号字节型810255signed short有符号短整型有符号短整型162-32768+32767unsigned short无符号短整型无符号短整型162065535signed int有符号短整型有符号短整型162-32768+32767unsigned int无符号短整型无符号短整型162065535signed long有符号长整型有符号长整型324-2147483648+2147483647unsigned lon

6、g无符号长整型无符号长整型32404294967295float浮点型浮点型3243.4E-383.4E+38double双精度型双精度型6481.7E-3121.7E+312嵌入式系统学习嵌入式系统学习5.1.2 运算符运算符 C语言的运算符与大多数计算机语言基本相同,分为算术、逻辑、关系和位运算及语言的运算符与大多数计算机语言基本相同,分为算术、逻辑、关系和位运算及一些特殊的操作符。表一些特殊的操作符。表5-2列出了列出了C语言的部分运算符及使用方法举例。语言的部分运算符及使用方法举例。5.1.3 流程控制流程控制 在程序设计中主要有三种基本控制结构:顺序结构、选择结构和循环结在程序设计中

7、主要有三种基本控制结构:顺序结构、选择结构和循环结构。构。l(1)顺序结构顺序结构 顺序结构就是从前向后依次执行语句。从整体上看,所有程序的基本结顺序结构就是从前向后依次执行语句。从整体上看,所有程序的基本结构都是顺序结构,中间的某个过程可以是选择结构或循环结构。构都是顺序结构,中间的某个过程可以是选择结构或循环结构。l(2)选择结构选择结构 在大多数程序中都会包含选择结构。它的作用是,根据所指定的条件在大多数程序中都会包含选择结构。它的作用是,根据所指定的条件是否满足,决定从给定的两组操作选择其一。在是否满足,决定从给定的两组操作选择其一。在C语言中选择结构可语言中选择结构可以用两种语句来实

8、现:以用两种语句来实现:if语句和语句和switch语句。语句。l(3)循环结构循环结构 C语言中的循环结构常用语言中的循环结构常用for循环,循环,while循环与循环与do.while循环。循环。5.1.4 函数函数 所谓所谓函数函数,即子程序,也就是,即子程序,也就是“语句的集合语句的集合”,就是说把经,就是说把经常使用的语句群定义成函数,供其他程序调用,这样就可以避免重常使用的语句群定义成函数,供其他程序调用,这样就可以避免重复编写程序的麻烦,也可以缩短程序的长度。当一个程序太大时,复编写程序的麻烦,也可以缩短程序的长度。当一个程序太大时,建议将其中的一部分程序改成用函数的方式调用较好

9、,因为大程序建议将其中的一部分程序改成用函数的方式调用较好,因为大程序过于繁杂容易出错,而小程序容易调试,也易于阅读和修改。函数过于繁杂容易出错,而小程序容易调试,也易于阅读和修改。函数定义的一般形式如下所示:定义的一般形式如下所示:类型标识符类型标识符 函数名函数名(类型类型 参数参数1 1,类型,类型 参数参数2 2,类型,类型 参数参数3 3,)说明部分说明部分 语句语句(1)(1)使用函数的注意事项使用函数的注意事项函数定义时要同时声明其类型。函数定义时要同时声明其类型。调用函数前要先声明该函数。调用函数前要先声明该函数。传给函数的参数值,其类型要与函数原定义一致。传给函数的参数值,其

10、类型要与函数原定义一致。接收函数返回值的变量,其类型也要与函数类型一致。接收函数返回值的变量,其类型也要与函数类型一致。5.1.4 5.1.4 函数函数(2)(2)(2)(2)函数的声明函数的声明 void function1(void)void function1(void)此函数无返回值,也不传参数。此函数无返回值,也不传参数。void function2(unsigned char i,intvoid function2(unsigned char i,int j)j)此函数无返回值,但需要此函数无返回值,但需要unsigned char unsigned char 类型的参数类型的参数

11、i i和和intint类类型的参数型的参数j j。unsigned char function3(unsigned char i)unsigned char function3(unsigned char i)此函数有返回值此函数有返回值,其类型为其类型为unsigned charunsigned char。(3)(3)函数的返回值函数的返回值 returnreturn 表达式表达式;return return语句用来立即结束函数,并返回一确定给调用程序语句用来立即结束函数,并返回一确定给调用程序。如果函数的类型和。如果函数的类型和returnreturn语句中表达式的值不一致,则语句中表达式

12、的值不一致,则以函数类型为准。对数值型数据,可以自动进行类型转换以函数类型为准。对数值型数据,可以自动进行类型转换。即函数类型决定返回值的类型。即函数类型决定返回值的类型。5.1.5 指针指针指针是语言中广泛使用的一种数据类型,运用指针是语言最主指针是语言中广泛使用的一种数据类型,运用指针是语言最主要的风格之一。指针是一种特殊的数据类型,在其它语言中一般没有。要的风格之一。指针是一种特殊的数据类型,在其它语言中一般没有。指针是指向变量的地址,实质上指针就是存储单元的地址。根据所指指针是指向变量的地址,实质上指针就是存储单元的地址。根据所指的变量类型不同,可以是整型指针的变量类型不同,可以是整型

13、指针(intint *)、浮点型指针、浮点型指针(float float*)、字符型指针字符型指针(char char*)、结构指针、结构指针(structstruct *)和联合指针和联合指针(union union*)。(1)(1)指针变量的定义指针变量的定义其一般形式为:其一般形式为:类型说明符类型说明符 *变量名;变量名;其中,其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。型说明符表示本指针变量所指向的变量的数据类型。例如例如:intint *point_1;point_1;

14、表示表示point_1point_1是一个指向整型的指针变量,它的值是一个整型变量的是一个指向整型的指针变量,它的值是一个整型变量的地址。地址。5.1.55.1.5 指针指针(2)(2)(2)(2)指针变量的赋值指针变量的赋值指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体值。未指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体值。未经赋值的指针变量不能使用,否则将造成系统混乱,甚至死机。指针变量的经赋值的指针变量不能使用,否则将造成系统混乱,甚至死机。指针变量的赋值只能赋予地址。赋值只能赋予地址。指针变量初始化的方法指针变量初始化的方法int a;int a;i

15、ntint *point=&a;apoint=&a;a 给指针赋值的方法给指针赋值的方法int a;int a;intint *point;point;point=&a;point=&a;将数值赋给指针将导致错误,例如:将数值赋给指针将导致错误,例如:intint *point;point=1000;point;point=1000;是错误的。是错误的。被赋值的指针变量前不能再加被赋值的指针变量前不能再加“*”说明符,如写为说明符,如写为*point=&apoint=&a也是错误的。也是错误的。(3)(3)指针的运算指针的运算 取地址运算符取地址运算符&取地址运算符取地址运算符&是单目运算符,

16、其结合性为自右至左,其功能是取变量地址。是单目运算符,其结合性为自右至左,其功能是取变量地址。5.1.55.1.5 指针指针(3)(3)取内容运算符取内容运算符 *取内容运算符取内容运算符*是单目运算符,其结合性为自右至左,用来表示指针变量所指的是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在变量。在*运算符之后跟的变量必须是指针变量。运算符之后跟的变量必须是指针变量。注意:注意:指针运算符指针运算符*和指针变量说明中的指针说明符和指针变量说明中的指针说明符*并非相同。在指针变量说明并非相同。在指针变量说明中,中,“*”是类型说明符,表示其后的变量是指针类型。而表达式中出现的是

17、类型说明符,表示其后的变量是指针类型。而表达式中出现的“*”则是一个运算符用以表示指针变量所指的变量。则是一个运算符用以表示指针变量所指的变量。main()main()int a=5,int a=5,*point=&a;point=&a;printfprintf(%d,(%d,*point);point);表示指针变量表示指针变量pointpoint取得了整型变量取得了整型变量a a的地址。本语句表示输出变量的地址。本语句表示输出变量a a的值。的值。加减算术运算加减算术运算对于指向数组的指针变量,可以加上或减去一个整数对于指向数组的指针变量,可以加上或减去一个整数n n。设。设papa是指向

18、数组是指向数组a a的指的指针变量,则针变量,则pa+n,pa-n,pa+,+pa,pa-,-papa+n,pa-n,pa+,+pa,pa-,-pa运算都是合法的。指针变量加运算都是合法的。指针变量加或减一个整数或减一个整数n n的意义是把指针指向的当前位置的意义是把指针指向的当前位置(指向某数组元素指向某数组元素)向前或向后向前或向后移动移动n n个位置。个位置。5.1.55.1.5 指针指针(4)(4)注意:数组指针变量向前或向后移动一个位置和地址加注意:数组指针变量向前或向后移动一个位置和地址加1 1或减或减1 1在概念上是不同的在概念上是不同的。因为数组可以有不同的类型,各种类型的数组

19、元素所占的字节长度是不同。因为数组可以有不同的类型,各种类型的数组元素所占的字节长度是不同的。如指针变量加的。如指针变量加1 1,即向后移动,即向后移动1 1个位置表示指针变量指向下一个数据元素个位置表示指针变量指向下一个数据元素的首地址。而不是在原地址基础上加的首地址。而不是在原地址基础上加1 1。例如例如:intint a5,a5,*pa;pa;pa=a;pa=a;/*papa指向数组指向数组a a,也是指向,也是指向a0a0*/pa=pa+2;pa=pa+2;/*papa指向指向a2a2,即,即papa的值为的值为&pa2pa2*/指针变量的加减运算只能对数组指针变量进行,对指向其它类型

20、变量的指针变量指针变量的加减运算只能对数组指针变量进行,对指向其它类型变量的指针变量作加减运算是毫无意义的。作加减运算是毫无意义的。(4)void指针类型指针类型顾名思义,顾名思义,void*为为“无类型指针无类型指针”,即用来定义一个指针变量,不指定它是指,即用来定义一个指针变量,不指定它是指向哪一种类型数据,但可以把它强制转化成任何一种类型的指针。对于向哪一种类型数据,但可以把它强制转化成任何一种类型的指针。对于void*类型的指针变量不能进行取内容运算和加减算术运算,因为编译器不知道它类型的指针变量不能进行取内容运算和加减算术运算,因为编译器不知道它指向的具体类型。指向的具体类型。5.1

21、.55.1.5 指针指针(5)(5)众所周知,如果指针众所周知,如果指针p1和和p2的类型相同,那么我们可以直接在的类型相同,那么我们可以直接在p1和和p2间互相赋间互相赋值;如果值;如果p1和和p2指向不同的数据类型,则必须使用强制类型转换运算符把赋指向不同的数据类型,则必须使用强制类型转换运算符把赋值运算符右边的指针类型转换为左边指针的类型。值运算符右边的指针类型转换为左边指针的类型。例如例如:float*p1;int*p2;p1=(float*)p2;而而void*则不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换则不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换

22、:void*p1;int*p2;p1=p2;但这并不意味着,但这并不意味着,void*也可以无需强制类型转换地赋给其它类型的指针,也就也可以无需强制类型转换地赋给其它类型的指针,也就是说是说p2=p1这条语句编译就会出错,而必须将这条语句编译就会出错,而必须将p1强制类型转换成强制类型转换成“void*”类型的。因为类型的。因为“无类型无类型”可以包容可以包容“有类型有类型”,而,而“有类型有类型”则不能包容则不能包容“无类型无类型”.5.1.6 结构体结构体 结构体是由基本数据类型构成的,并用一个标识符来命名的各种变结构体是由基本数据类型构成的,并用一个标识符来命名的各种变量的组合。结构体中

23、可以使用不同的数据类型量的组合。结构体中可以使用不同的数据类型。(1)(1)结构体的说明和结构体变量的定义结构体的说明和结构体变量的定义定义一个结构体的一般形式为定义一个结构体的一般形式为:在在方式中,仅定义了一个结构体。如果要使用这种类型的结方式中,仅定义了一个结构体。如果要使用这种类型的结构体还需要使用变量定义语句。构体还需要使用变量定义语句。方式在定义结构体的同时,定义方式在定义结构体的同时,定义了结构体变量。例如下面左右两边的代码是等价的。了结构体变量。例如下面左右两边的代码是等价的。struct 结结构体名构体名 成员列表成员列表;struct 结构结构体名体名成员列表成员列表结结构

24、体变量构体变量;或 5.1.6 结构体结构体(2)(2)struct student /*定义一个定义一个student结构体结构体*/char name8;int age;char sex2;struct student student1;/*定义一个定义一个student结构变量结构变量student1*/struct student char name8;int age;char sex2;student1;/*定义一个定义一个student结构体结构体,同时定义一个,同时定义一个student结结构变量构变量student1*/结构体是一个新的数据类型,因此结构体变量也可以象其它类型的

25、变量一样结构体是一个新的数据类型,因此结构体变量也可以象其它类型的变量一样赋值运算,不同的是结构体变量以成员作为基本变量。赋值运算,不同的是结构体变量以成员作为基本变量。结构体成员的表示方式为:结构体成员的表示方式为:结构体变量结构体变量.成员名成员名 如果将如果将“结构体变量结构体变量.成员名成员名”看成一个整体,则这个整体的数据类型与结看成一个整体,则这个整体的数据类型与结构体中该成员的数据类型相同,这样就像前面所讲的变量那样使用。例如构体中该成员的数据类型相同,这样就像前面所讲的变量那样使用。例如:student1.age=18;5.1.6 结构体结构体(3)(3)(3)结构体指针结构体

26、指针 结构体指针是指向结构体的指针。它由一个加在结构体变量名前的结构体指针是指向结构体的指针。它由一个加在结构体变量名前的“*”操作符来定义。例如用上面已说明的结构体定义一个结构体指针如操作符来定义。例如用上面已说明的结构体定义一个结构体指针如下下:struct student *Pstudent;使用结构体指针对结构体成员的访问,与结构体变量对结构体成员的访使用结构体指针对结构体成员的访问,与结构体变量对结构体成员的访问在表达方式上有所不同。结构体指针对结构体成员的访问表示为问在表达方式上有所不同。结构体指针对结构体成员的访问表示为:结构体指针名结构体指针名-结构体成员结构体成员其中其中-是

27、两个符号是两个符号-和和的组合,好象一个箭头指向结构体成员。的组合,好象一个箭头指向结构体成员。例如要给上面定义的结构体中例如要给上面定义的结构体中name和和age赋值赋值,可以用下面语句:可以用下面语句:strcpy(Pstudent-name,LiuYuZhang);Pstudent-age=18;5.1.6 结构体结构体(4)(4)实际上,实际上,Pstudent-name就是就是(*Pstudent).name的缩写形式。的缩写形式。需要指出的是结构体指针是指向结构体的一个指针,即结构体需要指出的是结构体指针是指向结构体的一个指针,即结构体中第一个成员的首地址,因此在使用之前应该对结

28、构体指中第一个成员的首地址,因此在使用之前应该对结构体指针初始化,即分配整个结构体长度的字节空间。这可用下针初始化,即分配整个结构体长度的字节空间。这可用下面函数完成面函数完成,例如:例如:Pstudent=(struct sudent*)malloc(size of(struct student);size of(struct student)自动求取自动求取student结构体的字节长度结构体的字节长度,malloc()函数定义了一个大小为结构体长度的内存区域,函数定义了一个大小为结构体长度的内存区域,然后将其地址作为结构体指针返回。然后将其地址作为结构体指针返回。5.1.7 共用体共用体

29、l 有时需要将几种不同类型的变有时需要将几种不同类型的变量存放到同一段内存单元中。嵌入量存放到同一段内存单元中。嵌入式系统为了减少内存使用,内存单式系统为了减少内存使用,内存单元不同时刻作不同的用途,即内存元不同时刻作不同的用途,即内存复用,共用体数据类型就非常适合复用,共用体数据类型就非常适合于这种情况。例如,可把一个整型于这种情况。例如,可把一个整型变量、一个字符型变量和一个长整变量、一个字符型变量和一个长整型变量放在同一个地址开始的内存型变量放在同一个地址开始的内存单元,如图单元,如图5-6所示。以上所示。以上3个变量个变量在内存中占的字节数不同,但都从在内存中占的字节数不同,但都从同一

30、地址开始同一地址开始(图中设地址为图中设地址为$0080)存放。这种几个不同的变量共同占存放。这种几个不同的变量共同占用同一段的结构,称为用同一段的结构,称为“共用体共用体”类型结构。如右图,为共用体的内类型结构。如右图,为共用体的内存使用。存使用。图图5-6 共用体的内存共用体的内存“共用共用”0080地址整型变量b字符型变量a长整型变量c(1)共用体的定义定义一个联合类型的一般形式为:定义一个联合类型的一般形式为:union union 共用名共用名 成员表成员表 共用变量名共用变量名;成员表中含有若干成员,成员的一般形式为:成员表中含有若干成员,成员的一般形式为:类型说明符类型说明符 成

31、员名成员名例如例如:union abc int a;char b;long c;u1;(2)共用体的使用在共用体变量在共用体变量u1被分配的内存单元数量等于长整型变量被分配的内存单元数量等于长整型变量c的长度的长度(4字节字节)中。中。如果整型变量如果整型变量c的赋值为:的赋值为:u1.c=0 x12345678;则则u1.a和和u1.b的值也被修改。本例中,它们的值为:的值也被修改。本例中,它们的值为:u1.a=0 x12;u1.b=0 x1234;5.1.8 位域位域l 有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一有些信息在存储时,并不需要占用一个完整的字节,而只需占几个

32、或一个二进制位。例如在存放一个开关量时,只有个二进制位。例如在存放一个开关量时,只有0和和1两种状态,用一位二进位两种状态,用一位二进位即可。为了节省存储空间,并使处理简便,即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,语言又提供了一种数据结构,称为称为“位域位域”或或“位段位段”。所谓。所谓“位域位域”是把一个字节中的二进制位划分为是把一个字节中的二进制位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域中按域名进行操作

33、。这样就可以把几个不同的对象用一个字节的二进制位域来表示。来表示。l(1)位域的定义位域的定义位域定义与结构定义相仿,其形式为:位域定义与结构定义相仿,其形式为:strict 位域结构名位域结构名 位域列表位域列表 ;位域列表格式为:位域列表格式为:类型说明符类型说明符 位域名:位域长度位域名:位域长度例如例如:struct bs int a:8;int b:2;int c:6;b1;l(2)位域的使用位域的使用 位域的使用和结构成员的使用相同,其一般形式为:位域的使用和结构成员的使用相同,其一般形式为:位域变量名位域变量名位域名位位域名位 例如在上面定义的位域例如在上面定义的位域b1可以这样

34、调用:可以这样调用:b1.a=1;/将将b1的第的第0位置位置1 b1.b=7;/将将b1的第的第35位置位置111 通过位域定义位变量,是实现单个位操作的重要途径和方法,采用位域定义通过位域定义位变量,是实现单个位操作的重要途径和方法,采用位域定义 位变量,产生的代码紧凑、高效。位变量,产生的代码紧凑、高效。5.1.9 编译预处理编译预处理l C语言提供编译预处理的功能,语言提供编译预处理的功能,“编译预处理编译预处理”是是C编译系统的一个重要编译系统的一个重要组成部分。组成部分。C语言允许在程序中使用几种特殊的命令语言允许在程序中使用几种特殊的命令(它们不是一般的它们不是一般的C语句语句)

35、。在在C编译系统对程序进行通常的编译编译系统对程序进行通常的编译(包括语法分析,代码生成,优化等包括语法分析,代码生成,优化等)之前,之前,先对程序中的这些特殊的命令进行先对程序中的这些特殊的命令进行“预处理预处理”,然后将预处理的结果和源程,然后将预处理的结果和源程序一起再进行常规的编译处理,以得到目标代码。序一起再进行常规的编译处理,以得到目标代码。C提供的预处理功能主要提供的预处理功能主要有宏定义、条件编译和文件包含。有宏定义、条件编译和文件包含。l(1)宏定义宏定义#define 宏名宏名 表达式表达式 表达式可以是数字、字符、也可以是若干条语句。在编译时,所有引用该宏表达式可以是数字

36、、字符、也可以是若干条语句。在编译时,所有引用该宏的地方,都将自动被替换成宏所代表的表达式。的地方,都将自动被替换成宏所代表的表达式。例如例如:#define PI 3.1415926#define S(r)PI*r*rl(2)条件编译条件编译l 通常源程序的所有行参加编译。但是有时希望对其中一部分内容只在满足通常源程序的所有行参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译,这就是一定条件才进行编译,这就是“条件编译条件编译”。条件编译有三种形式。条件编译有三种形式#if 表达式表达式 程序段程序段1#else 表达式表达式 程序段程序段2#endif#ifdef 标识符标识

37、符 程序段程序段1#else 程序程序段段2#endif#ifndef 标识符标识符 程序段程序段1#else 程序段程序段2#endif形式形式在表达式为真时,则编译在表达式为真时,则编译#if下的程下的程序,否则编译序,否则编译#else下的程序。下的程序。形式形式是当所指定的标识符已经被是当所指定的标识符已经被#define命令定义过,则编译程序段命令定义过,则编译程序段1,否则编,否则编译程序段译程序段2。形式形式是当所指定的标识符未被是当所指定的标识符未被#define命命令定义过,则编译程序段令定义过,则编译程序段1,否则编译,否则编译程序段程序段2。5.1.10 用用typede

38、f定义类型定义类型l 除了可以直接使用除了可以直接使用C提供的标准类型名提供的标准类型名(如如int、char、float、double、long等等)和自己定义的结构体、共用体、指针、枚举类型外,还可以用和自己定义的结构体、共用体、指针、枚举类型外,还可以用typedef定义新的类型名来代替已有的类型名。例如定义新的类型名来代替已有的类型名。例如:typedef unsigned char INT8U;l 用法说明:用法说明:用用typedef可以定义各种类型名,但不能用来定义变量。可以定义各种类型名,但不能用来定义变量。用用typedef只是对已经存在的类型增加一个类型名,而没有创造新的类

39、型。只是对已经存在的类型增加一个类型名,而没有创造新的类型。typedef与与#define有相似之处,如:有相似之处,如:typedef unsigned int INT16U;#define INT16U unsigned int当不同源文件中用到各种类型数据当不同源文件中用到各种类型数据(尤其是像数组、指针、结构体、共用体等尤其是像数组、指针、结构体、共用体等较复杂数据类型较复杂数据类型)时,常用时,常用typedef定义一些数据类型,并把它们单独存放在定义一些数据类型,并把它们单独存放在一个文件中,而后在需要用到它们的文件中用一个文件中,而后在需要用到它们的文件中用#include命令

40、把它们包含进来。命令把它们包含进来。使用使用typedef有利于程序的通用与移植。有利于程序的通用与移植。5.2 08C语言的使用语言的使用l 08C语言适用于语言适用于Freescale 08系列微控制器,它的语法与标准系列微控制器,它的语法与标准C语法基语法基本相同,但它的函数库和标准本相同,但它的函数库和标准C的函数库有些差异,而且用的函数库有些差异,而且用08C在编程时涉及的在编程时涉及的硬件知识比较多,需要注意一些编程技巧。硬件知识比较多,需要注意一些编程技巧。5.2.1 寄存器和寄存器和I/O口的使用口的使用(1)I/O口和寄存器的定位口和寄存器的定位 普通变量的定义和访问同标准普

41、通变量的定义和访问同标准C语言,在嵌入式语言,在嵌入式C语言中我们主要要解决语言中我们主要要解决寄存器变量和某些特殊变量的定位问题,即把这些变量存放在寄存器变量和某些特殊变量的定位问题,即把这些变量存放在RAM中指定的中指定的位置。位置。(2)I/O与寄存器的操作与寄存器的操作 使用上面定义的使用上面定义的I/O口或寄存器宏,可以方便对口或寄存器宏,可以方便对I/O置高低电平或读取置高低电平或读取I/O的状态,读写寄存器。例如:的状态,读写寄存器。例如:unsigned char sPortA=PTA;/将将A口的状态赋口的状态赋给给sPortA变量变量 PTA=0 xff;/将将0 xff赋

42、给赋给A口,口,A口将全为高电平口将全为高电平 T1SC&=0 xdf;/对对TT1SC寄存器进行位操作寄存器进行位操作5.2.2 位操作方法位操作方法l 在嵌入式系统中,主控在嵌入式系统中,主控MCU的内存资源很宝贵,为了减少内存的使用量,常的内存资源很宝贵,为了减少内存的使用量,常常将一些取值为常将一些取值为0或或1的标志位组合到一个字节中,而不是使用整个字节来保存一的标志位组合到一个字节中,而不是使用整个字节来保存一个只能为个只能为0或或1的值。例如:在开发一款水表控制的软件中,定义了一个状态标志的值。例如:在开发一款水表控制的软件中,定义了一个状态标志字节字节Flag,其各位的含义如表

43、,其各位的含义如表5-1所示。所示。表表5-1 嵌入式软件中位定义实例嵌入式软件中位定义实例Bit 7Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0备用备用QLQYZFFMZT3FMZT2FMZT1CGR第第0位:磁干扰标志位:磁干扰标志(0,无干扰;,无干扰;1,有干扰,有干扰)第第1位:阀门状态标志位:阀门状态标志1(=0,正常;,正常;=1,阀门关不上,卡住,阀门关不上,卡住)第第2位:阀门状态标志位:阀门状态标志2(0,阀开着;,阀开着;1,阀关着,阀关着)第第3位:阀门状态标志位:阀门状态标志3(=0,正常;,正常;=1,阀门关不上,打滑,阀门关不上

44、,打滑)第第4位:剩余水量正负标志位:剩余水量正负标志(0,正;,正;1,负,负)第第5位:欠压标志位位:欠压标志位(0,电压正常;,电压正常;1,欠电压,欠电压)第第6位:欠量标志位:欠量标志(0,未欠量;,未欠量;1,已欠量,已欠量)第第7位:备用位:备用l 1用位运算符实现位操作用位运算符实现位操作 C语言中提供了语言中提供了6种基本的位运算符:按位与种基本的位运算符:按位与(&)、按位或、按位或(|)、按位取反、按位取反()、按位异或、按位异或()、左移、左移()。嵌入式系统编程常常需要寄存器或内。嵌入式系统编程常常需要寄存器或内存存内单个二制位。在大多数情况下,最好的方法是读出整个寄

45、存器值,改变二进内单个二制位。在大多数情况下,最好的方法是读出整个寄存器值,改变二进制制位,然后把整个值写回到设备寄存器中。位,然后把整个值写回到设备寄存器中。l 2测试位测试位按位按位“与与”运算最常用于测试单个位运算最常用于测试单个位(或位域或位域)的值,在需要关注的的值,在需要关注的“位位”所在位所在位置由单置由单独一个独一个1组成的特征码与操作数作组成的特征码与操作数作“与与”运算,当关注的运算,当关注的“位位”是是1时,结果才时,结果才是非是非0值,即逻辑真值。在实际书写时,特征码通常用十六进制、二进制数或移位表值,即逻辑真值。在实际书写时,特征码通常用十六进制、二进制数或移位表达达

46、式。例如:要测试第式。例如:要测试第4位是否为位是否为1,有以下几种写法:,有以下几种写法:if(bits&0 x10)!=0)if(bits&0 x10)if(bits&0b00010000)if(bits&(14)l 由于任意非由于任意非0值都解释为值,所以条件中可以省略对值都解释为值,所以条件中可以省略对0的冗余比较。的冗余比较。l 表表5-3给出了给出了08C位操作语句编译后的所对应的指令,从表中可以看出编译器位操作语句编译后的所对应的指令,从表中可以看出编译器在编译时,已经做了优化,将这些在编译时,已经做了优化,将这些C语句变成了语句变成了08CPU中的位指令,达到和中的位指令,达到

47、和汇编相同的执行效率。汇编相同的执行效率。表表5-3 08C中的位操作语句及对应的编译后的中的位操作语句及对应的编译后的指令指令C语句语句编译后的汇编指令编译后的汇编指令PTA|=(17);/PTA的第的第7位置位置1Bset 7,0 x00 PTA&=(17);/PTA的第的第7位清位清0Bclr 7,0 x00PTA=0 x80;/PTA的第的第7位取反位取反LDA 0 x00EOR#-128STA 0 x00if(PTA&0 x81)=0)/检查第检查第7位和第位和第0位是否为位是否为0LDA 0 x00BIT#-127BNE 0 x08C中除了上述的位操作的方法外,还可以综合共用体和位

48、域等多种数据类型,中除了上述的位操作的方法外,还可以综合共用体和位域等多种数据类型,很直观地实现位操作,关于这部分的讲述读者参考本章的进一步讨论部分。很直观地实现位操作,关于这部分的讲述读者参考本章的进一步讨论部分。5.2.3 中断处理中断处理l 首先,ISR与C中的正常子函数是有差别的:第一,正常子函数被编译后的返回指令为RTS,而ISR被编译后的返回指令为RTI。第二,正常子函数是通过调用方式进入的,而ISR是通过中断机制进入的。第三,ISR的参数和返回类型总是void。现在,就可以带着ISR的这些独有的特性编写它了:新建一个Vectors08.c,并加入工程中。定义中断向量表。5.2.4

49、 085.2.4 08C C的常用库函数的常用库函数 08C提供一系列函数库供程序员使用,其中囊括了标准提供一系列函数库供程序员使用,其中囊括了标准C所具有的大部分库所具有的大部分库函数和一些函数和一些08C特有的函数,但是特有的函数,但是08C中的有些函数和标准中的有些函数和标准C中的函数的功能中的函数的功能不一样。这些函数的头文件位于安装目录的不一样。这些函数的头文件位于安装目录的include目录下,库文件位于安装目录下,库文件位于安装目录的目录的lib目录下。下面对目录下。下面对08C中一些常用的库函数做简要说明,更多的函数中一些常用的库函数做简要说明,更多的函数库说明库说明参见附录参

50、见附录D。(1)串口操作类函数串口操作类函数函数的声明如下:函数的声明如下:int printf(char*fmt,)格式化输出格式化输出printf函数是一个标准库函数,它的函数原型在头文件函数是一个标准库函数,它的函数原型在头文件“stdio.h”中。但作中。但作为一个特例,不要求在使用为一个特例,不要求在使用 printf 函数之前必须包含函数之前必须包含stdio.h文件。文件。printf函数函数调用的一般形式为:调用的一般形式为:printf(“格式控制字符串格式控制字符串”,输出列表,输出列表)其中格式控制字其中格式控制字符串用于指定输出格式。格式控制串可由格式字符串和非格式字符

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(第5章08C语言及第课件.ppt)为本站会员(晟晟文业)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|