0
点赞
收藏
分享

微信扫一扫

STC89C52RC单片机额外篇 | 03 - 认识C51编译器支持的数据类型


以前我们在学习C语言的时候,有C语言支持的数据类型,它们被称为标准C,现在对于51单片机,它与标准C的数据类型稍有不同,并且追加了一些关键字。

在标准C语言中基本的数据类型,例如​​char、int、short、long、float​​​与​​double​​​,它们存储数据的长度是有差异的,而在C51编译器中,​​int​​​与​​short​​​是一样的,​​float​​​与​​double​​也是一样的,我们通过表格来看看它们具体的定义:

STC89C52RC单片机额外篇 | 03 - 认识C51编译器支持的数据类型_c语言


对于​​unsigned char、signed char、unsigned int、signed int、unsigned long、signed long​​​这些数据类型,我们在C语言的学习中就已经用得较多,这里不再赘述。下面分别对指针型​​*、bit、sfr、sfr16、sbit​​这五个数据类型进行说明。

1 指针型*

指针型​​*​​可以说是C语言的一大特性,有人说不懂指针,C语言只是学会了一半。在博主看过很多8位单片机开发中,几乎很少看到指针的使用,原因可能是一方面8位单片机往往ROM资源有限,指针往往是操作内存的,另一方面是指针往往与结构体结合使用,定义结构体很大程度上是用于抽象数据类型,便于复用,但在8位单片机较少使用结构体。

指针型*本身是一个变量,在这个变量中存放的是指向另一个数据类型的地址。这个指针变量要占据一定的内存单元,对于不一样的处理器长度也不尽相同,在C51中,它的长度一般为1~3个字节。

后面实践中,博主会逐渐使用指针,方便大家理解。

2 bit 位变量

​bit​​​位变量是C51编译器的一种扩充数据类型,利用它可定义一个位变量,但不能定义为位指针,也不能位数组,例如​​bit* a;、bit a[5];​​​这些是不允许的。它的值是一个二进制位,不是0就是1,类似一些高级语言中的​​Boolean​​​类型中的​​True​​​与​​Flase​​。

3 sfr 特殊功能寄存器

​sfr​​​也是C51编译器的一种扩充数据类型,它占用一个内存单元,值域为0~255。利用它能访问51单片机内部的所有特殊功能寄存器。例如​​sfr P1 = 0x90;​​​这一句定义地址0x90为​​P1​​​端口在片内的寄存器,在后面的语句中可以用​​P1 = 0xff;​​​ (对​​P1​​端口的所有引脚输出高电平)之类的语句来操作特殊功能寄存器。

4 sfr16 16为特殊功能寄存器

​sfr16​​​也是C51编译器的一种扩充数据类型,它占用两个内存单元,值域为0~65535。​​sfr16​​​与​​sfr​​​一样用于操作特殊功能寄存器,不一样的是它操作占两个字节的寄存器,如定义器​​T0​​​与​​T1​​。

5 sbit 可寻址位

​sbit​​​同样是C51编译器的一种扩充数据类型,利用它能访问芯片内部的RAM中的可寻址位或者特殊功能寄存器中的可寻址位。例如之前定义了​​sfr P1 = 0x90;​​​(​​P1​​​端口的寄存器是支持位寻址的),现在可以定义​​sbit P1_1 = P1^1;​​​(定义​​P1_1​​​为​​P1​​​中的​​P1.1​​​引脚)。同样的,我们也可以用地址去定义,例如​​P1.1​​​的地址是0x91,那么我们可以定义​​sbit P1_1 = 0x91;​​,这种定义方式也是可以的。

6 其他扩展关键字

如表所示:

STC89C52RC单片机额外篇 | 03 - 认识C51编译器支持的数据类型_嵌入式_02


这里插个知识点:

程序可以简单的分为code(程序)区,和data (数据)区,code区在运行的时候是不可以更改的,data区放全局变量和临时变量,是要不断的改变的,cpu从code区读取指令,对data区的数据进行运算处理,因此code区存储在什么介质上并不重要,像以前的计算机程序存储在卡片上,code区也可以放在ROM里面,也可以放在RAM里面,也可以放在Flash里面(但是运行速度要慢很多,主要读Flash比读RAM要费时间),因此一般的做法是要将程序放到Flash里面,然后load到RAM里面运行的;data区就没有什么选择了,肯定要放在RAM里面,放到ROM里面改动不了。

