单片机C语言及程序设计.docx

上传人:b****5 文档编号:28007089 上传时间:2023-07-07 格式:DOCX 页数:38 大小:35.57KB
下载 相关 举报
单片机C语言及程序设计.docx_第1页
第1页 / 共38页
单片机C语言及程序设计.docx_第2页
第2页 / 共38页
单片机C语言及程序设计.docx_第3页
第3页 / 共38页
单片机C语言及程序设计.docx_第4页
第4页 / 共38页
单片机C语言及程序设计.docx_第5页
第5页 / 共38页
点击查看更多>>
下载资源
资源描述

单片机C语言及程序设计.docx

《单片机C语言及程序设计.docx》由会员分享,可在线阅读,更多相关《单片机C语言及程序设计.docx(38页珍藏版)》请在冰豆网上搜索。

单片机C语言及程序设计.docx

单片机C语言及程序设计

单片机C语言及程序设计

4.1C51概述

“C51”概念:

为了与ANSIC区别,把“单片机C语言”称为“C51”,也称为“KeilC”。

用汇编语言编写单片机程序时,必须要考虑其存储器的结构,尤其要考虑其片内数据存储器、特殊功能寄存器是否正确合理的使用,以及按照实际地址端口数据的处理。

Ø4.1.2C语言与ANSI的区别

用C51编写程序,虽然不像汇编语言那样需要具体地组织、分配存储器资源,但是C51对数据类型和变量的定义,必须要与单片机的存储结构相关联,否则编译器不能正确地映射定位。

用C51编写单片机程序,与用ANSIC编写程序的不同之处是,需要根据单片机存储器结构及内部资源,定义相应的数据类型和变量。

其它的语法规定、程序结构及程序设计方法,都与ANSIC相同。

所以本章主要介绍C51各种变量的定义、指针定义、函数定义和混合编程。

Ø4.1.3C51扩展的关键字

由于单片机在结构及编程上的特殊要求,C51有自己的特殊关键字,称之为C51扩展的关键字,下面给出常用的C51扩展的关键字。

_at_bdatabitcode

dataidatainterruptpdata

reentrantsbitsfr

sfr16usingvolatilexdata

Ø4.2C51数据类型及存储

表4-1C51数据类型、长度和数值范围

数据类型

表示方法

长度

数值范围

无符号字符型

unsignedchar

1字节

0~255

有符号字符型

signedchar

1字节

-128~127

无符号整型

unsignedint

2字节

0~65535

有符号整型

signedint

2字节

-32768~32767

无符号长整型

unsignedlong

4字节

0~

有符号长整型

signedlong

4字节

-~

浮点型

float

4字节

±1.1755E-38~±3.40E+38

特殊功能寄存器型

Sfr

sfr16

1字节

2字节

0~255

0~65535

位类型

bit、sbit

1位

0或1

数据类型转换

1)自动转换

转换规则是向高精度数据类型转换、向有符号数据类型转换。

如字符型变量与整型变量相加时,则位变量先转换字符型或整型数据,然后相加。

2)强制转换

像ANSIC一样,通过强制类型转换的方式进行转换。

如:

unsignedintb;

floatc;b=(int)c;

Ø4.2.2C51数据的存储

MCS-51单片机只有bit和unsignedchar两种数据类型支持机器指令,而其它类型的数据都需要转换成bit或unsignedchar型进行存储。

为了减少单片机的存储空间和提高运行速度,要尽可能地使用unsignedchar型数据。

一、位变量的存储

bit和sbit型位变量,直接存于RAM的位寻址空间,包括低128位和特殊功能寄存器位。

二、字符变量的存储

字符变量(char):

无论是unsignedchar数据还是signedchar数据,均为1个字节,能够被直接存储在RAM中,可以存储在0~0x7f区域,也可以存储在0x80~0xff区域,与变量的定义有关。

unsignedchar数:

可直接被MSC-51接受

地址

 

:

:

34

12

:

:

signedchar数据:

用补码表示。

需要额外的操作来测试、处理符号位,使用的是两种库函数,代码量大,运算速度降低。

三、整型变量的存储

整型变量(int):

不管是unsignedint数据还是signedint数据,

均为2个字节,其存储方法是高位字节保存在低地址(在前面),

