(玩电子) 电子技术学习与研讨
当时方位:单片机教程网 >> 根底教程 >> 阅览文章

第五课 C51变量

作者:佚名   来历:本站原创   点击数:x  更新时刻:2007年07月18日   【字体:
  上课所说到变量便是一种在程序履行过程中其值能不断改动的量。要在程序中运用变量有必要先用标识符作为变量名,并指出所用的数据类型和存储形式,这样编译体系才能为变量分配相应的存储空间。界说一个变量的格局如下:
    [存储品种] 数据类型 [存储器类型] 变量名表
  在界说格局中除了数据类型和变量名表是必要的,其它都是可选项。存储品种有四种:主动(auto),外部(extern),静态(static)和寄存器(register),缺省类型为主动(auto)。这些存储品种的详细意义和运用办法,将在第七课《变量的存储》中进一步进行学习。
  而这儿的数据类型则是和咱们在第四课中学习到的名种数据类型的界说是相同的。阐明晰一个变量的数据类型后,还可挑选阐明该变量的存储器类型。存储器类型的阐明便是指定该变量在单片机c言语硬件体系中所运用的存储区域,并在编译时精确的定位。表6-1中是KEIL uVision2所能认其他存储器类型。留意的是在AT89c51芯片中RAM只要低128位,坐落80H到FFH的高128位则在52芯片中才有用,并和特别寄存器地址堆叠。特别寄存器(SFR)的地址表请看附录二 AT89c51特别功用寄存器列表

表6-1 存储器类型

存储器类型

说 明

data

直接拜访内部数据存储器(128字节),拜访速度最快

bdata

可位寻址内部数据存储器(16字节),答应位与字节混合拜访

idata

直接拜访内部数据存储器(256字节),答应拜访悉数内部地址

pdata

分页拜访外部数据存储器(256字节),用MOVX @Ri指令拜访

xdata

外部数据存储器(64KB),用MOVX @DPTR指令拜访

code

程序存储器(64KB),用MOVC @A+DPTR指令拜访

 


  假如省掉存储器类型,体系则会按编译形式SMALL,COMPACT或LARGE所规矩的默许存储器类型去指定变量的存储区域。无论什么存储形式都能声明变量在任何的8051存储区规模,然而把最常用的指令如循环计数器和行列索引放在内部数据区能明显的进步体系功用。还有要指出的便是变量的存储品种与存储器类型是彻底无关的。

. 数据存储形式
存储形式决议了没有清晰指定存储类型的变量,函数参数等的缺省存储区域,共三种:
1. 1. Small形式
一切缺省变量参数均装入内部RAM,长处是拜访速度快,缺陷是空间有限,只适用于小程序。
2. 2. Compact形式
一切缺省变量均坐落外部RAM区的一页(256Bytes),详细哪一页可由P2口指定,在STARTUP.A51文件中阐明,也可用pdata指定,长处是空间较Small为宽余速度较Small慢,较large要快,是一种中间状态。
3. 3. large形式
一切缺省变量可放在多达64KB的外部RAM区,长处是空间大,可存变量多,缺陷是速度较慢。
提示:存储形式在单片机c言语编译器选项中挑选。

  之前说到简略说到sfr,sfr16,sbit界说变量的办法,下面咱们再来细心看看。
  sfr和sfr16能直接对51单片机的特别寄存器进行界说,界说办法如下:
    sfr 特别功用寄存器名= 特别功用寄存器地址常数;
    sfr16 特别功用寄存器名= 特别功用寄存器地址常数;
  咱们能这样界说AT89c51的P1口
    sfr P1 = 0x90; //界说P1 I/O口,其地址90H
  sfr要害定后边是一个要界说的姓名,可任意选取,但要契合标识符的命名规矩,姓名最好有必定的意义如P1口能用P1为名,这样程序会变的好读很多。等号后边有必要是常数,不答应有带运算符的表达式,并且该常数有必要在特别功用寄存器的地址规模之内(80H-FFH),详细可检查附录中的相关表。sfr是界说8位的特别功用寄存器而sfr16则是用来界说16位特别功用寄存器,如8052的T2定时器,能界说为:
    sfr16 T2 = 0xCC; //这儿界说8052定时器2,地址为T2L=CCH,T2H=CDH
