单片机3章.docx
- 文档编号:23185879
- 上传时间:2023-05-15
- 格式:DOCX
- 页数:41
- 大小:40.34KB
单片机3章.docx
《单片机3章.docx》由会员分享,可在线阅读,更多相关《单片机3章.docx(41页珍藏版)》请在冰豆网上搜索。
单片机3章
第3章C51语言编程基础
内容概要
目前单片机应用设计与开发,多使用C51语言来编程。
C51语言是在标准C的基础上,根据单片机存储器硬件结构及内部资源,扩展相应的数据类型和变量,而在语法规定、程序结构与设计方法上,都与标准C相同。
本章介绍C51语言的基础知识、对C51集成开发环境KeilµVision3以及单片机虚拟仿真平台Proteus也作以介绍。
在单片机应用开发中,软件编程占有非常重要的地位。
要求编程人员在短时间内编写出执行效率高、运行可靠的程序代码。
同时,由于实际系统的日趋复杂,对程序的可读性、升级与维护以及模块化的要求越来越高,以方便多个工程师协同开发。
C51语言是近年来在国内外的51单片机开发中,普遍使用的一种程序设计语言。
C51能直接对单片机硬件进行操作,既有高级语言的特点,又有汇编语言的特点,因此在单片机应用的程序设计中,得到非常广泛的使用。
3.1编程语言KeilC51简介
KeilC51(简称C51),是在标准C语言的基础上发展的。
3.1.1KeilC51简介
KeilC51语言是在标准C的基础上针对51单片机的硬件特点进行的扩展,并向51单片机上移植,经多年努力,C51语言已成为公认的高效、简洁的51单片机的实用高级编程语言。
与汇编语言相比,用C51语言进行软件开发,有如下优点:
(1)可读性好。
C51语言程序比汇编语言程序的可读性好,因而编程效率高,程序便于修改、维护以及程序升级。
(2)模块化开发与资源共享。
C51开发的模块可直接被其他项目所用,能很好地利用已有的标准C程序资源与丰富的库函数,减少重复劳动,也有利于多个工程师的协同开发。
(3)可移植性好。
为某型单片机开发的C51程序,只需将与硬件相关之处和编译链接的参数进行适当修改,就可方便地移植到其它型号的单片机上。
例如,为51单片机编写的程序通过改写头文件以及少量的程序行,就可以方便地移植到PIC单片机上。
(4)生成的代码效率高。
代码效率比直接使用汇编语言低20%左右,如使用优化编译选项,最高可达90%左右,效果会更好。
3.1.2C51与标准C的比较
C51标准C语言有许多相同的地方,但也有自身特点。
不同的嵌入式C语言编译系统与标准C语言的不同,主要是由于它们所针对的硬件系统不同。
对于51单片机,目前广泛使用的是KeilC51语言,简称C51语言。
C51的基本语法与标准C相同,C51在标准C的基础上进行了适合于51系列单片机硬件的扩展。
深入理解KeilC51对标准C的扩展部分以及不同之处,是掌握C51语言的关键之一。
C51与标准C的主要区别如下:
(1)库函数的不同。
标准C中的部分库函数不适合于嵌入式控制器系统,被排除在KeilC51之外,如字符屏幕和图形函数。
有些库函数可继续使用,但这些库函数都必须针对51单片机的硬件特点做出相应的开发。
例如库函数printf和scanf,在标准C中,这两个函数通常用于屏幕打印和接收字符,而在KeilC51中,主要用于串行口数据的收发。
(2)数据类型有一定的区别。
在C51中增加了几种针对51单片机特有的数据类型,在标准C的基础上又扩展了4种类型。
例如,51单片机包含位操作空间和丰富的位操作指令,因此,C51语言与标准C相比就要增加位类型。
(3)C51的变量存储模式与标准C中的变量存储模式数据不一样。
标准C是为通用计算机设计的,计算机中只有一个程序和数据统一寻址的内存空间,而C51中变量的存储模式与51单片机的存储器紧密相关。
(4)数据存储类型的不同。
51单片机存储区可分为内部数据存储区、外部数据存储区以及程序存储区。
内部数据存储区可分为3个不同的C51存储类型:
data、idata和bdata。
外部数据存储区分为2个不同的C51存储类型:
xdata和pdata。
程序存储区只能读不能写,在51单片机内部或外部。
C51提供了code存储类型来访问程序存储区。
(5)标准C语言没有处理单片机中断的定义。
C51中有专门的中断函数。
(6)头文件的不同。
C51语言与标准C头文件的差异是C51头文件必须把51单片机内部的外设硬件资源如定时器、中断、I/O等所相应的功能寄存器的写入头文件内。
(7)程序结构的差异。
由于51单片机硬件资源有限,它的编译系统不允许太多的程序嵌套。
其次,标准C所具备的递归特性不被C51语言支持。
但是从数据运算操作、程序控制语句以及函数的使用上来说,KeilC51与标准C几乎没有什么明显的差别。
如果程序设计者具备了有关标准C的编程基础,只要注意KeilC51与标准C的不同之处,并熟悉51单片机的硬件结构,就能够较快地掌握C51的编程。
3.2KeilC51的开发工具
KeilC51是德国Keilsoftware公司开发的用于51单片机的C51语言开发软件,在兼容标准C的基础上,又增加了很多与51单片机硬件相关的编译特性,使得在51系列单片机上开发应用程序更为方便和快捷,生成的程序代码运行速度快,所需的存储器空间小,完全可以和汇编语言相媲美。
它支持众多的8051架构的芯片,同时集编辑、编译、仿真等功能于一体,具有强大的软件调试功能,是众多的单片机应用开发软件中的最优秀软件之一。
3.2.1集成开发环境KeilµVision4简介
KeilC51已集成到一个功能强大的集成开发环境(IDE—IntergratedDevelopmentEviroment)µVision4中,用于51单片机的Windows下的集成开发环境,提供对8051内核的各种型号的支持,为51单片机软件开发提供全新的C语言开发环境。
该开发环境下集成了文件编辑处理、编译链接、项目(Project)管理、窗口、工具引用和仿真软件模拟器以及Monitor51硬件目标调试器等多种功能,所有功能均
可在KeilµVision4的开发环境中极为简便地进行操作。
较新的版本为KeilC51v8.08a。
经常用到KeilC51和KeilµVision4两个术语。
KeilC51一般简写为C51,指的是51单片机编程所用的C51语言;而KeilµVision4,可简写为µVision4,指的是用于51单片机的C51程序编写、调试的集成开发环境。
µVision4内部集成了源程序编辑器,并允许用户在编辑源文件时就可设置程序调试断点,便于在程序调试过程中快速
检查和修改程序。
此外,µVision4还支持软件模拟仿真(Simulator)和用户目标板调试(Monitor51)两种工作方式。
在软件模拟仿真方式下不需要任何51单片机及其外围硬件即可完成用户程序仿真调试。
在用户目标板调试方式下,利用硬件目标板中的监控程序可以直接调试目标硬件系统,使用户节省购买硬件仿真器的费用。
3.2.2KeilµVision4软件的安装、启动和运行
1.软件安装
集成开发环境安装,同大多数软件安装一样,根据提示进行。
安装完毕后,可在桌面上看到KeilµVision3的快捷图标。
2.软件启动
点击桌面上的KeilµVision3软件的快捷图标,即可启动该软件,几秒种后,出现编辑界面。
3.软件的运行
KeilµVision3把用户的每一个应用程序设计都当作一个项目,
用项目管理方法可把一个应用程序设计中所用到的、互相关联的程序链接在同一项目中。
打开一个项目时,所需要的关联程序也都进入了调试窗口,方便用户对项目中各程序的编写、调试和存储。
用户也可能开发了多个项目,每个项目用到了相同或不同的程序文件和库文件,采用项目管理,就很容易区分不同项目中所用到的程序文件和库文件,非常容易管理。
因此,在编写一个新的应用程序前,一定先要建立项目。
下面首先介绍如何建立一个新的项目。
在编辑界面下,首先要建立一个点击“Project”菜单,选择下拉式菜单中的“NewProject”,弹出文件对话窗口,选择要
保存的路径,在“文件名”中输入一个程序项目名称,保存后的文件扩展名为“.uvproj”,这是KeilµVision4项目文件的扩展名,以后可直接点击此文件就可打开先前做的项目。
点击“保存”后,会弹出一个对话框,要求选择单片机的型号,用户可根据所使用的单片机来选择。
KeilµVision4支持几乎所有的51内核单片机。
然后编写第一个程序。
点击“File”菜单,单击“New”。
这时,用户可输入代码。
输入完毕,单击菜单上的“File”,在下拉菜单中单击“SaveAs”,在“文件名”栏的编辑框中,键入文件名,同时,必须键入正确的扩展名(.C或.ASM),然后,单击“保存”按钮。
上述工作完成后,还有有关项目的设置,程序的编译,链接,调试。
这些内容,可按照KeilµVision4开发环境的帮助功能。
3.3C51语言程序设计基础
在标准C的基础上了解掌握C51的数据类型和存储类型、基本运算与流程控制语句、C51语言构造数据类型、C51函数以及C51程序设计的其它问题,为C51程序设计打下基础。
3.3.1C51语言中的数据类型与存储类型
1.数据类型
数据是单片机操作的对象,是具有一定格式的数字或数值,
数据的不同格式就称为数据类型。
KeilC51支持的基本数据类型如表3-1所示。
针对AT89S51单片机的硬件特点,C51在标准C的基础上,扩展了4种数据类型(表3-1中最后4行)。
注意:
扩展的4种数据类型,不能使用指针对它们存取。
2.C51的扩展数据类型
(1)位变量bit
由于51单片机能够进行位操作,C51扩展的“bit”数据类型用来定义位变量,这是C51与标准C的不同之处。
bit的值可以是1(true),也可以是0(false)。
C51采用关键字“bit”来定义位变量,一般格式为:
bitov_flag;/*将ov_flag定义为位变量*/
函数可以包含类型为bit的参数,也可将其作为返回值
例如:
bitfunc(bitb0,bitb1);/*位变量b0与b1作为函数func的参数*/
{……
return(b1);/*位变量b1作为函数的返回值*/
}
位变量定义的限制
位变量不能用来定义指针和数组。
例如:
bit*ptr;/*错误,不能用位变量来定义指针*/
bitarray[];/*错误,不能用位变量来定义数组array[]*/
定义位变量时,允许定义存储类型,位变量存放在片内RAM中,因此其存储类型限制为DATA、IDATA或BDATA,如果将位变量定义成其他类型都会导致编译时出错。
③sbit位名=位地址;
这种方法将位的绝对位地址赋给位名变量,位地址必须在0x80~0xFF之间。
例如:
sbitCY=0xD7;/*CY位地址为0xD7*/
sbitOV=0xD2;/*OV位地址为0xD2*/
【例】片内I/O口P1口的各寻址位的定义如下:
sfrP1=0x90;
sbitP1_7=P1^7;
sbitP1_6=P1^6;
sbitP1_5=P1^5;
sbitP1_4=P1^4;
sbitP1_3=P1^3;
sbitP1_2=P1^2;
sbitP1_1=P1^1;
sbitP1_0=P1^0;
(4)特殊功能寄存器sfr16
“sfr16”数据类型占两个内存单元。
它用于操作占两个字节的特殊功能寄存器。
例如:
“sfr16DPTR=0x82”语句定义了片内16位数据指针寄存器DPTR,其低8位字节地址为82H,高8位字节地址为83H。
AT89S51有两个指向外部RAM(ROM)的数据指针,需自己定义。
sfr16DPTR0=0x82;
sfr16DPTR1=0x84;
……
DPTR0=0x5678;
DPTR1=0x1234;
通过头文件访问SFR
各种衍生型的51单片机的特殊功能寄存器的数量与类型有时是不相同的,对单片机特殊功能寄存器的访问可以通过头文件的访问来进行。
为了用户处理方便,C51语言把51单片机(或52单片机)的常用的特殊功能寄存器和其中的可寻址位进行了定义,放在一个reg51.h(或reg52.h)的头文件中。
当用户要使用
时,只需在使用之前用一条预处理命令#include
用户可以通过文本编辑器对头文件进行增减。
头文件引用举例如下:
#include
voidmain(void)
{TL0=0xF0;/*给定时器T0低字节TL0设置时间常数,已在reg51.h中定义*/
TH0=0x3F;/*给T0高字节TH0设时间常数*/
TR0=1;/*启动定时器0*/
……
}
有256个字节的内部数据存储区,其中低128字节可直接寻址,高128字节(80H~FFH)只能间接寻址,从20H开始的16字节可位寻址。
内部数据存储区可分为3个不同的数据存储类型:
data、idata和bdata。
访问片外数据存储区比访问片内数据存储区慢,因为片外数据存储区是通过数据指针加载地址来间接寻址访问的。
C51提供两种不同数据存储类型xdata和pdata来访问片外数据存储区。
程序存储区只能读不能写,可能在51单片机内部或者外部,或者外部和内部都有,由51单片机的硬件决定,C51提供了code存储类型来访问程序存储区。
C51存储类型与AT89S51单片机实际的存储空间的对应关系如表3-2所示。
下面对表3-2中的各种存储区作以说明。
(1)DATA区。
寻址是最快的,应该把经常使用的变量放在DATA区,但是DATA区的存储空间是有限的,DATA区除了包含程序变量外,还包含了堆栈和寄存器组。
DATA区声明中的存储类型标识符为data,通常指片内RAM的128字节的内部数据存储的变量,直接寻址。
声明举例如下:
unsignedchardatasystem_status=0;
unsignedintdataunit_id[8];
chardatainp_string[20];
由于C51使用默认的寄存器组来传递参数,这样DATA区至少失去了8字节的空间。
另外,当内部堆栈溢出的时候,程序会复位。
这是因为51单片机没有报错的机制,堆栈的溢出只能以这种方式表示,因此要留有较大的堆栈空间来防止堆栈溢出
(2)BDATA区。
是DATA中的位寻址区,在这个区中声明变量就可进行位寻址。
BDATA区声明中的存储类型标识符为bdata,指的是内部RAM可位寻址的16字节存储区(字节地址为20H~2FH)中的128个位。
下面是在BDATA区中声明的位变量和使用位变量的例子:
unsignedcharbdataflag;
sbitflag0=flag^0;
sbitflag1=flag^1;
sbitflag2=flag^2;
sbitflag3=flag^3;
voidmain(void)
{
flag=0x88;
while
(1)
{
flag0=~flag0;
flag1=~flag1;
flag2=~flag2;
flag3=~flag3;
}
}
(4)PDATA区和XDATA区。
PDATA区和XDATA区位于片外存储区,PDATA区和XDATA区声明中的存储类型标识符分别为pdata和xdata。
PDATA区只有256字节,仅指定256字节的外部数据存储区。
但XDATA区最多可达64KB,对应的xdata存储类型标识符可以指定外部数据区64KB内的任何地址。
对PDATA区的寻址要比对XDATA区寻址快,因为对PDATA区寻址,只需要装入8位地址,而对XDATA区寻址要装入16位地址,所以要尽量把外部数据存储在PDATA区中。
对PDATA区和XDATA区的声明举例如下:
unsignedcharxdatasystem_status=0;
unsignedintpdataunit_id[8];
charxdatainp_string[16];
floatpdataout_value;
由于外部数据存储器与外部I/O口是统一编址的,外部数据存储器地址段中除了包含存储器地址外,还包含外部I/O口的地址。
对外部数据存储器及外部I/O口的寻址将在后面的绝对地址寻址中详细介绍。
(5)程序存储区CODE。
程序存储区CODE声明的标识符为code,储存的数据在程序运行过程中不可改变的。
在C51编译器中可以用存储区类型标识符code来访问程序存储区。
声明举例如下:
unsignedcharcodea[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
voidmain()
{
…
a[i]=i;
….
}
单片机访问片内RAM比访问片外RAM相对快一些,所以应当尽量把频繁使用的变量置于片内RAM。
即采用data、bdata或idata存储类型,而将容量较大的或使用不太频繁的那些变量置于片外RAM,即采用pdata或xdata存储类型。
常量、表格通常采用code存储类型。
变量存储类型定义举例:
(1)chardataa1;/*字符变量a1被定义为data型,分配在片内RAM低128字节中*/
(2)floatidatax,y;/*浮点型变量x和y被定义为idata型,定位在片内RAM中,只能用间接寻址方式寻址*/
(3)charbdatap;/*位变量p被定义为bdata型,定位在片内RAM中的位寻址区*/
(4)unsignedintpdatavar1;/*无符号整型变量var1被定义为pdata型,定位在片外RAM中,相当于使用@Ri间接寻址*/
(5)unsignedcharxdataa[2][4];/*无符号字符型二维数组变量a[2][4]被定义为xdata存储类型,定位在片外RAM中,占据24=8个字节,相当于使用@DPTR间接寻址*/
4.数据存储模式
如在变量定义变量时略去存储类型标识符,编译器会根据存储模式自动默认存储类型。
C51开发环境默认的存储模式(SMALL、COMPACT和LARGE)限制。
例如,若声明charvar1,则在使用SMALL存储模式下,var1被定位在data存储区,在使用COMPACT模式下,var1被定位在pdata存储区;在LARGE模式下,var1被定位在xdata存储区中。
(1)SMALL模式:
所有变量都默认位于51单片机内部RAM,这与使用data指定存储器类型的方式一样。
本模式,变量访问的效率高,但所有数据对象和堆栈必须使用内部RAM。
(2)COMPACT模式:
所有变量都默认在外部数据存储器的1页内,这与使用pdata指定存储器类型是一样的。
该存储器类型适用于变量不超过256字节的情况,此限制是由寻址方式决定,相当用数据指针@Ri进行寻址。
与SMALL模式相比,该存储模式的效率比较低,对变量访问的速度也慢一些,但比LARGE模式快。
(3)LARGE模式。
在LARGE模式中,所有变量都默认位于外部数据存储器,相当于使用数据指针@DPTR进行寻址。
通过数据指针访问外部数据存储器的效率较低,特别是当变量为2字节或更多字节时,该模式要比SMALL和COMPACT产生更多的代码。
3.3.3C51语言的绝对地址访问
如何对51单片机的片内RAM、片外RAM及I/O进行访问,C51语言提供了两种比较常用的访问绝对地址的方法。
1.绝对宏
C51编译器提供了一组宏定义来对code、data、pdata和xdata空间进行绝对寻址。
在程序中,用“#include
其中:
CBYTE以字节形式对code区寻址;
CWORD以字形式对code区寻址;
DBYTE以字节形式对data区寻址;
DWORD以字形式对data区寻址;
XBYTE以字节形式对xdata区寻址;
XWORD以字形式对xdata区寻址;
PBYTE以字节形式对pdata区寻址;
PWORD以字形式对pdata区寻址。
例如:
#include
#definePORTAXBYTE[0xFFC0]/*把外部地址为0xFFC0的I/O口(存储器)定义为PORTA,长度8位*/
#defineNRAMDBYTE[0x50]/*将片内RAM,地址为0x50的单元定义为NRAM,长度8位*/
【例】片内RAM、片外RAM及I/O的定义的程序如下:
#include
#definePORTAXBYTE[0xFFC0]/*将PORTA定义为外部RAM,地址为0xFFC0*/
#defineNRAMDBYTE[0x40]/*将NRAM定义为片内RAM,地址为0x40*/
main()
{PORTA=0x3D;/*数据3DH写入地址0xFFC0的外部I/O端口或存储单元*/
NRAM=0x01;/*将数据01H写入片内RAM的40H单元*/
}
【例】使用关键字_at_实现绝对地址的访问,程序如下:
dataunsignedchary1_at_0x50;/*在data区定义字节变量y1,它的地址为50H*/
xdataunsignedinty2_at_0x4000;/*在xdata区定义字变量y2,地址为4000H*/
voidmain(void)
{
y1=0xff;
y2=0x1234;
while
(1);
}
【例】将片外RAM2000H开始的连续20个字节单元置为1_20。
程序如下:
xdataunsignedcharbuffer[20]_at_0x2000;
voidmain(void)
{unsignedchari;
for(i=0;i<20;i++)buffer[i]=i+1;
while
(1);
}
如果把片内RAM40H单元开始的8个单元内容置数,则程序如下:
dataunsignedcharbuffer[8]_at_0x40;
voidmain(void)
{unsignedchari;
for(i=0;i<8;i++)buffer[i]=i+1;
while
(1);
}
3.3.4C51的基本运算
C51语言的基本运算与标准C类似,主要包括算术运算、关系运算、逻辑运算、位运算和赋值运算及其表达式等。
1.算术运算符
算术运算的算术运算符及其说明如表3-4所示。
读者对表3-4中的运算符“+、-、*”,运算比较熟悉,但是对于“/”和“%”往往会有疑问。
这两个符号都涉及除法运算,但“/”运算是取商,而“%”运算为取余数。
例如“5/3”的结果(商)为1,而“5%3”的结果为2(余数)。
表3-4中的自增和自减运算符是使变量自动加1或减1,自增和自减运算符放在变量前和变量之后是不同的。
例如:
++i,--i:
在使用i之前,先使i值加(减)1。
i++,i--:
在使用
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机