低位字节保存在高地址(在后面)。

例如,整型变量的值为0x1234,在内存中的存放如右图所示。

signedint数据用补码表示。

四、长整型变量的存储

长整型变量(long)为4个字节,其存储方法与整型数据一样,

是最高位字节保存的地址最低(在最前面),最低位字节保存的地址最高(在最后面)。

Ø如长整型变量的值为0x,在内存中的存放方法如右图所示。

地址

 

:

:

78

56

34

12

:

:

不管是unsignedlong数据还是signedlong数据。

五、浮点型变量的存储

浮点型变量(fload)占4个字节,用指数方式表示,其具体格式与编译器有关。

对于KeilC,采用的是IEEE-754标准,具有24位精度,尾数的最高位始终为1,

因而不保存。

具体分布为:

1位符号位,8位阶码位,23位尾数,如下图所示。

字节地址

0

1

2

3

浮点数

内容

SEEE

EEEE

EMMM

MMMM

MMMM

MMMM

MMMM

MMMM

 

符号和阶码

尾数高位

 

尾数低位

符号位S:

1表示负数,0表示正数。

地址

 

:

:

00

00

48

C1

:

:

阶码:

用移码表示。

如,实际阶码-126用1表示,实际阶码0用127表示,即实际阶码数加上127得到阶码的表达数。

阶码数值范围:

-126~+128。

例如浮点数-12.5

符号位为1,

12.5的二进制数为1100.1=1.1001E+0011,

阶码数值为3+127=130=B,

尾数为1001。

因此,其十六进制数为0xC,则存储结构如右图所示。

Ø4.3C51变量的定义及数据存储区域

Ø4.3.1C51变量的定义

C51变量定义的一般格式为:

[存储类型]数据类型[存储区]

变量名1[=初值][,变量名2[=初值]][,…]

或[存储类型][存储区]数据类型

变量名1[=初值][,变量名2[=初值]][,…]

可见变量(非位变量)的定义由4部分组成,即在变量定义时,指定变量4种属性。

数据类型:

在前面的4.2中已经叙述过,对于变量名也无须多说,下面主要解释“存储类型”和“存储区”等概念。

Ø4.3.2C51变量的存储类型

存储类型这个属性我们仍沿用ANSIC的说法,尽量不改变原来的含义。

按照ANSIC,C语言的变量有4种存储类型:

动态存储(auto)

静态存储(static)

全局存储(extern)

寄存器存储(register)

一、动态存储

动态(存储)变量:

用auto定义的为动态变量,也叫自动变量。

作用范围:

在定义它的函数内或复合语句内部。

当定义它的函数或复合语句执行时,C51才为变量分配存储空间,结束时所占用的存储空间释放。

定义变量时,auto可以省略,或者说如果省略了存储类型项,则认为是动态变量。

动态变量一般分配使用寄存器或堆栈。

二、静态存储

静态(存储)变量:

用static定义的为静态变量。

分为内部静态和外部静态变量。

内部静态变量:

在函数体内定义的为内部静态变量。

在函数内可以任意使用和修改,函数运行结束后会一直存在,但在函数外不可见,即在函数体外得到保护。

外部静态变量:

在函数体外部定义的为外部静态变量。

在定义的文件内可以任意使用和修改,外部静态变量会一直存在,但在文件外不可见,即在文件外得到保护。

三、外部存储

外部(存储)变量:

用extern声明的变量为外部变量,是在其它文件定义过的全局变量。

用extern声明后,便可以在所声明的文件中使用。

需要注意的是:

在定义变量时,即便是全局变量,也不能使用extern定义。

四、寄存器存储

寄存器(存储)变量:

用register定义的变量为寄存器变量。

寄存器变量存放在CPU的寄存器中,这种变量处理速度快,但数目少。

C51中的寄存器变量:

C51的编译器在编译时,能够自动识别程序中使用频率高的变量,并将其安排为寄存器变量,用户不用专门声明。

Ø4.3.3C51变量的存储区域

变量的存储区属性是单片机扩展的概念,非常重要,它涉及到7个新的关键字。

MCS-51单片机有四个存储空间,分成三类,它们是片内数据存储空间、片外数据存储空间和程序存储空间。

