8051单片机的C语言程序设计

一、数据类型
(一)基本类型:
1. 位类型(bit):1)是C51的扩充数据类型,用于访问8051中可寻址的位单元。
2)8051支持两种位类型:bit型和sbit类型,它们在内存中都只占一个二进制位,其值可以是1或0。
3)用bit定义的位变量在C51编译器编译时,在不同的时候位地址是可以变化的。
4)用sbit定义的位变量必须与8051系列单片机的一个可以寻址单元或可位寻址的字节单元中的某一位
联系在一起,在C51编译器编译时,其对应的位地址是不可以变化的。
2. 字符型(char):1)有signed char和unsigned char之分,默认signed char。占一个字节。
2)signed char定义带符号字节数据,字节最高位用0表示正数,1表示负数,一补码表示,数值
范围-128~+127.
3)unsigned char定义无符号字节数据或字符,可以存放一个字节的无符号数,数值范围0~255;
unsigned char还可以表示西文字符,占一个字节,在计算机中用ASCII码存放
3. 整型(int):1)有signed int和unsigned int之分,默认signed int。占两个字节。
2)signed int,用于存放两字节带符号数,以补码表示,数值范围-32768~+32767;
3)unsigned int,用于存放两个字节无符号数,数值范围0~65535;
4. 长整型(long):1)有signed long和unsigned long之分,默认signed long,占4个字节;
2)signed long,用于存放4字节带符号数,以补码表示,数值范围-2147483648~+2147483648;
3)unsigned long,用于存放4个字节无符号数,数值范围0~4294967695;
5. 浮点型(float):占4个字节
6. 特殊功能寄存器型:1)这是C51的扩充的数据类型,用于访问8051单片机中的特殊功能寄存器数据;
2)分为sfr和sfr16两种。sfr为字节型特殊功能寄存器类型,占一个字节单元,利用它可以访问
8051单片机内部所有的特殊功能寄存器;sfr16为2字节特殊功能寄存器类型,占2进行个字
节单元,利用它可以访问8051单片机内部所有2字节的特殊功能寄存器。
3)在C51中对特殊功能寄存器的访问必须先用sfr和sfr16进行声明
(二)构造类型
1. 数组类型(array)
2. 结构体类型(struct)
3. 共用体(union)
4. 枚举(enum)
(三)指针类型
指针型本身是一个变量,在这个变量中存放着指向另一个数据的地址。这个指针变量要占用一定的内 存单元,对于不 同的处理器器长度不一样,在C51中指针的长度一般为1~3个字节。
(四)空类型
二、C51的运算量
(一)常量
包括整型常量、浮点型常量、字符型常量、字符串型常量
(二)变量
1. 存储器类型在这里插入图片描述
2. 特殊功能寄存器变量
1)格式:sfr/sfr16 特殊功能寄存器名=地址。
2)特殊功能寄存器名一般用大写字母表示,地址一般采用直接地址形式,具体特殊功能寄存器地址看之前的文章
例:sfr PSW=0xD0;–>定义程序状态字PSW的地址为D0H;
sfr TMOD=0x89;–>定义定时器控制寄存器TMOD的地址为89H;
sfr P1=0x90;–>定义p1端口的地址为90H;
3. 位变量
1)格式:bit 位变量名(注意:在格式中可以加上各种修饰符,但存储器类型只有bdata data idata)
例:bit data a1;正确
bit pdata a2;错误
2)格式:sbit 位变量名=位地址;(注意:如位地址为为直接地址,其取值范围为0x00~0xFF;如位地址是可位寻址变量带位号或特殊功能寄存器名带位号,则在它前面需对可位寻址变量或特殊功能寄存器进行定义。字节地址与位号之间、特殊功能寄存器与位号之间一般用……作间隔。
例:sbit Cy=0xD7;–>定义进位标志Cy的地址位D7H;
sbit AC=0xD0……6;–>定义辅助进位标志AC的地址为D6H;
sbit RS0=0xD0^3;–>定义RS0的地址为D0H;
(三)存储模式
C51编译器支持3种存储模式:SMALL模式、COMPACT模式和LARGE模式。
1. SMALL模式:称为小编译模式,编译时函数参数和变量被默认在片内RAM中,存储器类型为data;
2. COMPACT模式:称为紧凑编译模式,函数参数被默认在片外RAM的低256B空间,存储类型为pdata;
3. LARGE模式:称为大编译模式,编译时函数参数和变量被默认在片外RAM的64B空间,存储类型为xdata;
在程序中变量存储模式的指定通过#pragma预处理指令来实现。函数的存储模式可通过函数定义时后面带存储模式来说明。如果没有指定,则默认为SMALL模式。
例:#pragma small/int func() small/int func() -->都是变量的存储模式为small模式
(四)绝对地址访问
在C51中,可以通过变量的形式访问8051单片机的的存储器,也可以通过绝对地址来访问存储器,访问绝对地址有3种
1. 使用C51运行库中预定义宏(使用时加头文件 #include <absacc.h>)
在C51中,可以通过变量的形式访问8051单片机的code、data、pdata、xdata空间进行绝对寻址。规定只能以无符号的方式访问,定义了8个宏,原型如下:
#difine CBYTE((unsigned char volatile*)0x50000L)–>(CBYTE以字节形式对code区寻址)
#difine DBYTE((unsigned char volatile*)0x40000L)–>(DBYTE以字节形式对data区寻址)
#difine PBYTE((unsigned char volatile*)0x30000L)–>(PBYTE以字节形式对pdata区寻址)
#difine XBYTE((unsigned char volatile*)0x20000L)–>(XBYTE以字节形式对xdata区寻址)
#difine CWORD((unsigned int volatile*)0x50000L)–>(CWORD以字节形式对code区寻址)
#difine DWORD((unsigned int volatile*)0x50000L)–>(DWORD以字节形式对data区寻址)
#difine PWORD((unsigned int volatile*)0x50000L)–>(PWORD以字节形式对pdata区寻址)
#difine XWORD((unsigned int volatile*)0x50000L)–>(XWORD以字节形式对xdata区寻址)
访问形式:宏名[地址];其中CBYTE、DBYTE、PBYTE、XBYTE、CWORD、DWORD、PWORD、XWORD为宏名,地址用16进制表示:
例:var1 = XBYTE[0x0005];–>XBYTE[0x0005]访问片外RAM的0005字节单元;
2. 通过指针访问
采用指针的方法,可以实现C51程序中对任意指定的存储器单元进行访问。
例: int xdata *dpt1;–>定义一个指向xdata区的指针dpt1;
dpt1=0x30;–>dpt1指针赋值,指向xdata区的30H单元;
dpt1=0xFF;–>将数据0xFF送到片外RAM的30H单元;
3. 使用C51关键扩展字_at_
使用_at_是对指定的存储器空间的绝对地址进行访问,格式:[存储器类型] 数据类型说明符 变量名 at 地址常数;
地址常数用于指定变量的绝对地址,必须位于有效的存储空间之内,使用_at_定义的变量必须为全局变量。
例:data char x1_at_0x40;–>在data区中定义字节变量x1,它的地址为40H;
三、函数
(一)函数的定义
一般格式:函数类型 函数名(形式参数表) [reentrant] [interrupt m] using n
(二)reentrant修饰符
在C51中,这个修饰符用于把函数定义可重入函数。所谓的可重入的函数就是允许被递归调用的函数。一般的函数不可以递归调用,只有可重入函数才允许递归调用。在C51中,当函数被定义为可重入函数,C51编译器编译时将会为可重入函数生成一个模块栈,通过这个模块栈来完成参数的传递和局部变量存放。关于可重入函数,应该注意以下几点:
1. 用reentrant修饰的可重入函数被调用的时,实参列表内不允许使用bit类型的参数。函数体内也不允许存在任何关于位变量的操作,更不能返回bit类型的值。
2. 编译时,系统为可重入函数在内部或外部存储器中建立一个模拟堆栈区,称为重入栈。可重入函数的局部变量及参数被放入重入栈中,时可重入函数可以实现被递归调用。
3. 在参数的传递上,实际参数可以传递给间接调用的可重入参数。无重入属性的间接调用函数不能包含调用函数,但是可以使用定义的全局变量来进行参数传递。
(三)interrupt m修饰符
interrupt m是C51函数中一个非常重要的修饰符,是因为中断函数必须通过它来进行修饰。在C51程序设计时,当函数用interrupt 修饰时,系统编译把对应的函数转化为中断函数,自动加上程序头段和尾段,并按MCS-51系统中断的处理方式自动把它安排在程序存储器的相应位置。在该修饰符中,m的取值为0~31,对应的中断如下:
0——外部中断;1——定时器/计数器T0;2——外部中断;3——定时器/计数器T1;
4——串行口中断;5——定时器/计数器T2;其他值预留。使用中断函数应注意以下7点:
1. 中断函数不能进行参数传递,如果中断函数中包含任何参数声明,都将导致编译出错;
2. 中断函数没有返回值,如果试图定义一个返回值,将得不到正确的结果,建议在定义中断函数时将其定义为void型,以说明没有返回值;
3. 在任何情况下都不能之间调用中断函数,否则会产生编译错误。因为中断函数的返回由8051单片机的RETI指令完成,RETI指令影响8051单片机的硬件中断系统。如果在没有实际中断情况下之间调用中断函数,RETI指令的操作结果会产生一个致命的错误。当中断条件满足时自动调用。
4. 如果在中断函数中直接调用了其他函数,则被调用函数所使用的寄存器必须与中断函数相同,否则不会输出正确结果。
5. C51编译器对中断函数编译时,会自动在程序开始和结束加上相应的内容。具体如下:在程序开始处ACC、B、DPH、DPL、PSW入栈,结束时出栈;中断函数未加using n修饰符的,开始时还要将R0~R1入栈,结束时出栈,如中断函数加using n修饰符,则在开始PSW将入栈后还要修改PSW中的工作寄存组选择位。
6. C51编译器从绝对地址8m+3处产生一个中断向量,其中m为中断号,即interrupt后面的数字,该向量包含一个到中断函数入口的绝对跳转。
7. 中断函数最好写在文件的尾部,并且禁止使用extern存储类型说明,以防其他程序调用。
(四)using n修饰符
MCS-51单片机有4组工作寄存器:0组、1组、2组、3组。每组8个寄存器,分别用R0~7R表示。修饰符using n用于指定本函数内部使用的工作寄存器组,其中n的取值范围0–3,表示寄存器组号。对应using n的使用,注意以下几点:
1. 加入using n后,C51在编译时自动在函数的开始处和结束处加入以下命令。
{
PUSH PSW;//标志寄存器入栈
MOV PSW,#与寄存器组号n相关的常量;//常量值为(PSW&OXET)&n
8
~~~~~
POP PSW;//标志寄存器出栈
}
2. using n修饰符不能用于有返回值的函数,因为C51函数的返回值是放在寄存器中的。如果寄存器组改变了,返回值就会出错。

猜你喜欢

转载自blog.csdn.net/y_a_n_g_12/article/details/109109593