您好,欢迎访问三七文档
MCS-51单片机的C语言编程§3-1C语言与MCS-51一、C语言特点C语言是一种编译型程序设计语言,它兼顾了多种高级语言的特点,并具备汇编语言的某些特点,用C语言进行程序设计已经成为软件开发的一个主流。单片机系统的开发也适应了这个潮流。与汇编语言相比,用C语言开发单片机具有如下特点:1.开发速度优于汇编语言;2.软件的可读性和可维护性显著改善;3.提供了库函数包含许多标准子程序,具有较强的数据处理能力;4.关键字及控制转移方式更接近人的思维方式;5.方便进行多人联合开发,进行模块化软件设计;6.C语言本身并不依赖于机器硬件系统,移植方便;7.适合运行嵌入式实时操作系统;对于MCS-51单片机的C语言:1.针对8051的特点对标准的C语言进行扩展。2.对单片机的指令系统不要求十分了解,只要对8051单片机的存储结构了初步了解,就可以编写出应用软件。3.寄存器的分配、不同存储器的寻址及数据类型等细节由编译器管理。用C语言编写的应用程序必须经单片机的C语言编译器(简称C51)转换生成单片机可执行代码程序。支持MCS-51系列单片机的C语言编译器有很多种。如AmericanAutomation、Auoect、Bso/Tasking、KEIL等等。其中德国KEIL公司的C51编译器在代码生成方面领先,可产生最少代码,它支持浮点和长整数、重入和递归,使用非常方便。本章针对这种被广泛应用的KEILC51编译器,介绍MCS-51单片机C语言的程序设计。二、C51程序的开发过程用C语言编写单片机应用程序和编写标准的C语言程序的不同之处,在于根据单片机的存储结构及内部资源定义C语言中的数据类型和变量,其他的语法规定、程序结构及程序设计方法与标准的C语言相同,所以在后面的几节中主要介绍如何定义C51中的变量的数据类型、存储类型、特殊功能寄存器以及中断函数,与标准C相同的部分就不再述。C51的开发过程和用其它语言包括汇编语言开发没有什么不同,其开发流程见下图:例1:如图所示,P1口连接8只发光二极管,要求每隔0.5秒移动一次,当P2.0为高时,发光二极管左移,否则右移。#includereg51.h//标准的8051头文件,定义了所有的SFR#includeintrins.h//内部函数包含到程序中,#defineucharunsignedchar#defineuintunsignedintsbitKEY=P2^0;//定义P2.0为开关输入voiddelay(void)//软件延时函数{uintt;for(t=0;t30000;t++);//空循环延时,大约0.5秒左右}voidmain(void){uchardataled;led=0xfe;//低电平点亮发光管,初始值对应最低位P1.0为低,即L0点亮while(1){P1=led;//将led送到P1口delay();//延时0.5秒if(KEY)//如果KEY为1(开关断开),则变量led循环左移一位led=_crol_(led,1);elseled=_cror_(led,1);//否则led循环右移一位}}这是一个完整的C51源程序,注意主函数中由while(1)所构成的死循环,因为单片机中没有其它软件,也就没有PC机C语言中所谓的退到DOS或WINDOWS的概念,如果程序中没有这样的死循环,程序执行完最后一条语名,随后的结果将不可预计。§3-2数据与数据类型无论我们学习哪一种语言,首先遇到的是数据类型,C51共有以下几种数据类型:位型:bit字符型:char整型:int基本类型长整型:long浮点型:float双精度浮点型:double数组类型:array数据类型构造类型结构体类型:struct共用体:union指针类型枚举:enum空类型KEILC51所支持的基本数据说型说明如下:数据类型长度(bit)长度(Byte)值域范围bit10,1unsignedchar810~255signedchar81-128~127unsignedint1620~65535signed162-32768~32767unsignedlong3240~4294967295uignedlong324-2147483648~2147483647float324±1.176E-38~±3.40E+38double648±1.176E-38~±3.40E+38一般指针243存储类型(1字节)偏移量(2字节)有了这些数据类型,我们用变量去描述一个现实中的数据时,就应按需选择变量类型。对于C51来讲,不管采用哪一种数据类型,虽然源程序看起来是一样的,但最终形成的目标代码却大相径庭,其效率相并非常大。例如:当我们去表示时间量秒的时候,虽然可用unsignedint类型甚到double类型,但由于秒的取值范围是0~59,所以采用unsignedchar就够了。这样不仅节省了存贮空间,而且还可以提高程序的运行速度。因此我们在编程时应按照变量可能的取值范围、精度要求去选择恰当的数据类型。另外,如果不涉及负数运算,要尽量采用无符号类型,这样可以提高编译后目标代码的效率。我们编程时最常用到的时无符号数运算,因此为了编程时书写的方便,我们可以采用简化的缩写形式来定义变量的数据类型。其方式是在源程序的开始处加上下面两条语句:#defineucharunsignedchar#defineuintunsignedint这样在定义变量时,就可以使用ucharuint来代替unsignedchar和signedchar。§3-3C51的数据存贮类型与8051存贮器结构8051系列单片机将程序存贮器(ROM)和数据存贮器(RAM)分开,并有各自的寻址机构和寻址方式。8051单片机在物理上有四个存贮空间:片内程序存贮器空间:0000—0FFF片外程序存贮器空间:1000—FFFF(/EA=1)0000—FFFF(EA=0)片内数据存贮器空间:1.1F:通用工作寄存器区20—2F:位寻址空间30—7F:用户RAM区80—FF:特殊功能寄存器区片外数据存贮器空间:0000—FFFF我们采用汇编编语言编程时,是按地址去读写指定的存储单元的,用不同的指令去表示不同的存储空间,例如:MOV指令访问片内数据存储器,MOVX指令访问片外数据存储器,MOVC指令访问程序存储器。而在C51中直接使用变量名去防问存储单元,而无需关心变量的存放地址,程序的可读性大大增加了。但变量放在哪一个存贮空间呢?这对最终目标代码的效率影响很大。因此在编程时除了说明变量的数据类型外,还应说明变量所在的存储空间即存储类型。C51将变量、常量定义成不同的存贮类型,以完全支持8051单片机的存贮器结构。C51存储类型与8051存储空间的对应关系存贮类型与存贮空间的对应关系data直接寻址片内数据存贮区,速度快(00—7F)bdata可位寻址片内数据存贮区,允许位/字节混合访问(20—2F)idata间接寻址片内数据存贮区,可访问全部RAM空间(00—FF)由MOV@Ri访问pdata分页寻址片外数据存贮区(256字节),用MOVX@Ri访问xdata片外数据存贮区(64字节),用MOVX@DPTR访问code代码存贮区(64K),由MOVC@DPTR访问C51中变量定义的格式:数据类型[存储类型]变量名1[,变量名2]……[,变量名n];例:chardatatemp;//字符变量temp,定位在片内数存贮区,用直接寻址方式访问。bitbdataflags;//位变量flags,定位在可位寻址片内数据存贮区。ucharbdataspeed;//无符号字符变量speed,定位在可位寻址片内数据存贮区ucharidatalen;//无符号字符变量len,定位在片内数据存贮区,用间接寻址ucharcodeseg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d};//定义无符号字符型数组seg,共有10个元表,存放在程序存储器中。说明:选择变量的存储类型时,可按以下的原则:通常将一些固定不变的参数或表格放在程序存储器中,即存储类型设为code。例如上面所定义的seg数组就是用来存放LED数码管的字段码的。访问片内数据存储器(存储类型为data/bdata/idata)比访问片外数据存储器的速度要快,因此对一些使用频率较高的变量或者对速度要求较高的程序中的变量可选择片内数据存储器,而将一些不常使用的变量放存片外数据存储器(存储类型为pdata/xdata)中。当然如果系统中所用的变量较少,片内数据存储器的空间足够应付时,就无需使用片外数据存储器了。对于52子系列的单片机,其内部RAM是256字节,其高128字节的地址从80H~FFH,正好与特殊功能寄存器地址重叠,两者通过寻址方式加以区别,对于52子系列的高128字节的RAM,必须用R0、R1寄存器间接寻址方式访问,而对特殊功能寄存器只能用直接寻址方式访问。也就是说如果希望在C51中对80H~0FFH之间的数据存储器进行读写,可以将变量的存储类型定义为idata。通常将位变量或希望位与字节混合访问的变量的存储类型设置为bdata。但要注意,不能定义指向指向位型的指针,也不能定义位数组。例如:下面两条定义语名时错误的。bitbdata*pb;bitbdatastatus[8];如果变量定义时省去存贮类型说明,编译时会自动选择默认的存储类型,而默认的存贮类型由存贮模式确定。在C51中有SMALL、COMPACT、LARGE三种存储模式,在KEIL环境中,可以通过目标工具选项设置选择所需的存储模式。下面分别对这三种模式进行说明:存贮模式作为编译选项如下表所示:存贮模式说明SMALL参数和局部变量放入可直接寻址的内部数据存贮器(最大128字节,默认的存储类型为DATA),速度快,访问方便。所用堆栈在片内RAM。CPMPACT参数和局部变量放入分页外部数据存贮器(最大256字节,默认的存储类型为PDATA),通过MOVX@Ri指令间接寻址,所用堆栈在片内RAM。LARGE参数和局部变量直接放入外部数据存贮器(最大64KB,默认的存储类型为XDATA),通过MOVX@DPTR指令进行访问,所形成的目标代码效率低。例如,有一程序如下:#defineucharunsignedcharvoidmain(void){ucharb;//由于省去了存储类型,C51会根据当前的选择存贮模式来确定b的存储类型。b=12;}如果当前的存贮模式为SMALL,编译后所形成的目标代码为:MOV08H,#0CH;这里08H为变量b在片内RAM的地址,#0CH即为12。如果当前的存贮模式为CPMPACT,编译后所形成的目标代码为:MOVR0,#00H;这里00H为变量b在片外RAM的页面地址,#0CH即为12。MOVA,#0CHMOVX@R0,A如果当前的存贮模式为LARGE,编译后所形成的目标代码为:MOVDPTR,#0000H;这里0000H为变量b在片外RAM的地址,#0CH即为12MOVA,#0CHMOVX@DPTR,A由此可见,在存储类型缺省的情况下,由当前的存贮模式确定变量的存储类型,初学者使用时一定要小心!例如,你的单片机系统并没有扩充外部数据存贮器,当前的存储模式为LARGE,而且一些变量又没有选择存储类型,这样在调试时会出现一些意想不到的错误。教学目的:掌握8051特殊功能寄存器、并行接口、位变量的C51定义,C51内部函数及常用的宏。教学难点:可位寻址对象的定义及实际应用中的技巧,关键字sbit与bit的差别。§3-48051特殊功能寄存器及其C51定义通过对变量的存储类型的定义,我们可以通过变量访问MCS-51系列单片机的各类存储器,但又通过什么方法去访问它的特殊功能寄存器呢?一、对特殊功能寄存器的访问8051单片机内有21个特殊功能寄存器(SFR),分散在片内RAM的高端,地址在80H—0FF间,对它们的操作,只能用直接寻址方式。为了能够直接访问21个特殊功能寄存器(SFR),C51提供了一种自主形式的定
本文标题:51基础知识
链接地址:https://www.777doc.com/doc-2893654 .html