MCS-51单片机有更多的存储区域:

由于片内数据存储器和片外数据存储器又分成不同的区域,所以单片机的变量有更多的存储区域。

在定义变量时,必须明确指出是存放在哪个区域。

表4-2C51存储区与存储空间的对应关系

关键字

对应的存储空间及范围

code

ROM空间,64KB全空间

data

片内RAM,直接寻址,低128字节

bdata

片内RAM,位寻址区0x20~0x2f,可字节访问

idata

片内RAM,间接寻址,256字节,与@Ri对应

pdata

片外RAM,分页寻址的256字节(P2不变),P2

改变可寻址64KB全空间,与MOVX@Ri对应

xdata

片外RAM,64KB全空间

bit

片内RAM位寻找区,位地址0x00~0x7f,128位

Ø4.3.4C51变量定义举例

1)定义存储在data区域的动态unsignedchar变量:

unsignedchardatasec=0,min=0,hou=0;

2)定义存储在data区域的静态unsignedchar变量:

staticunsignedchardatascan_code=0xfe;

3)定义存储在data区域的静态unsignedint变量:

staticunsignedintdatadd;

4)定义存储在bdata区域的动态unsignedchar变量:

unsignedcharbdataoperate,operate1;//定义指示操作的可位寻址的变量

5)定义存储在idata区域的动态unsignedchar数组:

unsignedcharidatatemp[20];

6)定义在pdata区域的动态有符号int数组:

intpdatasend_data[30];//定义存放发送数据的数组

7)定义存储在xdata区域的动态unsignedint数组:

unsignedintxdatareceiv_buf[50];//定义存放接受数据的数组

8)定义存储在code区域的unsignedchar数组:

unsignedcharcodedis_code[10]=

{0x3f,0x06,0x5b,0x4f,0x66,

0x6d,0x7d,0x07,0x7f,0x6f};//定义共阴极数码管段码数组

Ø4.3.5C51变量的存储模式

存储模式:

如果在定义变量时缺省了存储区属性,则编译器会自动选择默认的存储区域,也就是存储模式。

变量的存储模式也就是程序(或函数)的编译模式。

编译模式分为三种:

小模式(small)、紧凑模式(compact)和大模式(large)。

编译模式由编译控制命令决定。

存储模式(编译模式)决定了变量的默认存储区域和参数的传递方法。

一、small模式

在small模式下,变量的默认存储区域是“data”、“idata”,即未指出存储区域的变量保存到片内数据存储器中,并且堆栈也安排在该区域中。

small模式的特点:

存储容量小,但速度快。

在small模式下参数的传递:

通过寄存器、堆栈或片内数据存储区完成的。

二、compact模式

在compact模式下,变量的默认存储区域是“pdata”,即未指出存储区域的变量保存到片外数据存储器的一页中,最大变量数为256字节,并且堆栈也安排在该区域中。

compact模式的其特点:

是存储容量较small模式大,速度较small模式稍慢,但比large模式要快。

在compact模式下参数的传递:

通过片外数据区的一个固定页完成的。

三、large模式

在large模式下,变量的默认存储区域是“xdata”,即未指出存储区域的变量保存到片外数据存储器,最大变量数可达64KB,并且堆栈也安排在该区域中。

large模式的特点:

存储容量大,速度慢

large模式下参数的传递方式:

参数的传递也是通过片外数据存储器完成的。

C51支持混合模式:

即可以对函数设置编译模式,所以在large模式下,可以对某些函数设置为compact模式或small模式,从而提高运行速度。

默认编译模式:

如果文件或函数未指明编译模式,则编译器按small模式处理。

编译模式控制命令:

“#pragmasmall(或compact、large)”应放在文件的开始。

Ø4.3.6C51变量的绝对定位

C51有三种方式可以对变量(I/O端口)绝对定位:

绝对定位关键字_at_、指针、库函数的绝对定位宏。

对于后两种方式,在后面指针一节介绍。

C51扩展的关键字_at_专门用于对变量作绝对定位,_at_使用在变量的定义中,其格式为:

[存储类型]数据类型[存储区]变量名1_at_地址常数[,变量名2…]

举例说明_at_的使用方法

1)对data区域中的unsignedchar变量aa作绝对定位:

