C51与标准C语言有何核心差异?

99ANYc3cd6
预计阅读时长 13 分钟
位置: 首页 C语言 正文

C51 是标准C语言的一个超集,它专门为8051架构的微控制器进行了深度扩展和定制。

c51语言在标准c语言
(图片来源网络,侵删)

你可以把C51理解为“为8051单片机量身定做的C语言”,它保留了标准C语言的核心语法和大部分特性,但增加了一系列独特的功能来直接操作8051的硬件资源,如特殊功能寄存器、位寻址区、I/O端口等。


详细对比与解析

为了更好地理解,我们从几个关键方面来对比它们:

特性 标准C语言 (ANSI C) C51语言 (Keil C) 解释与差异
数据类型 char, int, float, double, long, short, void 增加了 bit, sbit, sfr, sfr16 这是C51最核心的扩展。
bit: 定义一个位变量,存储在8051内部的位寻址区 (20H-2FH)。
sbit: 定义一个可位寻址的特殊功能寄存器的某一位(如 EA, TR0)。
sfr: 定义一个8位的特殊功能寄存器(如 P0, TMOD, SCON)。
sfr16: 定义一个16位的特殊功能寄存器(如 DPTR)。
标准C没有这些直接操作硬件位和寄存器的类型。
存储类型 无明确的、与硬件相关的存储类型关键字。 增加了 data, bdata, idata, xdata, pdata, code 这是C51的另一大核心扩展。
8051有独特的内存结构(内部RAM、外部RAM、程序存储器),C51通过这些关键字告诉编译器变量存放在哪个区域,以优化访问速度。
data: 直接寻址的内部RAM (128字节),最快。
bdata: 可位寻址的内部RAM (16字节)。
idata: 间接寻址的内部RAM (256字节,包括128字节data)。
xdata: 外部RAM (64KB),速度较慢。
pdata: 分页寻址的外部RAM (256字节)。
code: 程序存储器 (64KB),存放常量和代码。
函数修饰符 无。 增加了 reentrant 用于解决8051架构下的递归和重入问题。
8051的堆栈空间有限,且通常位于内部RAM,对于需要被中断服务程序调用的函数,或自身会调用自己的递归函数,必须声明为 reentrant,编译器会为其创建一个模拟堆栈,通常放在外部RAM中,以保证数据安全。
中断处理 标准C不包含中断的概念。 使用 interrupt 关键字 这是C51实现中断编程的核心方式。
你可以这样定义一个中断服务函数:
void Timer0_ISR() interrupt 1
interrupt: 关键字,告诉编译器这是一个中断函数。
1: 中断号,对应8051的特定中断源(如0是外部中断0,1是定时器0溢出,2是外部中断1,等等)。
编译器会自动在中断入口处添加保护现场(如 PUSH PSW, ACC)和恢复现场(POP ACC, PSW)的指令,并自动生成中断返回指令 RETI
指针 指针非常通用,可以指向任何内存地址。 增加了基于存储类型的指针 (data *, xdata * 等) 为了优化访问效率。
标准C的指针大小是固定的(通常是2或4字节),在8051这种架构复杂的单片机上,一个指向内部RAM的指针和一个指向外部64KB RAM的指针,其生成机器码的效率是不同的,C51允许你指定指针指向的存储区域,编译器可以生成更紧凑、更高效的访问代码。
库函数 标准C库 (stdio.h, stdlib.h, math.h 等)。 包含标准C库,并增加了针对8051的硬件库函数 C51保留了大部分标准C库,但去除了像文件操作 (fopen, fprintf)、动态内存分配 (malloc) 等与操作系统或复杂硬件无关的函数,增加了如 printf 的变体(可以重定向到串口)、cprintf,以及访问定时器、串口等外设的库函数。
编译与链接 通用编译器 (GCC, Clang, MSVC),链接到通用操作系统或可执行文件。 专用编译器 (Keil C51/Auvidea),链接到8051的启动代码和目标硬件 C51编译器生成的目标代码是针对8051指令集的,链接过程会将你的代码、库函数、启动代码(用于初始化堆栈、数据段等)以及中断向量表链接成一个可以在8051上运行的最终.hex.bin文件。

一个简单的C51代码示例

下面是一个典型的C51程序,它展示了上述关键特性的使用:

#include <reg51.h> // 包含8051所有特殊功能寄存器的头文件
// 1. 定义一个位变量
bit flag; // 使用 bit 关键字
// 2. 定义特殊功能寄存器的位
sbit LED = P1^0; // 将P1端口的第0位命名为LED
sbit EA = IE^7;  // 将中断允许寄存器的第7位(总中断)命名为EA
// 3. 定义一个使用data存储区的变量
unsigned char counter data = 0; // 存放在最快的内部RAM区
// 4. 定义一个使用code存储区的常量表
unsigned char code seg_table[] = {0x3F, 0x06, 0x5B, ...}; // 存放在程序存储器
// 5. 定义一个可重入函数(可能被中断和主函数同时调用)
int calculate(int a, int b) reentrant
{
    // ...
    return a + b;
}
// 6. 定义一个中断服务函数
void Timer0_ISR() interrupt 1 // interrupt 1 表示定时器0溢出中断
{
    // 中断服务代码
    TH0 = (65536 - 50000) / 256; // 重新装载定时器初值
    TL0 = (65536 - 50000) % 256;
    flag = ~flag; // 翻转标志位
}
void main(void)
{
    // 初始化
    TMOD = 0x01;    // 设置定时器0为模式1
    TH0 = (65536 - 50000) / 256;
    TL0 = (65536 - 50000) % 256;
    EA = 1;         // 开启总中断
    ET0 = 1;        // 开启定时器0中断
    TR0 = 1;        // 启动定时器0
    while(1)
    {
        // 主循环
        if(flag)
        {
            LED = 0; // 点亮LED
        }
        else
        {
            LED = 1; // 熄灭LED
        }
        counter = calculate(counter, 1); // 调用可重入函数
    }
}

标准C语言 C51语言
定位 通用、跨平台的编程语言。 专用于8051架构单片机的嵌入式C语言。
核心 高级抽象、数据结构、算法。 硬件寄存器操作、内存管理、中断处理。
关系 基础和前提 超集和扩展,在标准C之上增加了大量面向8051硬件的特性。
适用场景 操作系统、桌面应用、服务器、大型嵌入式系统(如Linux设备)。 资源受限的8位/16位单片机,如8051、STC系列、AT89系列等。

对于学习嵌入式开发的初学者来说,先掌握标准C语言是绝对必要的,因为它是所有C语言衍生的基础,再学习C51的扩展部分,就很容易上手8051单片机的开发了,虽然更强大的ARM Cortex-M系列单片机已经成为主流,但C51的很多设计思想(如对特定硬件的抽象、中断处理模型等)在更高级的嵌入式C语言中依然能看到影子。

c51语言在标准c语言
(图片来源网络,侵删)
c51语言在标准c语言
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
dede首页练级如何获取?
« 上一篇 04-23
dede上传文件失败怎么办?
下一篇 » 04-23

相关文章

取消
微信二维码
支付宝二维码

目录[+]