用sfr16界说16位特别功用寄存器时,等号后边是它的低位地址,高位地址必定要坐落物理低位地址之上。留意的是不能用于定时器0和1的界说。
  sbit可界说可位寻址目标。如拜访特别功用寄存器中的某位。其实这样应用是常常要用的如要拜访P1口中的第2个引脚P1.1。咱们能照以下的办法去界说:
(1)sbit 位变量名=位地址
  sbit P1_1 = Ox91;
这样是把位的肯定地址赋给位变量。同sfr相同sbit的位地址有必要坐落80H-FFH之间。
(2)Sbit 位变量名=特别功用寄存器名^位方位
sft P1 = 0x90;
  sbit P1_1 = P1 ^ 1; //先界说一个特别功用寄存器名再指定位变量名地点的方位
当可寻址位坐落特别功用寄存器中时可采用这种办法
(3)sbit 位变量名=字节地址^位方位
  sbit P1_1 = 0x90 ^ 1;
  这种办法其实和2是相同的,仅仅把特别功用寄存器的位址直接用常数表明。
  在单片机c言语存储器类型中供应有一个bdata的存储器类型,这个是指可位寻址的数据存储器,坐落单片机的可位寻址区中,能将要求可位录址的数据界说为bdata,如:
unsigned char bdata ib; //在可位录址区界说ucsigned char类型的变量ib
int bdata ab[2]; //在可位寻址区界说数组ab[2],这些也称为可寻址位目标
sbit ib7=ib^7 //用要害字sbit界说位变量来独立拜访可寻址位目标的其间一位
sbit ab12=ab[1]^12;
  操作符"^"后边的位方位的最大值取决于指定的基址类型,char0-7,int0-15,long0-31。
下面咱们用上一课的电路来实践一下这一课的常识。同样是做一下简略的跑马灯试验,项目名为RunLED2。程序如下:

sfr P1 = 0x90; //这儿没有运用预界说文件,
sbit P1_0 = P1 ^ 0; //而是自己界说特别寄存器
sbit P1_7 = 0x90 ^ 7; //之前咱们运用的预界说文件其实便是这个效果
sbit P1_1 = 0x91; //这儿别离界说P1端口和P10,P11,P17引脚

void main(void)
{
unsigned int a;
unsigned char b;
do{
for (a=0;a<50000;a++)
P1_0 = 0; //点亮P1_0
for (a=0;a<50000;a++)
P1_7 = 0; //点亮P1_7
for (b=0;b<255;b++)
{
for (a=0;a<10000;a++)
P1 = b; //用b的值来做跑马灯的把戏
}
P1 = 255; //平息P1上的LED
for (b=0;b<255;b++)
{
for (a=0;a<10000;a++) //P1_1闪耀
P1_1 = 0;
for (a=0;a<10000;a++)
P1_1 = 1;
}
}while(1);
}

 

. Keil c51指针变量
单片机c言语支撑一般指针(Generic Pointer)和存储器指针(Memory_Specific Pointer).
1. 1. 一般指针
一般指针的声明和运用均与规范C相同,不过一起还能阐明指针的存储类型,例如:
long * state;为一个指向long型整数的指针,而state自身则依存储形式寄存。
char * xdata ptr;ptr为一个指向char数据的指针,而ptr自身放于外部RAM区,以上的long,char等指针指向的数据可寄存于任何存储器中。
一般指针自身用3个字节寄存,别离为存储器类型,高位偏移,低位偏移量。
2. 2. 存储器指针
根据存储器的指针阐明时即指定了存贮类型,例如:
char data * str;str指向data区中char型数据
int xdata * pow; pow指向外部RAM的int型整数。
这种指针寄存时,只需一个字节或2个字节就够了,由于只需寄存偏移量。
3. 3. 指针转化
即指针在上两品种型之间转化:
l 当根据存储器的指针作为一个实参传递给需求一般指针的函数时,指针主动转化。
l 假如不阐明外部函数原形,根据存储器的指针主动转化为一般指针,导致过错,因此请用“#include”阐明一切函数原形。
l 能强行改动指针类型。

 变量的存储类别