unsignedchardataaa_at_0x30;

2)对pdata区域中的unsignedint数组cc作绝对定位:

unsignedintpdatacc[10]_at_0x34;

3)对xdata区域中的unsignedchar变量printer_port作绝对定位:

unsignedcharxdataprinter_port_at_0x7fff;

对变量绝对定位的几点说明:

1)绝对地址变量在定义时不能初始化,因此不能对code型变量绝对定位;

2)绝对地址变量只能够是全局变量,不能在函数中对变量绝对定位;

3)绝对地址变量多用于I/O端口,一般情况下不对变量作绝对定位;

3)位变量不能使用_at_绝对定位。

Ø4.4C51位变量的定义

Ø4.4.1bit型位变量的定义

常说的位变量指的就是bit型位变量。

C51的bit型位变量定义的一般格式为:

[存储类型]bit位变量名1[=初值]

[,位变量名2[=初值]][,…]

bit位变量被保存在RAM中的位寻址区域(字节地址为0x20~0x2f,16字节)。

例如:

bitflag_run,receiv_bit=0;

staticbitsend_bit;

两点说明:

1)bit型位变量与其它变量一样,可以作为函数的形参,也可以作为函数的返回值,即函数的类型可以是位型的;

2)位变量不能定义指针,不能定义数组。

Ø4.4.2sbit型位变量的定义

对于能够按位寻址的特殊功能寄存器、定义在位寻址区域的变量(字节型、整型、长整型),可以对其各位用sbit定义位变量。

为了方便起见,分开讨论按位寻址的特殊功能寄存器中位变量的定义、按位寻址的变量中位变量的定义。

一、特殊功能寄存器中位变量定义

能够按位寻址的特殊功能寄存器中位变量定义的一般格式为:

sbit位变量名=位地址表达式

这里的位地址表达式有三种形式:

直接位地址

特殊功能寄存器名带位号

字节地址带位号

1、用直接位地址定义位变量

这种情况下位变量的定义格式为:

sbit位变量名=位地址常数

这里的位地址常数范围为0x80~0xff,实际是定义特殊功能寄存器的位。

例如:

sbitP0_0=0x80;

sbitP1_1=0x91;

sbitRS0=0xd3;//定义PSW的第3位

sbitET0=0xa9;//定义IE的第1位

2、特殊功能寄存器名带位号定义

这时位变量的定义格式为:

sbit位变量名=特殊功能寄存器名^号常数

这里的位号常数为0~7。

例如:

sbitP0_3=P0^3;

sbitP1_4=P1^4;

sbitOV=PSW^2;//定义PSW的第2位

sbitES=IE^4;//定义IE的第4位

3、寄存器地址带位号定义位变量

在这种情况下位变量的定义格式为:

sbit位变量名=特殊功能寄存器地址^位号常数

这里的位号常数同上,为0~7。

例如:

sbitP0_6=0x80^6;

sbitP1_7=0x90^7;

sbitAC=0xd0^6;//定义PSW的第6位

sbitEA=0xa8^7;//定义IE的第7位

4、几点说明

1)用sbit定义的位变量,必须能够按位操作,而不能够对无位操作功能的位定义位变量。

2)用sbit定义位变量,必须放在函数外面作为全局位变量,而不能在函数内部定义。

3)用sbit每次只能定义一个位变量。

4)对其它模块定义的位变量(bit型或sbit型)的引用声明,都使用bit。

5)用sbit定义的是一种绝对定位的位变量(因为名字是与确定位地址对应的),具有特定的意义,在应用时不能像bit型位变量那样随便使用。

二、位寻址区变量的位定义

对bdata型变量(字节型、整型、长整型),被保存在RAM中的位寻址区,因此可以对bdata型变量各位作位变量定义。

这样,既可以对bdata型变量作字节(或整型、长整型)操作,也可以作位操作。

bdata型变量的位定义格式:

sbit位变量名=bdata型变量名^位号常数

bdata型变量为在此之前应该是定义过的,位号常数可以是0~7(8位字节变量),或0~15(16位整型变量),或0~31(32位字长整型变量)。

例如:

unsignedcharbdataoperate;

对operate的低4位作位变量定义:

sbitflag_key=operate^0;//键盘标志位