读到这里就很好理解​​data​​​关键字(实际上很少用到)与​​code​​​关键字,这里着重介绍​​code​​关键字,因为它经常使用:

unsigned char code word[] = {
0x04,0x10,0x34,0x08,0xC4,0x06,0x04,0x01,
0xC4,0x82,0x3C,0x8C,0x20,0x40,0x10,0x30,
0x0F,0x0C,0xE8,0x03,0x08,0x0C,0x08,0x10,
0x28,0x60,0x18,0xC0,0x00,0x40,0x00,0x00,
};
int code val = 1201;

在单片机中一般都有两块存储区域,ROM和RAM,程序代码存储在ROM中,程序要用的变量存储在RAM中。而“code”的作用就是将其修饰过的变量存储在ROM中而非RAM。

在单片机中,RAM空间都比较小,是比较宝贵的。“​​code​​”的意义就是将一些初始化后值一直保持不变的变量(如固定的常数、表格、常量数组、只读常量等)放置于ROM区,从而节省了RAM空间

注意:用“code”修饰的变量是不能在程序运行时改变的!

剩下的提一下​​interrupt​​​与​​using​​​关键字,​​interrupt​​​是用于声明中断服务程序的关键字,​​using​​​与​​interrupt​​​结合使用,指定使用中断服务程序的寄存器组,这涉及到函数的压栈与出栈问题,只有深入了解了这块才能用好​​using​​​关键字,一般情况不建议使用​​using​​,让编译器给我们的中断服务程序分配寄存器组即可!

7 总结

对于​​sfr​​​与​​sbit​​​定义的一些寄存器,其实在我们开始写程序时包含的头文件就定义了一套,例如​​reg52.h​​头文件的内容如下:

/*--------------------------------------------------------------------------
REG52.H

Header file for generic 80C52 and 80C32 microcontroller.
Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/

#ifndef __REG52_H__
#define __REG52_H__

/* BYTE Registers */
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;

/* 8052 Extensions */
sfr T2CON = 0xC8;
sfr RCAP2L = 0xCA;
sfr RCAP2H = 0xCB;
sfr TL2 = 0xCC;
sfr TH2 = 0xCD;


/* BIT Registers */
/* PSW */
sbit CY = PSW^7;
sbit AC = PSW^6;
sbit F0 = PSW^5;
sbit RS1 = PSW^4;
sbit RS0 = PSW^3;
sbit OV = PSW^2;
sbit P = PSW^0; //8052 only

/* TCON */
sbit TF1 = TCON^7;
sbit TR1 = TCON^6;
sbit TF0 = TCON^5;
sbit TR0 = TCON^4;
sbit IE1 = TCON^3;
sbit IT1 = TCON^2;
sbit IE0 = TCON^1;
sbit IT0 = TCON^0;

/* IE */
sbit EA = IE^7;
sbit ET2 = IE^5; //8052 only
sbit ES = IE^4;
sbit ET1 = IE^3;
sbit EX1 = IE^2;
sbit ET0 = IE^1;
sbit EX0 = IE^0;

/* IP */
sbit PT2 = IP^5;
sbit PS = IP^4;
sbit PT1 = IP^3;
sbit PX1 = IP^2;
sbit PT0 = IP^1;
sbit PX0 = IP^0;

/* P3 */
sbit RD = P3^7;
sbit WR = P3^6;
sbit T1 = P3^5;
sbit T0 = P3^4;
sbit INT1 = P3^3;
sbit INT0 = P3^2;
sbit TXD = P3^1;
sbit RXD = P3^0;

/* SCON */
sbit SM0 = SCON^7;
sbit SM1 = SCON^6;
sbit SM2 = SCON^5;
sbit REN = SCON^4;
sbit TB8 = SCON^3;
sbit RB8 = SCON^2;
sbit TI = SCON^1;
sbit RI = SCON^0;

/* P1 */
sbit T2EX = P1^1; // 8052 only
sbit T2 = P1^0; // 8052 only

/* T2CON */
sbit TF2 = T2CON^7;
sbit EXF2 = T2CON^6;
sbit RCLK = T2CON^5;
sbit TCLK = T2CON^4;
sbit EXEN2 = T2CON^3;
sbit TR2 = T2CON^2;
sbit C_T2 = T2CON^1;
sbit CP_RL2 = T2CON^0;

#endif


举报

相关推荐

0 条评论