版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、3 单片机的C语言基础C语言是一种高级程序设计语言,C语言具有汇编语言和高级语言的双重特性,既可以作为系统设计语言来编写操作系统,也可以作为应用程序设计语言来编写不依赖计算机硬件的应用程序。它的优点是可读性强和可移植性高。使用C语言来开发程序不但可以减少程序开发的时间,而且所开发出来的程序不会占据大量的程序存储器,因此许多嵌入式系统程序都使用C语言作为开发工具。目前,单片机使用C语言编写程序比较流行,特别是对于初学者,利用C语言编写单片机程序根本不用了解通用寄存器的应用过程以及内部各个部件的地址,只需记住特殊寄存器的作用就可以编写完美的程序。单片机C语言程序设计过程中,虽然出现了各种不同的C语
2、言编译器,但使用C语言编程时仍然依照C语言格式进行。在这一节中,我们将学习单片机程序设计中常用的C语言基础知识。 本节任务:1.掌握C语言程序设计的基本方法;2.掌握C语言的控制命令的使用方法;3.掌握C语言的指针、函数的使用方法;4.掌握C语言程序中嵌入汇编语言的方法。3.1.1 C语言概述一、C语言简介C语言诞生于20世纪70年代初在贝尔实验室,当时的目的是作为UNIX操作系统的实现语言。随着UNIX操作系统的广泛使用,C语言也迅速得到推广。C语言在发展过程中出现了多种版本,并且得到不断的改进。各个C语言版本之间存在一些不一致的地方。美国国家标准协会(ANSI)在1983年对C语言进行了改
3、进和扩充,制定了ANSIC标准,并于1989年再次修订。二、C语言的特点C语言可读性强和可移植性高的优点。C语言的主要特点如下:(1)C语言是一种面向过程的高级程序设计语言。(2)可移植性好,编写的程序能够适应各种平台。(3)C语言语言简洁,结构紧凑,使用方便、灵活。(4)C语言是一种模块化的程序设计语言。(5)数据处理能力强,运算符丰富。 三、单片机使用C语言的基本格式在开始学习C语言之前,我们先看一个完整的单片机程序案例,该程序目的是想让单片机的P0.0口驱动一个LED明灭闪烁。本程序利用Keil C 软件编写。/*/#includesbit LED = P10; /定义LED为P1_0;
4、void delay( void )int i ,j;for(I = 1;I = 255;i+) /延时一段时间for(j=1;j=255;j+);void main(void) LED = 0;while(1)delay(); LED = !LED; /*/ 从以上程序中我们看到C语言程序有以下特点:(1)C语言程序中大小写是有所区别的,基本上C语言大都是使用小写。(2)程序中每一条指令的结尾都必须加上分号 “;”。每一个声明,每一个语句都必须以分号结束。但预处理命令、函数头和大括号“”之后不能加分号。(3)C语言程序中,main()表示主程序,程序都是从该函数开始运行,所以程序中一定要有且
5、仅有一个main()函数,但可以有多个其他函数(如min()函数等),每一个函数完成相对独立的功能,函数是C语言程序的基本模块单元。main()是函数名,后面的一对圆括号“()”用来写函数的参数,参数可以省略,但圆括号不能省略。(4)函数之后的“”表示本函数开始,“”表示本函数结束。(5)程序中所使用的变量一定要预先作声明,换言之,变量的声明必须放在程序的开头。(6)为了增强程序的可读性,低一层次的语句或声明通常比高一层次的语句或声明缩进若干格后书写,以体现层次结构四、编译预处理所谓预处理,是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所做的工作。预处理是C语言的一个重要功能,它由预处理
6、程序负责完成。当对一个源文件进行编译时,系统将自动调用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。预处理命令都以“#”开头,每个处理命令必须单独占一行,且末尾不使用分号作为结束符。预处理命令放在源程序的首部,作用域是从当前说明的地方开始到文件结束,在文件之外就失去作用。常用的预处理命令有宏定义、条件编译和文件包含。C语言有以下一些编译指令,如表2-1-1所示。表3-1-1 编译预处理编译指令说明#include包含另一个文件#define定义一个宏(macro)或是常量#undef取消一个宏或是常量的定义#asm和endasm在程序中加入汇编语言的程序#ifdef、
7、#indef、#else和#endif用于条件式的编译#include指示编译器把它所包的文件加进来一起进行编译。#include 是把文件regx51.h包含进来,而文件regx51.h定义所有8051的特殊用途寄存器的地址和一些经常使用的常量;另外一个文件stdio.h定义C语言经常使用的基本输入输出函数。#include之后所跟随的文件如果放在“”内就表示该文件位于include子目录中;如果被包含的文件保存在当前的工作目录中时,就必须用“”括起来。如果您使用到C语言的一些特定函数时,就必须将定义这些函数的文件包含进来一起编译。无参宏定义命令的一般格式如下#define 标识符 字符串其
8、中,“标识符”为所定义的宏名。“字符串”可以是常量、表达式、格式串等。#define命令出现在程序中所有函数的外面,宏名的有效范围为定义命令之后到本源文件结束,但可用#undef命令终止宏定义的作用域。其他编译预处理内容在后面用到时候具体讲解。五、注释为增强程序的可读性,编程人员可以在程序的每一指令后面中加入注释,这样可以让程序更容易让人阅读,一个高质量的程序,应在其源程序中加上必要的注释,在注释中也可以使用汉字进行注释。C语言的注释可以分成两种:单行注释和多行注释。单行注释格式为/注释内容以双斜线“/”开始,双斜线之后的文字都是注释,但是只能在同一行,多行注释格式为/*注释内容*/多行注释是
9、以/*开始、以*/结束的注释,在“/*”和“*/”之间的文字都是注释。并且必须配对使用,多行注释可以占用一行,也可以占用许多行,程序编译时,不对注释做任何的处理。3.1.2 数据类型一、基本数据类型C语言提供了5种基本数据类型,分别是整形(int)、单精度型(float)、双精度型(double)、字符型(char)、空类型(void), 还有一些数据类型修饰符,用来扩充基本类型的意义,以便更准确地适应各种情况的需要。修饰符有long(长型)、short(短型)、signed(有符号)、unsigned(无符号)。这些修饰符与基本数据类型的关键字组合可以表示不同的数值范围以及数据所占内存空间的
10、大小。如表2-1-2所示。表2-4-2 Keil C可以使用的合法数据类型和说明数据类型数据类型说明长度数据长度bit位1位0,1char字符8位-128127unsigned无符号字符8位0255Signed char有符号字符8位-128127int整型16位-3276832767shor int短整型16位-3276832767unsigned int无符号整型16位065535signed int有符号整型16位-3276832767long int长整型32位-unsigned long int无符号长整型32位0signed long int有符号长整型32位-float浮点数32
11、位0.175e-380.402e38double双精度浮点32位0.175e-380.402e38void空0位没有任何数据除了基本数据类型之外,用户也可以自己的数据类型。譬如,用户要记录时间或日期时,可以分别用不同的变量储存时、分、秒,可是年、月、日,如:char hour,minute,second,year,moth,day;但是也利用结构体自定义时间和日期等数据类型,如下所示:/*/typedef structchar hour; char minute;char second;time;typedet structchar year;char month;char day;data;
12、/*/当用户定义好time和date之后,就可以声明数据类型是time和date变量,如time now,alarm;date today,tmpday;实际上,C语言编译器会在数据存储器中保留适当的位置以储存这些变量,如图3-1所示。用户自定义数据类型的定义格式如下:typedef struct数据类型 变量序列1;数据类型 变量序列2;自定义数据类型的名称;二、标识符标识符就是编程人员为程序中的变量、常量、标示或取的名字。在C语言的每一个程序中所使用的函数和变量等都应有唯一的名称,这样才能被识别和使用。在上面的范例中,变量i和j者是用户自己取的名称,因为他们都是标识符。符号常量名、变量名、
13、函数名、标号、数组名、文件名、结构体类型名和其他各种用户定义的对象名都是标识符。编程人员所命名的标识符发布遵守一定的命名规则,如下所述: (1)标识符只能英文字母、数字以及下划线()所组成。 (2)标识符只能以英文字母或下划线开头。 (3)标识符的长度不能超过32字符。 (4)大小写英文字母是不同的。 (5)保留字不能作为标识符。如:以下是合法的标识符:Num, num1,buffer_1,i,flag,以下是不合法的标识符:1num,buffer 1,int。标识符在使用过程中用于标识量,可以用单词和短语来表示一定含义,避免混淆。Num和num 是不同的标识符,因为C语言中大小写英文字母是不
14、同的。三、关键字关键字是C语言使用的命令,作为关键字的每个标识符在C语言程序中都有预先定义好的特殊意义,这些关键字不能用于任何其他目的。所以不能用作变量的名字,在Keil C中的关键字除了ANSI C 标准中的32个关键字外,还根据51单片机的特点扩展了相关的关键字,以下是Keil C的关键字。_at_alienbdatabreakbitcasecharcodecompactdatadefaultdodoublefarelseenumexternfloatforgotoifidataintinlineinterruptlargelongpdata_priority_reentrantretur
15、nsbitsfrsfr16shortsignedsizeofsmallstructtypedefusingunionunsignedvoidwhilexdata四、常量整型常量即为整型常数,可以用十进制、八进制和十六进制三种形式表示。凡是以数字0开头,由数字07组成的序列均作为八进制数处理; 凡是以0x(或0x)开头的由数字、字符af(或AF)组成的序列均作为十六进制数处理; 其他情况下的数字序列均作为十进制数处理。 表3-1-3 各种常量使用的规则和范例各种常数规则范例十进制一般十进制格式1234二进制开头加上0b0b八进制开头加上OO0123十六进制开头加上0x0Xff00无符号整数常量结
16、尾加上U30000U长整数常量结尾加上L299L无符号长整数常量结尾加上ULUL浮点数的常量结尾加上F4.312F字符常量以单引号括起来a字符常量以双引号括起来“Hello”在C语言程序中,可以定义一个符号来代表一个常量,这种相应的符号称为符号常量。定义符号常量的目的是为了提高程序的可读性,便于程序的调试、修改和移植。因此在定义符号常量时,所使用的符号常量名应尽可能地表达其所代表的常量的含义。在C语言中,符号常量在使用前必须先用预处理命令#define进行定义。例如:#define TRUE 1#define FALSE 0这种语句的格式是在#define后面跟一个标识符和一串字符,彼此之间用
17、空格隔开。由于不是C语句,因此语句末不用分号。当程度被编译时,先被编译预处理。即当预处理遇到#define时,就用标识符后面的字符串替换程度中的所有该标识符。五、变量C语言程序中常常需要将数据存储在内存中,方便后面使用或者修改这个数据的值,所使用的变量一定要预先声明,变量声明时的格式化如下:存储类型 数据类型 变量名;变量初始化的一般格式如下:存储类型 数据类型 变量名1=初值1,变量名2=初值2,;每个变量都必须有一个名字这就是变量名。变量的命名规则与用户自定义标识符的命名规则相同。变量值存储在内存中,不同类型的变量,占用的内存单元(字节)数不同。在程序中,通过变量名来引用变量值。六、运算符
18、 各种数据类型、常量、变量可以用代表运算功能的运算符将运算对象连接起来,并且以符合C语言中的语法规则的一个说明运算过程的式子(即表达式)来完成对数据的处理。表达式中的操作数可以是常量、变量或子表达式。各种运算符彼此间的优先级及结合性。 优先级:当表达式中存在不同优先级的运算符参与操作时,优先级较高的先于优先级较低的进行运算。 结合性:当表达式中各种运算符优先级相同时,由运算符的结合性确定表达式的运算顺序。一类运算符的结合性为从左到右(占多数运算符),这是人们习惯的运算顺序;另一类运算符的结合性是从右到左,即单目、三目和赋值运算符。(1)算数运算符算数运算符是C语言中使用较多的的运算符号,不同的
19、运算符用法见表表2-1-4所示,为了便于了解运算符的应用,表中假设a等于8,b等于2。表3-1-4算术运算 运算符说明范例执行结果+加c=a+b;c等于10减d=ab;d等于6*乘e=a*b;e等于16/除f=a/b;f等于4%取余数g=a%b;g等于0+加1c+;相当于c=c+1c等于11减1d-;相当于 d=d-1d等于5=等于a=8;设置a等于8+=先相加再等于e+=5;相当于e=e+5;e等于21=先相减再等于f=5;相当于f=f5;f等于1*=先相乘再等于f*=5;相当于f=f*5;b等于是0/=先相除再等于a/=5;相当于a=a/5;a等于1(整数除法)%=先取余数再等于a%=5;
20、相当于a=a%5;a等于3(a原来等于8)虽然对于基本数据类型的变量进行+、-运算完全可以用n=n1完成,但使用+、-运算可以提高程序的执行效率。这是因为+、-运算只需要一条机器指令就可以完成,而n=n1则要对应3条机器指令。自增、自减运算符的运算对象只能是简单变量,不能是常量或是带有运算符的算式。例如,123+、(x+y)+是错误的。赋值运算符:“=”。 赋值运算符是一个双目运算符,其结合性是从右至左。赋值运算符的左边部分称为左值,左值只能是一个变量;赋值运算符的右边部分称为右值,右值可以是一个表达式。赋值表达式:由“=”连接的式子称为赋值表达式。其功能是将赋值号右边表达式的结果送到左边的变
21、量中保存。“=”和“=”是两种完全不同的运算符,前者为关系运算符中的相等运算符,后者为赋值运算符。 (2)关系运算符关系运算符用来测试两个操作数之间的关系。C语言中的关系运算符均为双目运算符,包括(大于),=(大于等于),小于a大于a5TRUE=小于等于a=大于等于a=5TRUE(3)逻辑运算符逻辑运算符用于对几个关系运算表达式的运算结果进行组合,做出综合的判断。逻辑运算的结果以非0为“真”,0为“假”。如果A代表一个关系表达式的运算结果,B代表另一个关系表达式的运算结果,则A和B的各种逻辑运算的真值关系如表2-1-6所示。表3-1-6 逻辑运算真值表ABA&BA|B!A!B真真真真假假真假假
22、真假真假真假真真假假假假假真真对于与运算,全真为真,有假为假;对于或运算,有真为真,全假为假。C语言程序中可以使用以下的逻辑运算,逻辑运算的结果是一个布尔值:TRUE 或FALSE。在以下的运算中,假设a=8,如表2-1-6所示。表3-1-6 逻辑运算运算符说明范例执行结果&AND(a5)&(a10)TRUEOR(a10)FALSE!NOT!(a10)TRUE(4)位运算符位逻辑运算是针对运算元的每一个位逐一地实施逻辑运算。在以下的运算中假设a=5,如表3-1-7所示。表3-1-7 位运算运算符说明范例执行结果&ANDa&0x01a等于1ORa0x80a等于0x85NOTaa等于0xFAaXO
23、Ra0xFFa等于0xFAa左移a1a等于0x02右移a1a等于0x0A3.1.3程序的三种基本控制结构程序的三种基本控制结构为顺序结构、选择结构和循环结构,这三种基本结构可以组成所有的复杂程序。一、顺序结构顺序结构是C语言程序最简单的程序结构,是构成复杂程序的基础。仅包含顺序结构的程序会按照语句的书写顺序执行。C语言程序是由若干语句组成的,每个语句以分号作为结束符。C语言的语句可以分为5类,分别是控制语句、表达式语句 、函数调用语句、空语句和复合语句。除了控制语句外,其余4类都属于顺序执行语句。(1)表达式语句表达式语句由表达式加上分号组成的,最常见的就是赋值语句,它是由一个赋值表达式后跟一
24、个分号形成。例如: i=7; /将7赋值给变量事实上,任何表达式都可以加上分号而成为语句,例如: i+; /使i变量的值加1(2)函数调用语句 由函数调用加上分号组成,例如:delay(); /调用延时函数 函数是一段程序,这段程序可能存在于函数库中,也可能是由用户自己定义的当调用函数时会转到该程序执行。但函数调用语句与前后语句之间的关系是按顺序执行的。(3)空语句 只有分号组成的语句称为空语句。在程序中,如果没有什么操作需要进行,但从语句的结构上来说必须有一个语句在进,可以书写一个空语句。(4)复合语句把多个语句用大括号“”括号来组成一个语句称复合语句。例如:delay(); LED=!LE
25、D; 复合语句内的各条语句都必须以分号结尾,在大括号外不能加分号。二、选择结构在解决实际问题中,有进需要根据给定的条件来做决定,即条件满足时做什么,条件不满足时做什么。选择结构程序可解决这类问题,其作用是根据所给定的两个或多个分支中,选择其中的一个分支来执行。C语言中有两种选择结构语句,即if语句和switch-case语句。(1)if语句1) 单分支if语句结构 if(条件)语句1; 如果表达式的值为真,则执行其后的语句,否则不执行该语句; 2)双分支if 语句双分支if语句的语法格式如下:if(表达式)语句1;else 语句2;如果表达式的值的为真,则执行语句1,否则执行语句2其中else
26、的部分可以省略。电脑首先判断if后面的条件是真还是假,如果是真就执行语名1,否则就执行语句2。else子句不能作为语句单独使用,必须与if配对使用。例如:if(i3) i=0;else i=2;嵌套if语句是指if语句中又有if语句,:if() if() 语句1; else 语句2;else当if语句嵌套使用时,会出现if与else的配对问题。C语言规定,else总是与其上面最近的if 配对。如果要改变这种默认的配对关系,可以在相应的if选择语句上加上”来重新确定配对关系。3)多分支if 语句 多分支语句的语法格式如下:if (表达式1)语句1;else if(表达式2)语句2; else i
27、f (表达式n)语句n; else 语句n+1;依次判断表达式的值,当出现某个值为真时,则执行其对应的语句。然后跳到整个if语句之外继续执行程序。如果所有的表达式均为假,则执行语句n。然后继续执行。(2)switch-case语句使用语句的嵌套结构实现多分支选择功能时,程序的结构显得不够清晰,因此使用switch语句。switch 语名的格式:switch (变量) case 常量1:语句1;break; case 常量2:语句2;break; case 常量3:语句3;break; . default :语句n; 计算表达式的值,并将其逐个与其后的常量表达式的值相比较,当表达式的值与某个常量
28、表达式的值相等时,即执行其后的语句,而不再进行判断,但继续执行case后面所有的语句;如果表达式的值与所有case后的常量表达式均不相同时,则执行default后的语句。case后的语句既可以是单个语句,也可以是复合语句,不需要用大括号括起来。case常量表达式和default子句可以按任何顺序出现,但其本身不改变控制流程。switch号内的表达式的值和case后面常量表达式的值,都必须是整型的或字符型的,不允许是实数在后的各个常量表达式的值不能相同。否则会出现错误。三、循环结构循环是计算机解题的一个重要特征。其特点是,在给定条件成立时,反复执行某程序段,直到条件不成立为止。给定的条件称为循环
29、条件,反复执行的程序段称为循环体。C语言提供了5种循环语句:while语句、do-while语句、for语句、goto语句和if语句。(1)for循环for 循环格式如下:for(表达式1;表达式2;表达式3)语句或程序;执行过程是:(1)计算“表达式1”;(2)进行第一轮循环:“计算表达式2”,若值为假,则退出循环;否则执行“语句”;(3)计算“表达式3”;(4)进行第二轮循环:计算“表达式2”,若值为假,则退出循环;否则执行“语句”;(5)计算“表达式3”其执行过程如图所示。表达式1表达式3语句表达式2图2.1.1 for循环语句的执行流程例如:for(i=1;i=200;i+) /延时一
30、段时间for(j=1;j=200;j+); /前一个for语句的循环体“表达式1”、“表达式2”,和“表达式3”都是选择项,可以省略,但其后的分号不能省略。省略“表达式1”,表示不对循环控制变量赋初值。省略“表达式2”,则不作其他处理时变成为死循环,需要在循环体中用break等语句退出循环。省略表达式3,则不对循环控制变量进行操作,这进可在语句体中加入修改循环控制变量的语句。“表达式1”和“表达式3”可以同时省略,需要使用相关语句保证循环结束。3个表达式都可省略。例如,for(; ;)语句相当于while(1)语句。(2)while 循环while语句的使用格式:while(表达式)语句;计算
31、表达式的值,当值为真(非0)时,执行循环体语句。例如:while(i-) a=a+; 当循环体由多个语句组成时,必须用大括号括起来,使其形成复合语句。 while(i5) a=a+1; i+;下面是一个无穷while循环:while(1); (3)do/while 循环 do-while语句的使用格式如下:do语句或程序;while(表达式); do-while 循环与while循环的不同在于,do-while循环语句先执行循环中的语句,然后再判断表达式是否为真,如果为真则继续循环;如查为假,则终止循环。因此,do-while循环至少要执行一次循环语句。例如:do a=a+1;i=i+3;wh
32、ile (i30); 四、goto语句goto语句是一种无条件转移语句,建议在程序中最好不使用它。因为goto语句会破坏结构化设计的3种基本结构,并给阅读和理解程序带来困难。但在多层嵌套退出时,用goto语句则比较合理。goto语句格式如下:goto 语句标号; 其中的语句标号是用户任意选取的标号符,其后跟一个“:”,可以放在程序中任意一条语句之前,作为该语句的一个代号。执行goto 语句后,程序将跳转到该标号处并执行其后的语句。另外标号必须与goto语句同处于一个函数中,但可以不在一个循环层中。 loop1:x+; if(x100) goto loop1;虽然大部分gogo语句都是可以避免的
33、,并且应该尽量少用,但是在某些时候,goto语句会使程序的流程更清楚,不过使用的进修一定要很小心同,避免让程序变得难懂。利用keil软件进行单片机C语言程序设计时,程序的每一条语句和程序结构往往不很复杂,对于没有C语言基础的人,学习单片机C程序设计能很快就能入门,但程序的语句之间有较强的逻辑关系,一个清晰的程序设计思路是程序设计的关键,另外还要有过硬的硬件技术基础,通过不断的编程练习,才能成为一个编程的高手。3.1.4指针指针(pointer)实际上就是存储器的地址,因为我们可以把它想像成一个指向存储器的箭头,所以称为指针。而指针变量就是储存存储器地址的变量。内存单元的指针和内存单元的内容是两
34、个不同的概念。使用指针变量时也必须预先声明。对于一个内存单元来说,它的地址即为指针,其中存放的数据是该单元的内容。在c语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个内存单元的地址,或称为某内存单元的指针。指针变量也是一个变量,它和普通变量一样占用一定的存储空间。但与普通变量不同之处在于,指针变量的存储空间存放的不是普通的数据,而是另一个变量的地址。因此,指针变量是一个地址变量。声明指针变量的格式如下所示:数据类型 *指针变量名;在指针定义中,“指针变量”前的“*”仅是一个符号,并不是指针运算符;“基类型”表示该项指针变量所指向变量的数据类型,并非指针变量
35、自身的数据类型,因为所有指针变量都是地址,所以所有指针变量的类型相同,只是所指向的变量的数据类型不同。例如:char *p;表示p是一个指针变量,其值是个整型变量的地址,或者说p指向一个整型变量。至于p究竟指向哪一个整型变量,应由向p赋予的地址来决定。指针也可以指向用户自定义的数据类型变量,如下所示:typedef struct char year; char moth; char day;date;date *dispaly_date;一、 指针与数组数组的名字后面没有加上任何索引值时,就是指向数组开始位置的地址值,所以数组的名字也是指针。范例char filename80;char *p;
36、p=filename; /指针p存放filename的开始地址反之,指针也可以当成数组来使用,如下例所示。范例int x5=1,2,3,4,5;int *p,sum,i;p=x; /指针p存放数组x的开始地址for(i=0;i5;i+) sum=sum+pi; /pi相当于xi二、 指针的运算(1)指针变量前面上*号就是取得指针所指向位置的内容。范例int x5=1,2,3,4,5;int *p;p=x; /指针p存放数组x的开始地址*p=10; /相当于x0等于10(2)变量前面加上&符号,可以取得一个变量的位置。范例 int x,y; int *p; p=&x; /指针p存放x的地址,相当
37、于p是指向x的指针 *p=1; /相当于设置x等于1(3)&符号也可以加在数组元数的前面。范例int x5;int *p;p=&x2; /指针p存放x2的地址,相当于p是指向x2的指针*p=50; /相当于设置x2等于503.1.5 数组在本案例中,数码管的显示码是一组有规律的同类型数据,如果定义大量的简单变量,程序将变得非常繁琐。为了处理方便,C语言把具有相同类型的若干变量或常量,用一个带下标数组定义。对各个变量的相同操作可以利用循环改变下标值来进行重复的处理,使程序变得简明清晰。带下标的变量由数组名称和用方括号括起来的下标共同表示,称为数组元素。通过数组名和下标可直接访问数组的每个元素。数
38、组有两个特点:一是其长度是确定的,在定义的同时确定了其数组的大小,在程序中不允许随机变动;二是其元素必须是相同类型,不允许出现混合类型。一、一维数组在C语言中使用数组必须先进行定义或声明,一旦定义了一个数组,系统就将在内存中为其分配一个所申请大小的空间,该空间大小固定,以后不能改变。一维数组的定义格式为数据类型 数组名常量表达式;在C语方中规定,一个数组的名字表示该数组在内存中所分配的一块存储区域的首地址,因此,数组名是一个地址常量,不允许对其进得修改。“常量表达式”表示该数组拥有的元素个数,即定义了数组的大小,必须是正整数。例如,以下语句定义了int 型的长度为10的一维数组unsigned
39、 char seven_seg10在定义了一个数组后,系统在内存在分配一块连续的存储空间用于存储数组。一个数组中的元素下标必须从0开始。所以,定义数组时,若“常量表达式”指出数组长度为N,数组元素下标只能从0到n-1。“常量表达式”能包含常量,但不能包含变量。二、一维数组元素的引用 在程序中,一维数组元素可以直接作为变量或常量直接饮用,其的引用格式为数组名下标其中,“下标”可以是整型常量或是整型表达式。下标是数组元素到数组开始的偏移量,第一个元素的偏移量是0(亦称0号元素),第二个元素的偏移量是1(亦称1号元素),依此类推。例如,seven_seg5表示引用数组seven_seg的下标为 5的
40、元素,即0x99。三、一维数组的初始化每个数组元素可以表示一个变量,对数组的赋值也就是对数组元素的赋值。在定义数组的语句中,可以直接为数组赋值,这称为数组的初始化。数组的初始化方法是将数组元素的初值信存放在由大括号括起来的初始值表中,每个初值之间由逗号隔开。例子:单片机内部存储的汉字字库uchar code keji32=/*- 文字: 河 -*/*- 宋体12; 此字体下对应的点阵为:宽x高=16x16 -*/0x20,0x00,0x17,0xFE,0x10,0x08,0x00,0x08,0x88,0x08,0x4B,0xC8,0x52,0x48,0x12,0x48,0x22,0x48,0x
41、23,0xC8,0xE2,0x48,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x28,0x20,0x10,/*- 文字: 南 -*/*- 宋体12; 此字体下对应的点阵为:宽x高=16x16 -*/0x01,0x00,0x01,0x04,0xFF,0xFE,0x01,0x00,0x02,0x00,0x3F,0xFC,0x24,0x24,0x22,0x44,0x2F,0xF4,0x21,0x04,0x3F,0xFC,0x21,0x04,0x21,0x04,0x21,0x14,0x21,0x08,0x00,0x00,/*- 文字: 科 -*/*- 宋体12; 此字体下
42、对应的点阵为:宽x高=16x16 -*/0x06,0x08,0x78,0x88,0x08,0x48,0x08,0x48,0xFE,0x08,0x18,0x88,0x1C,0x48,0x2A,0x48,0x28,0x0E,0x48,0x78,0x8B,0x88,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,/*- 文字: 技 -*/*- 宋体12; 此字体下对应的点阵为:宽x高=16x16 -*/0x10,0x20,0x10,0x20,0x10,0x20,0xFD,0xFE,0x10,0x20,0x14,0x20,0x19,0xFC,0x31
43、,0x08,0xD0,0x88,0x10,0x90,0x10,0x60,0x10,0x60,0x10,0x90,0x11,0x0E,0x56,0x04,0x20,0x00,/*- 文字: 学 -*/*- 宋体12; 此字体下对应的点阵为:宽x高=16x16 -*/0x01,0x08,0x10,0x8C,0x0C,0xC8,0x08,0x90,0x7F,0xFE,0x40,0x04,0x8F,0xE8,0x00,0x40,0x00,0x80,0x7F,0xFE,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x02,0x80,0x01,0x00,/*- 文字:
44、院 -*/31.6 函数调用与文件包含按照一定顺序把单片机的程序在一个函数或一个中全部完成,是简单的单片机系统程序设计常用的一种结构,当程序只有几十行或几百行的时候,采用顺序结构编程的方法很容易让人看明白。如果一个程序超过几千行的时候,分析就会变得很复杂。单片机C语言程序也支持模块化设计,在模块化程序设计过程,经常会用到函数的调用、文件的包含问题。C语言的模块化程序设计给单片机编程带来很大的方便,在这里以本节程序为例,简单介绍在Keil软件中实现模块化设计常用的技巧。一、自定义函数程序中经常反复执行的部分可以写成一个函数,然后就可以在程序中反复地调用。以下是函数的一般格式函数类型 函数名称(参
45、数序列); 函数的主体其中函数类型用来设置一个函数被调用之后所返回数值的类型,如果用户希望写一个不返回任何数据的函数时,可以将函数类型设为void。 (1)无返回值函数本节案例中delay()函数声明和调用情况为/*/void delay (unsigned int x) /没有返回值,有形参 unsigned int i;unsigned char j;for(i = 0;i x;i+) for (j = 0;j = 200;j+);void main (void).while (1) .delay(1000); /调用时间延迟函数,有实参/*/(2)有返回值函数如果函数中要返回数值时,必须
46、使用return命令。并且返回值的类型必须与函数的类型一致,以下是有返回值函数的例子/*/unsigned char sum(unsigned char a,unsigned char b)unsigned char x;check_GLCD_busyflag(); /函数中可以调用另一个函数x=a+b;return x; /return会返回unsigned char 类型的数据/*/一、函数调用我们可以把一些具有一定功能的程序打包为一个个独立的函数,用到此功能时直接调用即可。如在本节的几个程序中,主函数都调用了延时函数。函数的调用是单片机程序模块化设计的一个方法,函数的调用让C语言的单片机
47、程序具有很强的可移植性,同时也大大简化了程序的结构。函数调用比较简单,如本例和上一节的程序中,主函数中的出现的delay()语句就是一种函数调用,当单片机运行主函数的delay(1000)语句时,调用延时函数delay (unsigned int x),其中1000为延时函数的实参,x为函数的形参,在还有形参函数中,实参必须与形参类型统一,本例中如果x为char变量,则程序运行中会出错。另外,为了提高单片机程序的可靠性,在函数调用时,无返回值的函数尽量用void声名,没有形参的函数也要用void声名。二、文件的包含函数调用只能使程序的结构简,并不能使程序设计简化。在复杂的单片机程序中也常常用到
48、文件包含和文件关联。本例中程序前面的#include语句是一种文件包含形式。所谓文件包含,是指一个文件将另外一个文件的内容全部包含进来。reg51.h是Kiel软件中定义51系列单片机内部资源的头文件,在编写单片机程序时,只要用到51单片机内部资源,程序前面必须把此文件包含进来。复杂的单片机系统,程序可以有主程序和若干子程序组成,子程序服务与主程序,并通过文件包含与主程序关联,文件包含最简单应用是直接在主程序中包含子程序的C语言文件,也可以把子程序做成头文件形式被主程序包含。本例程序中,我们可以把延时函数在文档中剪切保存为一个delay.c文件,并存放在与主程序同一个目中。这个C文件内容为/*
49、/void delay (unsigned int x) unsigned int i;unsigned char j;for(i = 0;i x;i+) for (j = 0;j = 200;j+);/*/在设计LED闪烁程序时直接包含即可,这样主程序可以得到简化,如:/*/#include /包含51头文件 #include”delay.c” /包含delay.c文件void main (void)unsigned char i; /* 变量 i 作为数组的09编号 while (1) P0 = seven_segi; /*输出09到共阳七段显示器*/delay(1000); /*调用时间延迟函数delay()*/i+;if(i = 10)i = 0;/*/也可以把delay.c文件生成一个delay.h文件在程序中进行包含,在使用时delay.h也放在与主程序同一级目录中。delay.h的内容为/*/#ifndef _delay_h_#define _ delay _h_voi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030乌拉圭畜牧业市场分析与投资策略研究报告
- 2025-2030乌兹别克斯坦棉花行业市场供需分析及投资评估规划分析研究报告
- 2025-2030下沉式卫浴产品设计创新与用户体验提升研究
- 2025-2030智能手机产业链供需现状分析及投资价值规划研究报告
- 2025-2030中国高铁建设行业市场需求供给分析及投资评估规划分析研究报告
- 2026年法务专员面试问题及答案
- 2026年山东司法警官职业学院高职单招职业适应性考试备考题库及答案详解
- 2026年市场调查专员的面试技巧与问题解析
- 2026年重庆城市科技学院单招职业技能笔试备考题库及答案详解
- 2025年赤峰市阿鲁科尔沁旗留置保安员笔试真题附答案解析
- 福建省宁德市2024-2025学年九年级上学期期末考试道德与法治试题
- 结构件检验标准手册
- 小学地震应急疏散演练
- 个体工商户登记(备案)申请书
- 篮球原地投篮教学
- 购销摄像机合同范本
- 电力系统经济学原理课后习题及答案
- 智能水杯行业状况分析报告
- 电力部门春节安全生产培训
- 公司财务部门工作职责
- 人教版九年级数学上册22 3 3拱桥问题和运动中的抛物线 一课一练 (含答案)
评论
0/150
提交评论