sbitflag_dis=operate^1;//显示标志位

sbitflag_mus=operate^2;//音乐标志位

sbitflag_run=operate^3;//运行标志位

Ø4.5C51特殊功能寄存器的定义

Ø4.5.18位特殊功能寄存器的定义

定义的一般格式为:

sfr特殊功能寄存器名=地址常数

地址常数范围:

0x80~0xff。

特殊功能寄存器定义例子(见reg51.h、reg52.h等文件):

sfrP0=0x80;//定义P0寄存器

sfrP1=0x90;//定义P1口寄存器

sfrPSW=0xd0;//定义PSW

sfrIE=0xa8;//定义IE

Ø4.5.216位特殊功能寄存器的定义

定义的一般格式为:

sfr16特殊功能寄存器名=地址常数

地址常数范围:

0x80~0xff。

例如(见reg51.h、reg52.h等文件):

sfr16DPTR=0x82;

sfr16T2=0xcc;//含TL2和TH2

sfr16RCAP2=0xca;//含RCAP2L//和RCAP2H,0xca为RCAP2L的地址

几点说明:

1)定义特殊功能寄存器中的地址必须在0x80~0xff范围内。

2)定义特殊功能寄存器,必须放在函数外面作为全局变量。

3)用sfr或sfr16每次只能定义一个特殊功能寄存器。

4)像sbit一样,用sfr或sfr16定义的是绝对定位的变量(因为名字是与确定地址对应的),具有特定的意义,在应用时不能像一般变量那样随便使用。

Ø4.6C51指针的定义

Ø4.6C51指针的定义

由于MCS-51单片机有三种不同类型的存储空间,并且还有不同的存储区域,因此C51指针的内容更丰富。

指针除了具有像变量的四种属性(存储类型、数据类型、存储区、变量名)外,按存储区,将指针分为通用指针和不同存储区域的专用指针。

Ø4.6.1通用指针

所谓通用指针,就是通过该类指针可以访问所有的存储空间。

在C51库函数中通常使用这种指针来访问。

通用指针用3个字节来表示:

第一个字节:

表示指针所指向的存储空间

第二个字节:

为指针地址的高字节

第三个字节:

为指针地址的低字节

通用指针的定义与一般C语言指针的定义相同,其格式为:

[存储类型]数据类型*指针名1[,*指针名2][,…]

通用指针的特点:

Ø定义简单

Ø访问所有空间

Ø访问速度慢

例如:

unsignedchar*cpt;

int*dpt;

long*lpt;

staticchar*ccpt;

Ø4.6.2存储器专用指针

所谓存储器专用指针,就是通过该类指针,只能够访问规定的存储空间区域。

指针本身占用1个字节(data*,idata*,bdata*,pdata*)或2个字节(xdata*,code*)。

存储器专用指针的一般定义格式为:

[存储类型]数据类型指向存储区

*[指针存储区]指针名1[,*[指针存储区]指针名2,…]

指向存储区:

是指针变量所指向的数据存储空间区域。

不能够缺省。

指针存储区:

是指针变量本身所存储的空间区域。

缺省时认为指针存储区在默认的存储区域,其默认存储区域决定于所设定的编译模式。

指向和指针存储区,两者可以是同一个区域,但多数情况下不会是同一个区域。

存储器专用指针例子:

unsignedchardata*cpt1,*cpt2;

signedintidata*dpt1,*dpt2;

unsignedcharpdata*ppt;

signedlongxdata*lpt1,*lpt2;

unsignedcharcode*ccpt;

上面所定义的指针虽然所指向的空间不同,但指针变量本身都存储在默认的存储区域。

又如:

1)unsignedchardata*idatacpt1,*idatacpt2;

2)signedintidata*datadpt1,*datadpt2;

3)unsignedcharpdata*xdatappt;

4)signedlongxdata*lpt1,*xdatalpt2;

5)unsignedcharcode*dataccpt;

前关键字为指针所指向的存储区

后关键字为指针本身所存储的区域

注意:

(1)要区分指针变量指向的空间区域和指针变量本身所存储的区域;

(2)定义时,前者不能缺省,而后者可以缺省;(3)指针变量的长度:

指向不同的区域,占用的字节数不同。

说明:

指针

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 初中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1