




已阅读5页,还剩133页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1,04:02,单片机原理与接口技术,第5章 mcs-51单片机 c51程序设计,2,04:02,(1) 熟悉c51语法基础和程序结构。 (2) 掌握c51结构化程序设计。 (3) 掌握c51对单片机硬件的访问方法。 (4) 掌握c51函数定义与调用。 (5) 了解汇编语言和c51的混合编程。,本章教学要求,3,04:02,5.1 c51概述 5.2 c51语法基础 5.2.1 标识符和关键字 5.2.2 数据类型 5.2.3 运算符和表达式 5.2.4 程序结构,本 章 目 录,5.3 c51对mcs-51单片机的访问 5.3.1 存储类型 5.3.2 存储模式 5.3.3 对特殊功能寄存器的访问 5.3.4 对存储器和并行口的访问 5.3.5 位地址访问,4,04:02,5.4 c51函数 5.4.1 函数的分类 5.4.2 函数的定义 5.4.3 函数的调用 5.4.4 对被调函数的说明 5.4.5 中断函数 5.5 c51结构化程序设计 5.5.1 顺序结构程序 5.5.2 选择结构程序,5.5.3 循环结构程序 5.6 c51程序设计实例 5.6.1 查表程序 5.6.2 单片机内/外部资源应用程序设计 5.6.3 c51语言和mcs-51汇编语言混合编程 5.6.4 编程优化的概念 习题与思考题,本 章 目 录,5,04:02,5.1 c51概述,c语言是一种通用的程序设计语言,其代码率高,数据类型及运算符丰富,位操作能力强,适用于各种应用的程序设计。使用c语言进行单片机应用系统开发,具有编程灵活、调试方便、目标代码编译效率高的特点。c语言也是目前使用最广的单片机应用系统编程语言。 由c语言编程的单片机应用程序,称为单片机c语言程序。mcs-51系列单片机开发系统的编译软件可以对51单片机c语言源程序进行编译,称为c51编译器。在c51编译软件中可进行51单片机c语言程序的调试。,6,04:02,1) 扩展了专门访问mcs-51单片机硬件的数据类型; 2) 存储类型按mcs-51单片机存储空间分类; 3) 存储模式遵循存储空间选定编译器模式; 4) 指针分为通用指针和存储器指针; 5) 函数增加了中断函数和再入函数。,5.1 c51概述,c51编译器针对mcs-51单片机硬件在下列几方面对ansi c进行了扩展。,7,04:02,使用具有c51编译扩展功能的c语言进行mcs-51单片机应用系统的开发编程,简称c51编程。c51编程具有以下特点。 1) 可管理内部寄存器和存储器的分配,编程时,无需考虑不同存储器的寻址和数据类型等细节问题; 2) 程序由若干函数组成,具有良好的模块化结构、可移植性好、便于项目维护管理; 3) 有丰富的子程序库可直接引用,从而大大减少用户编程工作量,提高编程效率; 4) 与汇编语言交叉编程。用汇编语言编写与硬件有关的程序,用c51编写与硬件无关的运算程序,充分发挥两种语言的长处,提高开发效率。,5.1 c51概述,8,04:02,c51编程和汇编语言编程过程一样。单片机c语言源程序经过编辑、编译、连接后生成目标程序(.bin和.hex)文件,然后运行即可。调试51单片机c语言程序可用keil c51编译器。 注意,使用c51编程可以取代繁琐的汇编语言编程,但仍需要了解mcs-51单片机的硬件结构。所以对于单片机系统的开发应采用汇编语言与c51混合编程的方法更为有效。,5.1 c51概述,9,04:02,5.2 c51 语法基础,标识符用来标识源程序中某个对象的名字,这些对象可以是语句、数据类型、函数、变量、数组等。 标识符由字符串、数字和下划线等组成,应该注意的是第一个字符必须是字母或下划线,不能用数字开头,如“1_a”是错误的,编译时会有错误提示。在c51编译器中,只支持标识符的前32位为有效标识。 c51语言是区分大小写的一种高级语言,如“a_1”和“a_1”是两个完全不同的标识符。,5.2.1 标识符和关键字,-标识符,10,04:02,c51中有些库函数的标识符是以下划线开头的,所以一般不要以下划线开头命名用户自定义标识符。标识符在命名时应当简单,含义清晰,这样有助于阅读理解程序。 关键字则是编程语言保留的特殊标识符,它们具有固定的名称和含义,在程序编写中不允许将关键字另做他用。c51中的关键字除了有ansi c标准的32个关键字外,还根据mcs-51单片机的特点扩展了相关的关键字。c51关键字如表5-1所示。 在c51的文本编辑器中编写c程序,系统可以把保留关键字以不同颜色显示,如int关键字的默认颜色为天蓝色。,5.2.1 标识符和关键字,-关键字,11,04:02,5.2.1 标识符和关键字,-关键字列表,12,04:02,5.2.1 标识符和关键字,-关键字列表,13,04:02,5.2.1 标识符和关键字,-关键字列表,14,04:02,5.2.2 数据类型,c51具有ansi c的所有标准数据类型。 其基本数据类型包括:char、int、short、long、float和double。 对c51编译器来说,short类型和int类型相同,double类型和float类型相同。,-c51的数据类型,15,04:02,除此之外,为了更加有利地利用mcs-51的结构,c51还增加了一些特殊的数据类型,包括bit、sbit、sfr、sfr16。数据类型如表5-2所示。,5.2.2 数据类型,-c51的数据类型,16,04:02,char类型的长度是1b,通常用于定义处理字符数据的变量或常量。 unsigned char类型用字节中所有的位表示数值,可以表达的数值范围是0255。 signed char类型用字节中最高位表示数据的符号,0表示正数,1表示负数,负数用补码表示,能表示的数值范围是-128+127。unsigned char常用于处理ascii字符或用于处理小于或等于255的整型数。,1char字符类型,5.2.2 数据类型,-char字符类型,17,04:02,2int整型,int整型长度为2b,用于存放一个双字节数据。 signed int表示的数值范围是-32768+32767,字节中最高位表示数据的符号,0表示正数,1表示负数。 unsigned int表示的数值范围是065535。,5.2.2 数据类型,-int整型,18,04:02,long长整型长度为4b,用于存放一个四字节数据。 分有符号long长整型signed long和无符号long长整型unsigned long,默认值为signed long类型。 signed int表示的数值范围是-2147483648+2147483647,字节中最高位表示数据的符号,0表示正数,1表示负数。 unsigned long表示的数值范围是04294967295。,3long长整型,5.2.2 数据类型,-long长整型,19,04:02,4float浮点型,float浮点型在十进制中具有7位有效数字,是符合ieee-754标准(32)的单精度浮点型数据,占用4b。具有24位精度。,5.2.2 数据类型,-float浮点型,20,04:02,5*指针型,指针型本身就是一个变量,在这个变量中存放着指向另一个数据的地址。这个指针变量要占据一定的内存单元,对不同的处理器长度也不尽相同,在c51中它的长度一般为13个字节。,5.2.2 数据类型,-*指针型,21,04:02,bit位标量是c51编译器的一种扩充数据类型,利用它可定义一个位标量。它的值是一个二进制位,不是0,就是1,类似一些高级语言中的boolean型数据的true和false。,6bit位标量,5.2.2 数据类型,-bit位标量,22,04:02,7sfr特殊功能寄存器,sfr是一种c51扩充数据类型,占用一个内存单元,值域为0255。 利用它可以访问mcs-51单片机内部的所有特殊功能寄存器。 如用sfr p1 = 0x90定义一个特殊功能寄存器变量“p1”,0x90是指51单片机的p1端口地址90h,变量p1即指51单片机的p1端口。 在后面的语句中可以用p1 = 255(对p1端口的所有引脚置高电平)之类的语句操作特殊功能寄存器。,5.2.2 数据类型,-sfr特殊功能寄存器,23,04:02,8. sfr16 16位特殊功能寄存器,sfr16也是一种c51扩充数据类型,用于定义存在于mcs-51单片机内部ram的16位特殊功能寄存器,如定时器t0和t1。 sfr16型数据占用2个内存单元,取值范围为065535。,5.2.2 数据类型,-16位特殊功能寄存器,24,04:02,sbit也是一种c51扩充数据类型,利用它可以访问芯片内部ram中的可寻址位或特殊功能寄存器中的可寻址位。定义方法有如下三种: (1)sbit 位变量名 = 位地址 将位的绝对地址赋给位变量,位地址必须位于80hffh(特殊功能寄存器的位地址)之间。 (2)sbit 位变量名 = 特殊功能寄存器名位位置 当可寻址位位于特殊功能寄存器中时,可采用这种方法。位位置是一个07之间的常数。 (3)sbit 位变量名 = 字节地址位位置 这种方法是以一个常数(字节地址)作为基地址,该常数必须在80hffh(特殊功能寄存器的字节地址)之间。位位置是一个07之间的常数。,9sbit可寻址位,5.2.2 数据类型,-sbit可寻址位,25,04:02,mcs-51单片机中的特殊功能寄存器及其可寻址位,已被预先定义放在文件reg51.h中,在程序的开头只需加上#include或#include即可。 另外,bit还可访问mcs-51单片机片内20h2fh范围内的位对象。c51编译器提供了一个bdata存储器类型,允许将具有bdata类型的对象放入mcs-51单片机片内可位寻址区。,5.2.2 数据类型,-reg51.h,26,04:02,sbit和bit的区别: sbit定义特殊功能寄存器中的可寻址位;而bit则定义了一个普通的位变量,一个函数中可包含bit类型的参数,函数返回值也可为bit类型。,5.2.2 数据类型,-sbit和bit,27,04:02,5.2.3 运算符和表达式,c51算术运算符有五种: + 加法运算符或正号 - 减法运算符或负号 * 乘法运算符 / 除法运算符 % 模(求余)运算符 优先级:先乘除,后加减,先括号内,再括号外。 结合性:自左至右方向。 模运算即求余数,如,7%3,结果是7除以3所得余数1。,1c51的算术运算符,-算术运算符,28,04:02,c51关系运算符有六种: 大于 = 大于等于 = = 相等 ! = 不相等 优先级:前四个高,后两个“= =”和“! =”级别低。 结合性:自左至右方向。 关系表达式的结果是逻辑值“真”或“假”,c51中以“1”代表真,“0”代表假。,2c51关系运算符,5.2.3 运算符和表达式,-关系运算符,29,04:02,c51逻辑运算符有三种: & 逻辑与 | 逻辑或 ! 逻辑非 优先级:逻辑非“!”最高。 结合性:“&”和“|”自左至右方向。“!”自右至左方向。 运算符的两边为关系表达式。逻辑表达式和关系表达式的值相同,以“0”代表假,以“1”代表真。,3c51逻辑运算符,5.2.3 运算符和表达式,-逻辑运算符,30,04:02,c51按位操作运算符有六种: & 按位与 位取反 | 按位或 位右移 注:移位操作为补零移位。位运算符只能对整形和字符型运算,不能对实型数据运算。 如:char a = 0x0f;表达式a = a值为0xf0。 如:char a = 0x22;表达式a2值为0x88,即a值左移两位,移位后空白位补0。,-位操作运算符,5.2.3 运算符和表达式,4c51位操作运算符,31,04:02,+ 自增1 - 自减1 自增、自减运算符可以在变量的前面或后面使用。 如,+i或-i,意为在使用i之前,先使i值加1或减1。 如,i+或i-,意为在使用变量i之后,再使i值加1或减1。 例如,定义整型变量:int i=6,并有j=+i,则j值为7,i值也为7。而如有j=i+,则j值为6,i值为7。,5自增、自减运算符,5.2.3 运算符和表达式,- + -运算符,32,04:02,6赋值运算符, 赋值 将“”右边的值赋给“”左边的变量(注:不是相等运算符)。,5.2.3 运算符和表达式,-赋值运算符,33,04:02,c51提供了十种复合赋值运算符: += -= *= /= %= = &= = |= 采用符合赋值运算的目的是为了简化程序,提高c51程序的编译效率。 例:a+=b相当于a=a+b。a=b相当于a=ab。,7复合赋值运算符,5.2.3 运算符和表达式,-复合赋值运算符,34,04:02,8对指针操作的运算符,& 取地址运算符 * 指针运算符 注意&与*的用法意义如下: “&”与按位与运算符的差别。如果“&”为“与”运算,&运算符的两边必须为变量或常量,如a=c&b。“&”是取地址运算时,如a=&b。 “*”与指针定义时指针前的“*”的差别。如char *pt,这里的“*”只表示pt为指针变量,不代表间址取内容的运算。而c=*b,是将以b的内容为地址的单元内容送c变量。 c51运算的优先级: !(非)算术运算关系运算&和|赋值运算,5.2.3 运算符和表达式,-指针操作的运算符,35,04:02,5.2.4 程序结构,与ansi c一样,c51的程序是一个函数定义的集合,可以由任意个函数构成,其中必须有一个主函数main( )。 程序的执行是从主函数main( )开始的,调用其他函数后返回主函数main( ),最后在主函数中结束整个程序,而不管函数的排列顺序如何。,-函数定义的集合,36,04:02,全局变量说明 /*可被各函数引用*/ 类型说明 main( ) /*主函数*/ 声明部分 语句部分 类型说明 函数名1(形式参数表) /*函数1*/ 声明部分 语句部分 类型说明 函数名n(形式参数表) /*函数n*/ 声明部分 语句部分 ,5.2.4 程序结构,-程序的组成,37,04:02,5.3 c51对mcs-51单片机的访问,mcs-51单片机的存储器分为片内数据存储器、特殊功能寄存器、片外数据存储器、片内程序存储器和片外程序存储器。 在c51中访问这些存储器时,是通过定义不同存储类型的变量,以说明该变量所访问的存储器位置。,5.3.1 存储类型,-c51访问存储器,38,04:02,1data存储类型 data存储类型变量可直接寻址片内数据存储区ram(128字节),访问速度快。 2bdata存储类型 bdata存储类型变量可位寻址片内数据存储区ram(16个字节),允许位与字节混合访问。 3idata存储类型 idata存储类型变量可间接寻址内部数据存储区,可访问全部内部地址空间(00ffh,256字节)。,5.3.1 存储类型,-定义存储类型,39,04:02,4pdata存储类型 pdata存储类型变量可以分页(256 b)寻址由指令movx ri访问的片外ram空间。 5xdata存储类型 xdata存储类型变量可以寻址由指令movx dptr访问的64 kb片外ram空间。 6code存储类型 code存储类型变量可以寻址由指令movc a+dptr访问的64 kb片内外rom空间。,-定义存储类型,5.3.1 存储类型,40,04:02,5.3.2 存储模式,存储模式决定了变量的默认存储类型和参数传递区,变量定义不明确存储类型时使用默认值。 c51有三种存储模式: small、large 和 compact。,-变量的存储类型,41,04:02,5.3.2 存储模式,-变量的存储类型,42,04:02,数据存储模式的设定有两种方式: (1)使用预处理命令设定数据存储模式 需在程序的第一句加预处理命令。如: #pragma small/*设定数据存储模式为小编译模式*/ #pragma compact /*设定数据存储模式为紧凑编译模式*/ #pragma large/*设定数据存储模式为大编译模式*/ (2)使用编译控制命令设定数据存储模式 用c51编译程序对c51源程序进行编译时,使用编译控制命令,格式如下: c51 源程序名 small c51 源程序名 compact c51 源程序名 large,5.3.2 存储模式,-存储模式的设定,43,04:02,例如:c51源程序为file1.c,若使程序中的变量存储类型和参数传递区限定在外部数据存储区,即设定数据存储模式为compact(紧凑编译模式)。 方法1:在程序的第一句加预处理命令: #pragma compact。 方法2:用c51对file1.c进行编译时,使用编译控制命令: c51 file1.c compact。,5.3.2 存储模式,-存储模式的设定,44,04:02,5.3.2 存储模式,【例5-1】 变量和函数的存储模式设置 #pragma small /*默认存储类型为mcs-51直接寻址片内ram*/ char data i, j, k; /*在mcs-51片内直接寻址ram中定义了3个变量,默认为自动变量*/ char i, j, k; /*未指明存储类型,由#pragma small决定,与前一句完全等价*/ int xdata m, n; /*在mcs-51片外ram中定义了两个自动变量*/ static char m, n; /*在mcs-51片内直接寻址ram中定义了两个静态变量*/,-存储模式举例,45,04:02,unsigned char xdata ram10; /*在mcs-51片外ram中定 义了大小为10 b的数组变量*/ int func1(int i, int j) large /*指定函数中变量是large 模式*/ return(i+j); int func2(int i, int j) /*未指明存储模式,按默认的 small模式*/ return(i-j); ,5.3.2 存储模式,-存储模式举例,46,04:02,5.3.3 特殊功能寄存器的访问,mcs-51系列单片机片内有21个特殊功能寄存器(sfr),分散在片内ram区的0x800xff地址范围内。对sfr的操作只能用直接寻址方式。 为了能直接访问这些特殊功能寄存器,c51提供了定义sfr的方法。这与ansi c不兼容,只适用于mcs-51系列单片机。,-定义sfr的方法,47,04:02,-sfr数据类型,用sfr定义特殊功能寄存器名的语法如下: sfr 特殊功能寄存器名=整型常量; 例如: sfr psw=0xd0; /*定义程序状态字psw, 因mcs-51 单片机的psw 地址为d0h*/ sfr tmod=0x89; /*定义定时/计数器方式控制寄存 器tmod, 因mcs-51单片机的tmod地址为89h*/ sfr p1=0x90; /*定义p1口, 因mcs-51单片机的p1 口地址为 90h*/ sfr scon=0x98; /*定义串口控制寄存器scon, 因 mcs-51单片机的scon地址为8h*/,5.3.3 特殊功能寄存器的访问,1用sfr数据类型访问特殊功能寄存器,48,04:02,2用sbit数据类型访问可位寻址的特殊功能寄存器中的位,mcs-51系列单片机片内21个特殊功能寄存器(sfr)中有11个特殊功能寄存器是可位寻址的。访问这些可位寻址的特殊功能寄存器中的位的方法可由关键字sbit定义特殊功能寄存器位寻址数据类型来实现。定义特殊功能寄存器位名的语法有下列三种:,5.3.3 特殊功能寄存器的访问,-sbit数据类型,49,04:02,sbit 特殊功能寄存器位名=特殊功能寄存器名整型常量 其中,特殊功能寄存器名是已由sfr定义了的特殊功能寄存器名,整型常量是位可寻址特殊功能寄存器中的位(是一个07之间的常数)。 sbit 特殊功能寄存器位名=整型常量1整型常量2 其中,整型常量1是指可位寻址特殊功能寄存器的字节地址(在80hffh之间),整型常量2是指该寄存器中的位(是一个07之间的常数)。 sbit 特殊功能寄存器位名=整型常量 其中,整型常量是可位寻址特殊功能寄存器的绝对位地址(位于80hffh之间)。,5.3.3 特殊功能寄存器的访问,-定义方法,50,04:02,5.3.3 特殊功能寄存器的访问,sfr psw=0xd0; /*首先定义程序状态字psw, 因mcs-51单片机的psw地址为d0h*/ sbit ov=psw2; /*在前面定义了psw后,ov位于psw的 第2位*/ sbit ac=0xd06; /*d0h是程序状态字psw的字节地址, 辅助进位标志位ac位于psw的第6位*/ sbit rs0=0xd03; /*工作寄存器组控制位rs0位于psw的 第3位*/ sbit cy=0xd7; /*进位标志位cy的绝对位地址为d7h*/ 标准sfr在reg51.h、reg52.h等头文件中已经被定义,只要 用文件包含做出申明即可使用。,-实例,51,04:02,例5-2 特殊功能寄存器的访问。 #include ”reg51.h” sbit p10=p10; /*定义p10为p1口第0位,即p1.0口*/ sbit p12=p12; /*定义p12为p1口第2位,即p1.2口*/ void main( ) p10=1; /*置位p1.0口*/ p12=0; /*复位p1.2口*/ psw=0x08; /*程序状态字置0x08*/ ,5.3.3 特殊功能寄存器的访问,-应用实例,52,04:02,5.3.4 存储器和并行口的访问,mcs-51单片机片内有128个字节的ram区(00h7fh),可扩展片外64kb的rom和ram,有p0、p1、p2、p3四个8位双向并行i/o口,每个端口可以按字节输入或输出,也可以按位进行输入或输出,四个口共32根口线。 使用c51编程时,片内/外存储器、片内i/o口与片外扩展i/o口可以统一在头文件中定义,也可以在程序中进行定义(一般在程序开始的位置)。c51定义存储器、并行口方法如下。,-在头文件中定义,53,04:02,1对存储器使用绝对地址访问,c51编译器提供了一组宏定义用来对mcs-51系列单片机的code、data、pdata和xdata空间进行绝对地址访问。函数原型如下: #define cbyte(unsigned char volatile *)0x50000l) #define dbyte(unsigned char volatile *)0x40000l) #define pbyte(unsigned char volatile *)0x30000l) #define xbyte(unsigned char volatile *)0x20000l) #define cword(unsigned int volatile *)0x50000l) #define dword(unsigned int volatile *)0x40000l) #define pword(unsigned int volatile *)0x30000l) #define xword(unsigned int volatile *)0x20000l) 这些函数原型放在absacc.h文件中。,5.3.4 存储器和并行口的访问,-绝对地址访问,54,04:02,cbyte以字节形式对code区寻址,dbyte以字节形式对data区寻址,pbyte以字节形式对pdata区寻址,xbyte以字节形式对xdata区寻址,cword以字形式对code区寻址,dword以字形式对data区寻址,pword以字形式对pdata区寻址,xword以字形式对xdata区寻址。,5.3.4 存储器和并行口的访问,-绝对地址访问,55,04:02,例5-3 使用绝对地址访问存储器,#include #include #define uint unsigned int #define uchar unsigned char void main(void) uint ui_var1; uchar uc_var1; ui_var1 = xword 0x0000; /*访问外部ram的0000h0001h地址的内容*/ uc_var1 = xbyte 0x0002; /*访问外部ram的0002h地址的内容*/ xword 0x0000=0xaabb; /*将0xaabb送入外部ram的 0000h0001h 地址中*/ xbyte 0x0002=0xaa; /*将0xaa送入外部ram的0002h地址中*/ for(;); ,5.3.4 存储器和并行口的访问,-绝对地址访问,56,04:02,2对存储器使用指针访问,采用指针的方法,可实现在c51程序中对任意指定的存储器地址进行操作。 例5-4 使用指针访问存储器。 #define uchar unsigned char #define uint unsigned int void test_memory(void) uchar idata ivar1; /*定义一个指向idata存储空间的变量*/ uchar xdata *xdp; /*定义一个指向xdata存储器空间的指针*/ char data *dp; /*定义一个指向data存储器空间的指针*/,5.3.4 存储器和并行口的访问,-指针访问,57,04:02,uchar idata *idp; /*定义一个指向idata存储器空间的指针*/ xdp=0x1000; /*xdata指针赋值,指向xdata存储器地 址1000h处*/ *xdp=0x5a; /*将数据5ah送到xdata区的1000h单元*/ dp=0x61; /*data指针赋值,指向data存储器地址 61h处*/ *dp=0x23; /*将数据23h送到data区的61h单元*/ idp= /*数据16h送到idata区的变量ivar1所在的 地址单元中, 等价于ivar1=0x16*/ ,5.3.4 存储器和并行口的访问,-指针访问,58,04:02,3c51定义片内i/o口,单片机内部并行口可用关键字sfr定义,i/o口定义格式举例: sfr p0=0x80; /*定义p0口,地址80h*/ sfr p1=0x90; /*定义p1口,地址90h*/,5.3.4 存储器和并行口的访问,-sfr定义片内i/o,59,04:02,操作片内i/o口,例5-5 操作片内i/o口 sfr p1=0x90; /*定义p1口,地址90h*/ sfr p3=0xb0; /*定义p3口,地址b0h*/ sbit dipswitch=p14; /*p1口第4位(p1.4口)为dip开关的输入*/ sbit ledgreen=p35; /*p3口第5位(p3.5口)为led的输出*/ void main( ) unsigned char inval=0; for(;)if(dipswitch=1) /*检查p1.4口输入是否为高*/ inval=p1 /*p1口03位输出与p3口的03位相或输出*/ ,5.3.4 存储器和并行口的访问,60,04:02,4c51定义外部并行口,对片外扩展的i/o口,则根据其硬件译码地址,将其看作片外数据存储器的一个单元,使用#define语句进行定义。用指针定义,指针的定义在absacc.h头文件中。,5.3.4 存储器和并行口的访问,-#define语句定义片外i/o,61,04:02,操作片外i/o口,例5-6 操作片外i/o口 #include “absacc.h” #define pa xbyte0xffec /*将pa定义为外部i/o口,地址 为0xffec*/ void main( ) pa=0x5a; /*将数据5ah写入地址为0xffec 的存储单元或i/o端口*/ 在头文件或程序中对片内/外i/o口进行定义以后,在程序中就可以使用这些口了。定义口地址的目的是为了便于c51编译器按mcs-51单片机系统的实际硬件结构建立i/o口变量名与其实际地址的联系,以便程序员能用软件模拟mcs-51单片机系统的硬件操作。,5.3.4 存储器和并行口的访问,62,04:02,5.3.5 位地址访问,c51编译器支持bit数据类型,在c51程序中可以使用bit数据类型对位地址进行操作。 c51对位变量的定义有3种方法: 1用bit关键字定义c51位变量 2通过指定函数中参数为bit类变量 3定义位寻址存储区的位变量,-位变量定义,63,04:02,5.3.5 位地址访问,1用bit关键字定义c51位变量 例如: bit lock; /*将lock定义为位变量*/ bit dirention; /*将direction定义为位变量*/ bit display; /*将display定义为位变量*/ 注意:不能定义位变量指针; 也不能定义位变量数组。,-用bit定义位变量,64,04:02,例如: bit fun(bit a1,bit a2) return(a1); ,5.3.5 位地址访问,2通过指定函数中参数为bit类变量,-函数参数为位变量,65,04:02,-位寻址存储区的位变量定义,3定义位寻址存储区的位变量 c51编译器允许数据类型为bdata的变量放入片内ram可位寻址区中。 例如:先定义变量的数据类型和存储类型,然后使用sbit定义位变量。 bdata int ibdata; /* ibdata定义为bdata整型变量*/ bdata char carry5; /* carry定义为bdata字符数组*/ sbit mybit0= ibdata0; /* mybit0定义为ibdata的第0位*/ sbit mybit15= ibdata15; /* mybit15定义为ibdata的第15位*/,5.3.5 位地址访问,66,04:02,-位寻址存储区的位变量定义,sbit arrybit07= carry07; /* arrybit07定义为carry0的第7位*/ sbit arrybit37= carry37; /* arrybit37定义为carry3的第7位*/ arrybit37=0; /*carry3的第7位赋值为0(位寻址)*/ carry0=a; /*carry0赋值为a(字节寻址)*/ 位置(操作符)后的最大值取决于指定的基本数据类型。对于char而言是07;对于int而言是015;对于long而言是031。,5.3.5 位地址访问,67,04:02,5.4 c51函数,c51程序是由一个个函数构成的,在构成c51程序的若干个函数中,必须有一个主函数main( ),主函数可根据需要来调用其它函数。同一个函数可以在不同的地方被调用。,68,04:02,5.4.1 函数的分类,从用户使用角度划分,函数分为库函数和用户自定义函数。 库函数:是编译系统为用户设计的一系列标准函数,用户只需调用,而无需自己去编写这些复杂的函数。在调用前要先使用#include包含命令包含和该函数有关的头文件,然后才能调用。如前面所用到的头文件reg51.h等,每一种头文件中包括一系列函数。 用户自定义函数:是用户根据任务编写的函数。,-从用户使用角度分类,69,04:02,从函数定义形式上可划分为三种:无参函数、有参函数和空函数。 无参函数:函数中无参数定义,该函数调用时无参数传递。 有参函数:函数中定义形式参数。在调用函数时,实际参数值传递给形式参数,调用后返回结果给调用它的函数使用。 空函数:函数中无参数,也无语句。该函数可以调用但没有任何功能,该函数是为了开发程序时将一些非基本模块的功能函数定义成空函数,先占好位置,以后再用编好的函数替换它。,5.4.1 函数的分类,-从函数定义形式分类,70,04:02,5.4.2 函数的定义,函数类型 函数名 ( ) 函数体语句 如果函数没有返回值,可以将返回值类型设为void,函数以“”开始,以“”结束。,1无参函数的定义,-无参函数定义,71,04:02,例5-7 无参函数的定义与调用。 #include void fun1( ) printf(“this is a c51 programn”); void main( ) fun1( ); ,5.4.2 函数的定义,-无参函数定义,72,04:02,2有参函数的定义,函数类型 函数名 (形式参数表列) 函数体语句 return (返回形参名) 其中形式参数表列的各项要用“,”隔开,通过return语句将需返回的值返回给调用函数。,5.4.2 函数的定义,-有参函数定义,73,04:02,例5-8 有参函数的定义与调用。 void fun2(int a, int b ) int sum; sum=a+b; return sum; void main() int x=123, y=456, sum; sum=fun2(x,y); ,5.4.2 函数的定义,-有参函数定义,74,04:02,-空函数定义,3空函数的定义 函数类型 函数名 ( ) 函数可以将返回值类型设为void。 例5-9 空函数的定义与调用。 void fun3( ) void main( ) fun3( ); ,5.4.2 函数的定义,75,04:02,5.4.3 函数的调用,函数调用的一般形式为: 函数名 (实际参数表列); 函数的调用方式有三种: 1) 把被调函数作为主调函数中的一个语句。 例如 fun1( ); 2) 把被调函数作为表达式的一个运算对象。 例如 sum=2* fun2(x, y); 3) 把被调函数作为另一个函数的参数。 例如 printf(“sum is %dn”, fun2(x, y);,-函数调用形式,76,04:02,5.4.4 对被调函数的说明,函数调用必须具有以下条件: 1) 被调用函数必须是已经存在的函数(库函数和用户自定义函数)。 2) 调用库函数需要#include包含和该函数有关的头文件,然后才能调用。 3) 调用用户自定义函数,如果被调函数出现在主调函数之后,在主调函数前应对被调函数作声明。形式为: 函数类型 函数名 (形参表列);,-函数调用条件,77,04:02,例5-10 函数的定义与声明 void main() /*主函数*/ int fun1(int a, int b); /*函数声明*/ int d, u=3, v=2; d=2*fun1(u, v); int fun1(int a, int b) /*函数定义*/ int c; c=a+b; return(c); ,5.4.4 对被调函数的说明,-函数的定义与声明,78,04:02,int fun1(int a, int b) int c; c=a+b; return(c); void main() int d, u=3, v=2; d=2* fun1(u, v); ,5.4.4 对被调函数的说明,-函数的定义与声明,上例中被调函数在主调函数之后,在主调函数一开始对被调函数进行了声明。若被调函数出现在主调函数之前时,可以不对被调函数进行声明。上例可修改为:,79,04:02,5.4.5 中断函数,中断服务程序在c51程序中是以中断函数的形式出现的,中断函数的格式为: void 函数名( ) interrupt n using m 函数体语句 interrupt是中断函数的关键字,n是中断号,mcs-51的中断号与中断源的对应关系如表5-5所示。 using是指定中断函数中选用工作寄存器组的关键字,m是03范围的常数,若不用该选项,编译器会自动选择默认工作寄存器组(0组寄存器)。,-中断函数的格式,80,04:02,表5-5 mcs-51中断源和中断的关系,void 函数名( ) interrupt n using m,5.4.5 中断函数,-中断函数的中断号,81,04:02,例: void t0_srv(void) interrupt 1 using 1 /*定时/计数器0中断函数*/ /*定时/计数器0中断服务程序*/ ,5.4.5 中断函数,-中断函数举例,82,04:02,编写中断函数要点: 1) 中断函数不能进行参数传递。 2) 中断函数没有返回值,应定义为void型。 3) 禁止对中断函数的直接调用。 4) 如果中断函数调用了其他函数,被调函数与中断函数使用相同的寄存器组。 5) 中断函数最好写在程序尾部。,void 函数名( ) interrupt n using m,5.4.5 中断函数,-编写中断函数要点,83,04:02,5.5 c51结构化程序设计,c51程序是一种结构化程序,由若干模块组成,每个模块中包含若干个基本结构,而每个基本结构中可以有若干条语句。 基本结构有三种: 顺序结构 选择结构 循环结构,- 三种结构程序,84,04:02,顺序结构是一种最基本、最简单的程序结构。在这种结构中,语句被依次逐条地顺序执行。 例5-11 一乘法程序,乘积放在外部ram的0000h单元。 void main( ) unsigned long xdata *p; /*设定p是指向外部ram 区的unsigned long指针*/ unsigned long x=12345, y=67890, mum; mum=x*y; p=0; /*p指向外部ram区0000h单元*/ *p=mum; /*乘积存入外部ram区0000h单元*/ ,5.5.1 顺序结构程序,- 顺序结构,85,04:02,5.5.2 选择结构程序,用if语句可以构成选择结构。它根据给定的条件进行判断,以决定执行某个分支程序段。语言的if语句有三种基本形式。 1单分支语句 if (条件表达式) 语句组;,其语义是:如果条件表达式的值为真,则执行其后的语句组,否则不执行其后的语句组。单分支语句执行过程可表示为图5-1所示。,-单分支结构,86,04:02,-单分支结构举例,例5-12 寻找两个数中的大数输出 void main() unsigned xdata *p; unsigned a=35, b=78, max; max=a; if (maxb) max=b; p=0; /*p指向外部ram区0000h单元*/ *p=max; /*最大值存入外部ram区0000h单元*/ ,5.5.2 选择结构程序,87,04:02,2双分支语句 if (条件表达式) 语句组1; else 语句组2;,5.5.2 选择结构程序,-双分支结构,其语义是:如果条件表达式的值为真,则执行语句组1,否则执行语句组2。其执行过程可表示为图5-2所示。,88,04:02,例5-13 寻找两个数中的大数输出。 #include “reg51.h” void main() unsigned xdata *p; unsigned a=35, b=78, max; if(ab) max=a; else max=b; p=0; /*p指向外部ram区0000h单元*/ *p=max; /*最大值存入外部ram区0000h单元*/ ,5.5.2 选择结构程序,-双分支结构举例,89,04:02,3多分支语句 当有多个分支选择时,可采用if-else-if语句结构,其一般形式为: if (条件表达式1) 语句组1; else if (条件表达式2) 语句组2; else if (条件表达式3) 语句组3; else if (条件表达式n) 语句组n; else 语句m;,5.5.2 选择结构程序,-多分支结构,其语义是:依次判断条件表达式的值,当出现某个条件表达式的值为真(非0)时,则执行其对应的语句组。然后跳到整个if语句之外继续执行程序。如果所有的表达式的值均为假(0),则执行语句组m。然后继续执行后续程序。,90,04:02,例5-14 如图5-3所示,单片机p1口的p1.0和p1.1各接一个开关k1、k2,p1.4、p1.5、p1.6和p1.7各接一只发光二极管。由k1和k2的不同状态来确定哪个发光二极管被点亮。 程序如下:,5.5.2 选择结构程序,-多分支结构举例,91,04:02,#include “reg51.h” void main( ) char a; a=p1; a=a ,5.5.2 选择结构程序,-多分支结构举例,92,04:02,4开关选择switch语句,switch语句结构的一般形式为: switch (表达式) case 常量表达式1: 语句组1; case 常量表达式2: 语句组2; case 常量表达式n: 语句组n; default: 语句组n+1; ,5.5.2 选择结构程序,-多分支结构,其语义是:计算表达式的值,并逐个与其后的常量表达式值相比较,当表达式的值与某个常量表达式的值相等时,即执行其后的语句组,然后继续执行后面所有的case语句,但不再进行判断;如表达式的值与所有case后的常量表达式的值均不相等时,则执行default后的语句。,93,04:02,例5-15 用switch语句完成例5-14任务。程序如下: #include void main() char a; a=p1; a=a ,5.5.2 选择结构程序,-多分支结构举例,94,04:02,在使用switch语句时还应注意以下几点: (1) 在case后的各常量表达式的值不能相同,否则会出现错误。 (2) 在case后,允许有多条语句,可以不用 括起来。 (3) 各case和default子句的先后顺序可以变动,而不会影响程序执行结果。 (4) default子句可以省略不用。 (5) 在每一
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年无人机考试题库和部份考题带答案(典型题)
- 小儿视网膜母细胞瘤E期护理查房
- 安丘市2024-2025学年八年级下学期语文期中模拟试卷
- 2016年7月国开电大法律事务专科《行政法与行政诉讼法》期末纸质考试试题及答案
- 七夕主题活动总结2025年
- 广东省2025年下半年电机装配工:基础理论试题
- 社区网格化管理课件
- 江苏省无锡金桥双语实验学校2024-2025学年九年级下学期期中考试英语试卷(含答案)
- Unit 2 School life单元测试卷(含解析)译林版(2024)八年级英语上册
- 岩石基坑开槽合同范本
- 机关事业单位工人汽车驾驶员高级、技师国家题库练习题及答案
- 2025年青海辅警招聘考试题及答案
- 2025新外研版初中英语八年级上全册课文原文翻译
- 钢结构安装安全操作规程
- 2025年高处作业特种作业操作证考试试卷:高处作业特种作业操作证考试备考攻略与技巧
- 2025年山西中考道德与法治真题解读及答案讲评课件
- 2025届云南中考化学真题试卷【含答案】
- 2025年安徽省公务员录用考试行测真题试卷
- DB54∕T 0275-2023 民用建筑节能技术标准
- 伤口造口护理新进展
- 阿托西班护理
评论
0/150
提交评论