哈喽小伙伴们 ,今天给大家科普一个小知识。在日常生活中我们或多或少的都会接触到C51—运算量(重点:特殊功能寄存器变量、位变量方面的一些说法,有的小伙伴还不是很了解,今天就给大家详细的介绍一下关于C51—运算量(重点:特殊功能寄存器变量、位变量的相关内容。
(相关资料图)
C51就是c语言for 51单片机,这里边还是有很多不同的,在c语言里运算量相信都知道那叫一个简单,直接int, float就哦了,当然这里也可以直接int, float,但是他们还是有不同的,这里就介绍一下运算量中的不同!,相同的我就直接跳过~(果断不说了,不同的对于以后c语言开发51单片机还是相当有用的,慢慢的就会体会到了~~~~~,尤其是特殊功能寄存器变量、位变量、还有绝对地址的访问!
C51的运算量(只说重点~):
C51中的运算量主要是常量和变量。
1、常量
常量是指在程序执行过程中不能改变的量。在C51中支持整型常量、浮点型常量、字符型常量和字符串型常量。
1)整型常量
2)浮点型常量
3)字符型常量
4)字符串型常量
2、变量
变量就是在程序运行过程中可以改变的量呗。
一个变量有两部分组成:变量名和变量值。每个变量都有一个变量名,在存储器中占用一定的存储单元,变量的数据类型不同,占用的存储单元数就不同。在存储单元中存放的内容就是变量值。
1)数据类型说明符
在定义变量时必须通过数据类型说明符来指明变量的数据类型,指明变量在存储器中占用的字节数。可以使基本数据类型说明符,也可以是组合数据类型说明符,还可以是typedef或者#define定义的类型别名(这里一定要注意typedef一般用来定义别名!尽量不要用#define啊~~我就不解释了,太专业了~~不过用宏定义就一定要用#define)
例如:
typedef unsigned char uchar; //这个是有;的
typedef unsigned int uint;
或者:
#define uchar unsigned char //这个就没有; 而且它们两个定义相反
#define uint unsigned int
2)变量名
变量名有两种:普通变量和指针变量。他们的区别是指针变量名前面带“*”号。
3)存储种类
存储种类是指变量在程序执行过程中的作用范围。C51变量的存储种类有4种,分别是:自动(auto)、外部(extern)、静态(static)和存储器(register)。
a、auto
当定义它的函数体或者复合语句执行时,C51才为该变量分配内存空间,结束时占用的内存空间释放。自动变量一般分配在内存的堆栈空间中。定义变量时,如果缺省存储种类,则默认为此。
b、extern
被定以后分配固定的内存空间,在程序整个执行时间内都有效,知道程序结束时才释放。
c、static
使用static定义的变量成为外部变量,可分为内部静态变量和外部静态变量。在函数体内部定义的静态变量为内部静态变量,它在对应的函数体内有效,一直存在,但在函数体外不可见。这样不仅使变量在定义它的函数体外可以被保护,还可以实现当离开函数体时值不被改变。外部静态变量是在函数体外定义的静态变量,它在程序中一直存在,但在定义的范围之外是不可见的。如在多文件或者多模块处理中(这点很重要,以后会用到很多,尤其是多模块,写大程序必须具备的),外部静态变量只在文件内部或者模块内部有效。
d、register
它定义的变量存放在CPU内部的寄存器中,处理速度快,但是数目有限。
4)存储器类型
存储器类型用来指明变量所处的单片机的存储区域情况。类型如下:
data:直接寻址的片内RAM低128B,访问速度快
bdata:片内RAM的可位寻址区(20H~2FH),允许字节和位混合访问
idata:间接寻址访问的片内RAM,允许访问全部片内RAM
pdata:用Ri简洁访问的片外RAM低256B
xdata:用DPTR间接访问的片外RAM,允许访问全部64KB片外RAM
code:程序存储器ROM64KB
注意:定义变量时可以省略“存储类型”,省略时C51编译器将按存储模式默认存储器类型。具体的存储情况啊~~一会你就知道了,继续往下看~~哈
例如:
char data var1; //在片内RAM低128B定义用直接寻址方式访问的自足型变量var1
unsigned char bdata var2; //在片内RAM位寻址区(20H~2FH)单元定义可字节处理和位处理的无符号字符型变量var2
5)特殊功能寄存器变量
在51单片机中有很多特殊功能寄存器(不过这些有些东西还是不需要我们来关心的~~~因为在调用#include"reg52.h"的时候里面都给你整好了),通过这些特殊功能寄存器可以控制51单片机的定时器、计数器、串口、I/0及其他功能部件(这里很重要的~~~~~~),没一个特殊功能寄存器再片内RAM中都对应一个字节单元或者两个字节单元。
在C51中,允许用户对这些特殊功能寄存器进行访问,但是访问时需要通过sfr或者sfr16类型说明符进行定义,定义是需要指明他们所对应的片内RAM单元的地址。(你过关不用担心,直接调用#include"reg52.h"就哦了~)
例如:
sfr PSW=0xd0;
sfr SCON=0x98;
sfr16 DPTR=0x82;
6)位变量
在C51中,允许用户通过位类型符定义位变量。
位类型符有两个:bit和sbit。可以定义两种位变量。
a、bit型位变量
在格式中可以加上各种修饰,但是要注意存储器类型只能是bdata、data、idata,只能是片内RAM的可位寻址区,严格来说只能是bdata。
例如:
bit bdata a1;
b、sbit型位变量
sbit位类型符用于定义在可位寻址字节或者特殊功能寄存器中的位,定义时需要指明其位地址,可以使位直接地址,可以是可位寻址变量带位号,也可以是特殊功能寄存器名带位号。
例如(这些东西都在#include"reg52.h"中):
sbit OV=0xd2;
sbit CY=0xd7;
unsigned char bdata flag;
sbit flag_0=flag^0; //字节地址与位号之间、特殊功能寄存器与位号之间一般用“^”作间隔
sfr P1=x090;
sbit P1_1=P1^1;
3、存储模式(个人感觉真的用不到这些东东了,因为你丫的要是嫌小可以换个大的,而且还相当的便宜~~~~,我以前试过扩展一个RAM和ROM,擦不成啊~~)
C51编译器支持3种存储模式:SMALL模式、COMPACT模式和LARGE模式。不同的存储模式对变量默认的存储器类型不一样。
1)SMALL模式
SMALL模式成为小编译模式,在SMALL模式下,编译时函数参数以及变量被默认在片内RAM中,存储类型为data。
2)COMPACT模式
COMPACT模式称为紧凑编译模式,在COMPACT模式下,编译时函数参数和变量被默认在片外RAM的低256B空间,存储类型为pdata。
3)LARGE模式
LARGE模式称为大编译模式,在LARGE模式下,编译时函数参数和变量被默认在片外RAM的64KB空间了,存储器类型为xdata。
例如:
#pragma small //变量的存储模式为SMALL
char k1; //存储类型为data
int xdata m1; //存储类型xdata
#pragma compact //变量的存储模式为COMPACT
char k2;
int xdata m2;
int func1(int x1,int y1) large //函数的存储模式为LARGE
{
return(x1+y1);
}
int func2(int x2,int y2) //编译的存储模式隐含为SMALL,没有指明模式,隐含SMALL
{
return(x2-y2);
}
4、绝对地址的访问(这里才是重点中的重点啊~~~)
在C51中,可以通过变量的形势访问51单片机的存储器,也可以通过绝对地址来访问存储器。三种方法:
1)使用C51运行库中预定义宏(就是调用#include"absacc.h")
C51编译器提供了一组宏定义来对51单片机的code、data、pdata和xdata空间进行绝对寻址!
规定只能以无符号数方式访问,定义了8个宏定义,其函数原型如下:
#define CBYTE((unsigned char volatile*)0x50000L) //CBYTE以字节形势对code区寻址
#define DBYTE((unsigned char volatile*)0x40000L)//data区
#define PBYTE((unsigned char volatile*)0x30000L) //pdata区
#define XBYTE((unsigned char volatile*)0x20000L) //xdata区
#define CWORD(unsigned int volatile*)0x50000L) //以字形式对code区寻址
#define DWORD(unsigned int volatile*)0x40000L)
#define PWORD(unsigned int volatile*)0x30000L)
#define XWORD(unsigned int volstile*)0x20000L)
例如:
#include"absacc.h"
#include"reg52.h"
typedef unsigned char uchar;
typedef unsigned intuint;
void main()
{
uchar var1;
uintvar2;
var1=XBYTE[0x0005]; //XBYTE[0x0005]访问片外RAM的0005字节单元
var2=XWORD[0x0002];//XWORD[0x0002]访问片外RAM的0002字单元
.
.
.
while(1);
}
2)通过指针访问
采用指针的访问的方法,可以在C51程序中对任意指定的存储器单元进行访问。
typedef unsigned char uchar;
typedef unsigned int uint;
void func()
{
uchar data var1;
uchar pdata *dp1; //定义一个指向pdata区的指针dp1
uint xdata *dp2; //定义一个指向xdata区的指针dp2,为uint型
uchar data*dp3; //定义一个指向data区的指针dp3,为char型
dp1=0x30; //dp1指针赋值,指向pdata区的30H单元
dp2=0x1000; //dp2指针赋值(uint型),指向xdata区的1000H单元
*dp1=0xff;//将数据0xff送到片外RAM30H单元
*dp2=0x1234; //将数据0x1234(由于是uint型,你懂得~~~),送到片外RAM1000H单元
dp3=&var1; //dp3指针指向data区的var1变量
*dp3=0x20;//给变量var1赋值0x20
}
3)使用C51扩展关键字 _at_ (这个用的最多了~~~)
总算完了,我真的要累死了~~~~擦擦擦擦啊
一般格式:
[存储类型] 数据类型说明 变量名 _at_ 地址常量;
其中,存储类型为data、bdata、idata、pdata、xdata等C51能识别的数据类型,如果省略,则会按照存储模式规定的默认存储类型确定变量的存储区域(这里又用到上边的了);数据类型为C51支持的数据类型;地址常数用于指定变量的绝对地址,必须位于有效的存储器空间之内;使用_at_定义的变量必须为全局变量。
例如:
typedef unsigned char uchar;
typedef unsigned int uint;
data uchar x1 _at_ 0x40; //在data区中定义字节变量x1,地址为0x40H,这里是uchar
xdata uint x2 _at_ 0x2000; //在xdata区中定义字变量x2,它的地址为0x2000H,这里是uint
我感觉我真的不想再写了,累死了~~~擦
不过完工了,爽啊~~解脱