单片机原理与c51编程课件3第三章 C51程序设计.ppt
《单片机原理与c51编程课件3第三章 C51程序设计.ppt》由会员分享,可在线阅读,更多相关《单片机原理与c51编程课件3第三章 C51程序设计.ppt(98页珍藏版)》请在三一文库上搜索。
1、第章 C51单片机编程语言,3.1 单片机编程语言概述 3.2 C51程序设计基础 3.3 函数、数组、指针的应用 3.4 C51程序设计,3.1 单片机编程语言概述,51单片机的编程语言可以是汇编语言,也可以是高级语言,如由C语言演变而成的C51语言等。 汇编语言产生的目标代码短,占用的存储空间小,执行速度快,能充分发挥单片机的硬件功能。但对于复杂的应用来讲使用汇编语言编程复杂,程序的可读性和可移植性不强。 高级语言产生的目标代码长,占用的存储空间大,执行速度慢。但这是相对于汇编语言来讲的,其实C语言在大多数情况下的机器代码生成效率和汇编语言相当,但可读性和可移植性却远远超过汇编语言,编程效
2、率也大大高于汇编语言。,如果应用系统的存储空间比较小,且对实时性的要求很高,则应选用汇编语言。如果系统的存储空间比较大,且对实时性的要求不是很高,则应选用C51语言。如果系统中有部分模块对实时性的要求很高,而其它模块对实时性的要求不是很高,则可以将两种语言结合,程序的主体部分使用C51编程,对实时性的要求高的模块用汇编语言编程,然后将汇编语言程序模块嵌入到C51语言程序当中。 无论是高级语言还是汇编语言写的源程序都必须转换成目标程序,单片机才能执行。目前很多公司都将编辑器、汇编器、编译器、连接/定位器、符号转换程序做成了软件包,称为集成开发环境,如Keil uVision、MedWin等。,3
3、.1 单片机编程语言概述,使用C语言有以下的优点: C 语言具有结构化和模块化特点,便于阅读和维护。 C 语言可移植性好,很多微控制器都支持C 编译器。功能化的代码能够很方便的从一个工程移植到另一个工程,从而减少了开发时间。 C 语言编写的程序比汇编语言编写的程序更符合人们的思考习惯,开发者可以更专心的考虑算法,而不是考虑一些细节问题。这样可以减少编程出错的机率,从而提高开发效率,减少调试的时间。 C 语言和微控制器是相对独立的,开发者不必知道处理器的具体内部结构和处理过程。当基于新型的微控制器开发程序时,可以很快上手,减少学习时间和程序开发时间。,3.2 C51程序设计基础,3.2.1 C5
4、1扩展关键字,3.2.1 C51扩展关键字,位运算符,例:unsigned char x=0x55 ; unsigned char y=0x37 ; unsigned char z; z=x 则 z=0x2A,位运算符举例,3.2.2 C51数据类型,3.2.2 C51数据类型,3.2.3 常量及变量,在C51中变量定义的格式如下: 存储种类 数据类型 存储器类型 变量名表; 变量定义中可使用的存储种类(Storage Classes)有四种: 自动(auto) 外部(extern) 静态(static) 寄存器(register) 变量定义时,如果省略存储种类选项,则该变量将为自动(auto
5、)变量(默认)。,auto 类型: 在定义它的函数体内部有效; 进入定义它的函数体时动态分配内存,退出函数体时所占用的内存区域被释放(局部变量); 变量的默认存储种类。 register类型: 作用域与寿命和auto型相同; 编译器尽可能将该类变量放在CPU的寄存器中,以提高存储速度。通常选择访问频率较高的变量定义为该类型,以提高效率。,存储种类,extern类型 可以在一个应用的多个程序文件中均有效; 存放在内存的静态存储区。直到该程序结束,分配的内存才被释放(全局变量)。可在函数间传递信息,在函数内被修改时,修改值会传递给其它函数。 static类型 局部变量 作用域与auto类相同; 寿
6、命与extern类相同。数据值在两次调用之间一直保持,占用的内存空间在程序结束才释放。 全局变量 仅在定义它的程序文件内有效; 寿命与extern类相同。作用范围受限的全局变量,仅在定义它的文件中有效。,存储种类,存储区域,8051系列微处理器采用了哈佛结构,即程序存储器和数据存储器是分离的。8051系列微处理器提供了三种不同类型的存储区域(memory areas): 程序存储区(program memory) 内部数据存储区(internal data memory) 外部数据存储区(external data memory) 这三种存储区域均从地址0开始编址,通过采用不同的寻址指令来解决
7、地址重叠的问题。,存储区域的划分,存储器类型的变量声明举例,char data var1; char code text = “ENTER PARAMETER:“; unsigned long xdata array100; float idata x,y,z; unsigned int pdata dimension; unsigned char xdata vector1044; char bdata flags;,说明:声明变量时存储区修饰符和数据类型修饰符的位置可以互换,即char data x; 和 data char x; 是完全等效的。不过从兼容性考虑,建议使用前一种格式。,存储
8、模式(memory models),如果在变量声明时未声明变量的存储器类型,则该变量的存储器类型,由程序的存储模式来决定。 小模式(small model):默认data区 紧凑模式(compact model):默认pdata区 大模式(large model):默认xdata区 注意:除非应用在特殊的场合,否则SMALL存储模式可以提供最快和最有效的代码。,3.2.4 C51中的特殊数据类型,C51中有几种ANSI C所没有的特殊数据类型,这些数据类型是和存储区域和存储器类型的概念密切相关的。 位变量 可位寻址的对象 特殊功能寄存器,位变量,位变量(Bit Types)是指用一个二进制位表
9、示的变量。位数据类型可以用来说明变量,参数表,函数返回值等。位数据变量声明和基本的数据类型声明一样。 所有的位变量都存储在内部数据区的位寻址段中。因为该段只有16个字节长,所以在一个作用域内最多只能声明128个位变量。 注意:由于位变量只能存储在内部数据存储区的位变量区内,因此只能使用data 和idata两种存储器类型修饰符,其它存储器类型是非法的。,例 3.15 位变量的使用 static bit done_flag = 0; /* 位变量 */ bit testfunc ( /*位函数返回类型 */ bit flag1, /*位类型参数 */ bit flag2 ) return (0)
10、; /* 位类型返回值 */ ,特殊功能寄存器,8051系列的微控制器提供了一个独立的内存区,用来存放特殊功能寄存器(special function register, SFR)。 SFR用来在程序中控制定时器,计数器,串行I/O,端口I/O操作,以及外设的操作。SFR驻留在地址0X80到0XFF空间,可按字节寻址或按字寻址,某些寄存器还可以按位寻址。 8051系列微控制器中SFR的个数和类型是变化的。C51没有预先定义SFR的名字,而是提供了许多8051兼容芯片的包含文件,这些文件对芯片的SFR进行了定义。CX51编译器用sfr,sfr16,sbit来进行SFR定义。,sfr:定义8位特殊
11、功能寄存器 sfr可以用来定义8051单片机的8位特殊功能寄存器。sfr占用一个字节内存单元,取值范围是0 255。 SFR的声明和C变量的声明格式是一样的,只不过使用的修饰符不是char 或int 而是sfr。 例如: sfr P0 = 0x80; /* Port-0, address 80h */ sfr P1 = 0x90; /* Port-1, address 90h */ sfr P2 = 0xA0; /* Port-2, address 0A0h */ sfr P3 = 0xB0; /* Port-3, address 0B0h */ P0,P1,P2,P3是sfr声明的特殊功能寄
12、存器的名称。特殊功能寄存器名称是一个合法的C标识符。等号后的地址必须是数值常量,不允许使用带运算符的表达式。,sfr16:定义16位特殊功能寄存器 8051芯片可以将两个8位SFR作为一个16位寄存器来访问。条件是这两个SFR必须处在相邻地址上,并且是低字节在高字节地址的前面。 C51提供了sfr16数据类型来进行16位特殊功能寄存器的声明,声明时低字节地址被用来作为sfr16的地址。 例如: sfr16 T2 = 0xCC; /* Timer 2: T2L 0CCh, T2H 0CDh */ sfr16 RCAP2 = 0xCA;/* RCAP2L 0CAh, RCAP2H 0CBh */
13、在这个例子中,T2和RCAP2被声明为16位的特殊功能寄存器。 sfr16声明和sfr声明的规则相同。,sbit:定义特殊功能位 sbit用来访问SFR中的可寻址位和其它可位寻址对象的可寻址位。 在8051应用中,经常需要对SFR中的可寻址位(特殊功能位)进行独立访问。可以用sbit数据类型来将SFR中的可寻址位声明为特殊功能位。 sbit EA = 0xAF; 上例中将EA定义为地址0XAF,对8051而言这是中断使能寄存器(IE)的中断许可位。,有三种方法来声明位地址: 方法一: sfr_name int_constant,即SFR寄存器名整形常量。 这种方法使用已经定义的sfr作为sbi
14、t的基地址。该SFR的地址必须能被8整除,符号后的表达式定义了可寻址位的位地址。位地址必须是0-7之间的数。 sfr PSW = 0xD0; /声明寄存器名 sfr IE = 0xA8; sbit OV = PSW 2; /声明特殊功能位 sbit CY = PSW 7; sbit EA = IE 7;,方法二: int_constant int_constant,即整形常量整形常量。 这种方法使用整形常数作为基地址。该地址必须可以被8整除,符号后的表达式定义了可寻址位的位地址。位地址必须是0-7之间的数。 sbit OV = 0xD0 2; sbit CY = 0xD0 7; sbit EA
15、 = 0xA8 7; 方法三:int_constant 用绝对位地址来声明sbit。 sbit OV = 0xD2; sbit CY = 0xD7; sbit EA = 0xAF;,注意:sbit、bit和位域是三种不同的数据类型。使用sbit声明时,基对象必须可位寻址变量或者是可以位寻址的特殊功能寄存器。,绝对变量地址,开发者有时候希望把变量存储在指定的地址单元中。可用 _at_ 关键词来将变量定位在一个绝对的内存地址单元。 使用方法如下: 数据类型 存储器类型 变量名 _at_ 变量所在绝对地址; 在 _at_ 后面的绝对地址必须符合存储器类型的物理边界限制,即不超过存储区域的最大可寻址范
16、围,该地址必须为常数。,绝对变量定位遵循以下约束: 绝对变量不能初始化。 类型为bit的函数和变量不能用绝对地址定位。 绝对变量必须是全局变量,不能是局部变量。,例3.18 struct link struct link idata *next; char code *test; ; struct link list idata _at_ 0x40; /* list at idata 0x40 */ char xdata text256 _at_ 0xE000; /* array at xdata 0xE000 */ int xdata i1 _at_ 0x8000; /* i1 at xda
17、ta 0x8000 */ void main ( void ) list.next = (void *) 0; i1 = 0x1234; text 0 = a; ,有时需要在不同的模块之间调用变量,可使用下列的语句来在另一个源文件中访问上例中用 _at_修饰的变量。 例3.19 struct link struct link idata *next; char code *test; ; extern struct link idata list; /* list at idata 0x40 */ extern char xdata text256; /* array at xdata 0xE
18、000 */ extern int xdata i1; /* int at xdata 0x8000 */,3.3.1 数组和指针,数组是一个由同种类型的变量组成的集合,它保存在连续的存储区域中,第一个元素保存在最低地址中,最末一个元素保存在最高地址中。 数组可以是一维的也可以是多维的。 数组的定义方式如下: 数据类型 数组名常量1常量2常量n; 这里的n是数组的维数。 在定义时可以进行数组元素的初始化,初始化的值放在 中,每个元素值用逗号分开。如果是对多维数组进行初始化,还可以使用 将元素维的大小分成组。,例如: char a23=0,1,2,3,4,5; char a23=0,1,2,3,
19、4,5; 以上两条语句的功能是相同的,执行完成后各元素的值如下: (设初始地址为ADDR),对于特殊的字符串数组,初始化时不仅可以采用每个元素分别赋值,还可以以字符串的形式赋值。如 char array20=”hello world”; 还可以使维数的大小为空,由初始化字串的长度决定数组的长度。如 char array =”hello world”; 上例中,数组array的长度为12个字节(字符串赋值时会增加一个0字符,作为字符串的结束标志)。,注意: C语言中的数组元素的下标总是从0开始的。 多维数组在内存中保存时,下标1变化最慢,下标n变化最快。,指针与地址的概念,程序中的变量经过编译处
20、理后都对应着内存中的一个地址。编译器根据变量的类型,为其分配不同大小的内存单元来存放变量的数据。 所谓指针,就是某个变量所占用存储单元的首地址。用来存放指针值的变量称为指针变量。 指针变量的定义格式如下: 类型说明符 存储器类型 *指针变量名 其中:“*”表示定义的是指针变量,类型说明符表示该指针变量指向的变量的类型。,C51的指针和标准C中的指针功能相同。但是由于8051体系结构的特殊性,C51提供了两种不同类型的指针: 通用指针(Generic Pointers) 具体指针(Memory-specific Pointers)。 通用指针的声明是和标准C中的指针声明是相同的,例如: char
21、 *s; /* 指向字符类型的指针 */ int *numptr; /* 指向整型类型的指针*/ long *state; /* 指向长整型类型的指针 */,通用指针总是占用三个字节。 第1个字节保存存储器类型编码值, 第2个字节保存地址的高字节, 第3 个字节保存地址的低字节。 许多C51的库例程使用这种指针类型,通用指针类型可以访问任何存储区域内变量。,具体指针是在声明时指定了存储器类型的指针,是指向特定存储区域中的指针变量。 char data *str; /* ptr to string in data */ int xdata *numtab; /* ptr to int(s) in
22、 xdata */ long code *powtab; /* ptr to long(s) in code */ 具体指针不需要保存存储器类型字节。具体指针可以保存在一个字节(idata, data, bdata, pdata类型指针)或2个字节(code 和xdata类型指针)中。 具体指针可以用来访问8051声明的存储区内的变量。具体指针的效率高,但灵活性较差。,指定具体指针本身的存储类型的定义,例: char data * xdata ptr; /* ptr in xdata to data char */ int xdata * data numtab; /* numtab in d
23、ata to xdata int */ long code * idata powtab; /* powtab in idata to code long */ 注意:本例中变量定义时使用了两个存储器类型,*前的存储器类型修饰指针指向的数据,*后的存储器类型修饰指针本身,即指针所占据的存储区域类型。,注意:完成相同的功能,使用通用指针类型的代码与使用具体指针类型的代码相比,前者的运行速度要慢很多。 原因:这是因为通用指针类型只有在程序运行时才能知道实际的变量存储区类型,因此编译器就不能对内存访问进行优化,从而只能生成可以访问任意存储区的通用代码。如果必须优先考虑程序的运行速度,那么只要有可能就
24、应该使用具体指针来替代通用指针,指针变量的引用,在利用指针变量进行间接访问时,必须使它指向一个确定的变量。指针变量只能存放地址,不能将一个非地址量赋给指针变量。 C语言中有两个与指针相关的运算符: *:指针运算符,作用是通过指针变量间接访问它所指向的变量,来存取数据。 &:取地址运算符,作用是取得变量所占用存储单元的首地址,即指针。,例子,数组的指针 一个数组包含多个元素,每个数组元素都在内存中占用存储单元,都有相应的地址,并且这些存储单元都是连续的。指针变量可以指向数组和数组的任意元素。 引用数组元素可以使用: 下标法(即 运算符和对应元素的下标) 指针法(即通过指向数组元素的指针找到所需元
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机原理与c51编程课件3第三章 C51程序设计 单片机 原理 c51 编程 课件 第三 程序设计
链接地址:https://www.31doc.com/p-3037473.html