一、static(静态部分)变量。
1、静态部分变量在程序整个运转期间都不会开释内存。
2、关于静态部分变量,是在编译的时分赋初值的,即只赋值一次。假如在程序运转时现已有初值,则今后每次调用的时分不再从头赋值。
3、假如界说部分变量的时分不赋值,则编译的时分主动赋值为0。而关于主动变量而言,界说的时分不赋值,则是一个不确定的值。
4、尽管静态变量在函数调用完毕后依然存在,可是其他函数不能引证。
 
  二、用extern声明外部变量。
用extern声明外部变量,是为了扩展外部变量的效果规模。比方一个程序能由多个源程序文件组成。假如一个程序中需求引证其他一个文件中现已界说的外部变量,就需求运用extern来声明。
  正确的做法是在一个文件中界说外部变量,而在其他一个文件中运用extern对该变量作外部变量声明。
  一个文件中:   int abc;
  其他一个文件中:   extern abc;
 
比方:
用extern将外部变量的效果域扩展到其他文件:
文件1:
//用extern将外部变量的效果域扩展到其他文件中
#include
#include
#include
unsigned int array[10];
void fillarray();
void init_ser()
{
 SCON=0X50;
 TMOD|=0X20;
 TH1=0XF3;
 TR1=1;
 TI=1;
}
void main()
{
 unsigned int i;
 init_ser();
 fillarray();
 for(i=0;i<10;i++)
 {
  printf("array[%d]=%d\n",i,array[i]);
 }
  for(;;){;}
}
 
文件2:
extern int array[10];
void fillarray()
{
 unsigned char i;
 for(i=0;i<10;i++)
 {
  array[i]=i;
 }
}

 

在单片机c言语中变量的空间分配几个办法

1、 data区空间小,所以只要频频用到或对运算速度要求很高的变量才放到data区内,比方for循环中的计数值。

2、 data区内最好放部分变量。

由于部分变量的空间是能掩盖的某个函数的部分变量空间在退出该函数是就开释,由其他函数的部分变量掩盖),能进步内存利用率。当然静态部分变量在外,其内存运用办法与全局变量相同;

3、 保证你的程序中没有未调用的函数。

在Keil C里遇到未调用函数,编译器就将其以为可能是中止函数。函数里用的部分变量的空间是不开释,也便是同全局变量相同处理。这一点Keil C做得很愚笨,但也没办法。

4、 程序中遇到的逻辑标志变量能界说到bdata中,能大大下降内存占用空间。

在51系列芯片中有16个字节位寻址区bdata,其间能界说8*16=128个逻辑变量。界说办法是: bdata bit LedState;但位类型不能用在数组和结构体中。

5、 其他不频频用到和对运算速度要求不高的变量都放到xdata区。

6、 假如想节约data空间就有必要用large形式,将未界说内存方位的变量全放到xdata区。当然最好对一切变量都要指定内存类型。

7、 当运用到指针时,要指定指针指向的内存类型。

在单片机c51言语中未界说指向内存类型的通用指针占用3个字节;而指定指向data区的指针只占1个字节;指定指向xdata区的指针占2个字节。如指针p是指向data区,则应界说为: char data *p;。还可指定指针自身的寄存内存类型,如:char data * xdata p;。其意义是指针p指向data区变量,而其自身寄存在xdata区。

宣布谈论】【告知老友】【保藏此文】【封闭窗口

文章谈论

相关文章