C51的特点与使用(增补内容)
C51是一种在MCS—51系列单片机上使用的C语言。相对于汇编语言,C51具有很强的语言表达能力和运算能力,而且可移植性很好。在单片机上用C编写程序,可以有效地提高程序员的工作效率。过去,由于单片机硬件系统运算速度慢,存储器资源少,而实现同样功能的C语言程序,其占用的存储器空间比汇编语言大很多,耗费的时间比汇编语言长很多,使用C语言比较困难。近年来,单片机的运算速度大大提高,存储器的价格大幅降低,而在专业人员的不断努力下,C51编译软件功能增强,使得C51机器码占用的存储器空间缩小,运算速度加快,在单片机系统中使用C51进行程序设计得以实现。
1 C51的特点
C51与ANSI C的规范绝大部分是相同的,以下仅对C51的特殊部分进行必要的说明。 1.1 新增数据类型
bit:片内RAM位变量。但注意不能定义位指针,也不能定义位数组。
例:bit N3_4; //定义一个片内RAM位变量N3_4 sfr:特殊功能寄存器变量。
例:sfr P0 = 0x80; //定义一个特殊功能寄存器变量P0 sfr16:双字节特殊功能寄存器变量。
sbit:定义特殊功能寄存器中的位变量。
例:sbit EA = 0xAF; //定义一个特殊功能寄存器位变量EA
例:sbit P3_2=P3^2; //定义一个特殊功能寄存器位变量P3_2
1.2 新增的数据存储器类型
data:片内RAM直接寻址区(优先使用30H~7FH,可使用00H~7FH)。
例:unsigned char data HJSQ; //在片内RAM中定义一个无符号字节变量HJSQ
bdata:片内RAM位寻址区(使用20H~2FH)。
例:bit bdata CXJS; //在片内RAM位寻址区定义一个位变量CXJS idata:片内RAM间接寻址区(优先使用80H~FFH,可使用00H~FFH)。 例:unsigned char idata BUFFER[8]; //在片内RAM间接寻址区定义
//一个数组变量BUFFER xdata:片外RAM的全部空间(使用MOVX @DPTR寻址)。
例:unsigned char xdata * data x; //在片内RAM中定义一个指向
//片外RAM中的无符号字节变量的指针
pdata:分页访问的片外RAM的一个页面,即0~255(使用MOVX @Ri寻址)。 code:程序存储器空间。
例:unsigned char code zxb[]={0x77,0x14,0xB3,0xB6,0xD4, //01234 字形表
0xE6,0xE7,0x34,0xF7,0xF6, //56789
0x00,0x80}; // -
如果在定义变量时省略了存储器类型,则按编译模式SMALL、COMPACT或LARGE确定变量的存储器类型。模式在编译软件中设置。
SMALL:变量定义在片内RAM中。
COMPACT:变量定义在分页片外RAM中(使用MOVX A,@Ri访问)。 LARGE:变量定义在片外RAM中(使用MOVX A,@DPTR访问)。 1.3 新增中断服务函数
函数类型 函数名(形式参数表) [interrupt n] [using n]
关键字interrupt后面的n是中断号,n的取值范围为0~31。MCS—51单片机常用中断源的中断号和中断向量如表1。
表1 常用中断号与中断向量
N 0 1 2 3 4 中断源 外部中断0 定时器/计数器0 外部中断1 定时器/计数器1 串行口 中断向量8n+3 0003H 000BH 0013H 001BH 0023H 关键字using用来设定该中断服务函数中使用的工作寄存器组。n的取值范围为0~3,分别用来选用0~3组。
例:定时器0中断服务程序,使用工作寄存器1区。 void timer0(void) interrupt 1 using 1 {
… }
单片机响应定时器0中断时进入该程序,在程序中使用工作寄存器1区,程序执行完毕后返回中断前的断点继续执行。
1.4 位运算符
~:按位取反。例:WD_L=~WD_L。
&:按位与。例:a=WD_L&0X08。 |:按位或。例:P1=BAK|0xc0。 ^:按位异或。例:P1=BAK^0xc0。 <<:左移。例:a=WD_H<<4。 >>:右移。例:a=WD_L>>4。
2 C51的使用
1. 在头文件reg51.h或其他头文件中,已经将各个特殊功能寄存器及可使用的位作了定义,用语句#include
2. 3. 速度。
4. char变量有signed char和unsigned char,分别用于有符号字节变量和无符号字节变量,并非只用于保存字符。
5. 中断服务函数中最好不要再调用其它函数。函数中为提高指令执行效率,会把工作寄存器作为直接寻址的片内RAM单元使用,例如当选用工作寄存器0组时,MOV A,R3与MOV A,03H是等价的。当中断服务函数使用的工作寄存器组与其它函数中使用的工作寄存器组不一致时,就会发生错误。
6. 注意逻辑运算符||、&&与位运算符|、&的区别,关系运算符= =与赋值运算符=的区别。||和&&用于连接两个条件,|和&用两个变量或常量的运算。= =用于连接两个变量或常量构成一个条件,=用于将一个变量或常量的值赋给一个变量。
用语句#include < stdio.h>将头文件stdio.h加入后,即可使用C51的库函数。
频繁使用的变量,最好定义成片内RAM存储器类型,这样有利于提高程序的运行
7. 对特殊功能寄存器的操作是通过sfr和sbit变量实现的。例如:
IE=0x82,P1=0xc0,EA=0;
8. 存储数据表可以用数组。例如:
unsigned char code zxb[]={0x77,0x14,0xB3,0xB6,0xD4, //01234 字形表
0xE6,0xE7,0x34,0xF7,0xF6, //56789 9.
0x00,0x80}; // - 对于无符号数,应使用无符号变量(unsigned)。虽然有符号变量(signed)可以处
理无符号数,但这样做会降低运算速度。
10. 尽量使用短一些的变量,能用8位(char)就不用16位(int),能用16位(int)就不用32位(long),这既能减少对存储器的占用,又能提高运算速度。
11. 编写程序时,若对运算的优先级吃不准,应该多使用括号。例如:
if ((CXKBAK1= =0x54)&&(CXKBAK2= =0x32)&&(i= =0x10))