|
Keil的C51编译器是目前各种8051单片机的主流编译器,C51是该编译器制定的单片机C语言标准,本文将介绍C51的各个规范。
一、 基本说明C51语言是基于标准C语言(ANSI C)为8051单片机扩展的专业嵌入式开发语言,由Keil公司实现并集成于µVision开发环境。学习者应首先掌握标准C语法基础,再学习C51的扩展特性。以下按知识点逐条列出学习内容和要求。
二、 特殊功能寄存器(SFR)定义学习目标:能够正确访问单片机内部SFR及其可寻址位。 知识点: 1. sfr关键字 - 用于定义8位特殊功能寄存器,格式:`sfr 寄存器名 = 地址常数;` - 示例:`sfr P0 = 0x80;` // 定义P0口寄存器地址 2. sbit关键字 - 用于定义SFR中的可独立寻址的位。 - 三种格式: sbit 位名 = 寄存器名 ^ 位序号;` sbit 位名 = 地址常数;` (位地址,0x80~0xFF) sbit 位名 = SFR地址 ^ 位序号;` - 示例:`sbit LED = P1^0;` 要求: - 掌握通过 `reg51.h` 或 `reg52.h` 头文件引用已定义的SFR。 - 能独立使用sfr/sbit定义用户所需的寄存器或引脚。
三数据类型学习目标:区分C51与标准C的数据类型差异,理解硬件资源对类型选择的影响。 知识点: 扩展存储类型(重要): - `code` – 程序存储器(只读,存放常量/表格) - `data` – 直接寻址片内数据存储器(最快,128字节) - `idata`– 间接寻址片内数据存储器(256字节) - `bdata`– 可位寻址的片内数据存储器(16字节) - `xdata`– 外部数据存储器(最大64KB,访问较慢) 示例: unsignedchar data var1; // 内部RAM直接寻址 unsignedint xdata buffer[10]; // 外部RAM数组 code chartable[] = {0x3F,0x06}; // 常量表存于ROM ``` 要求: - 熟记每种数据类型在8051中的字节数及默认符号特性(char默认无符号)。 - 能够根据变量用途(频繁访问、数据量大小、位操作)合理选择存储类型。
四、 运算符的分类与功能学习目标:熟悉 C51的各种运算,能正确使用各种运算。 知识点: 算术运算符 - `+`(加)、`-`(减)、`*`(乘)、`/`(除)、`%`(取模) - 功能:执行基本的数学运算。注意整数除法会截断小数部分,取模运算要求操作数为整型。 关系运算符 - `>`、`<`、`>=`、`<=`、`==`(等于)、`!=`(不等于) - 功能:比较两个值,返回真(1)或假(0),常用于条件判断。 逻辑运算符 -`&&`(逻辑与)、`||`(逻辑或)、`!`(逻辑非) - 功能:用于组合多个条件,返回布尔结果。逻辑与、或具有短路特性。 二进制运算(位运算符) - `&`(按位与)、`|`(按位或)、`^`(按位异或)、`~`(按位取反)、`<<`(左移)、`>>`(右移) - 功能:直接操作数据的二进制位,在控制 I/O 口、状态寄存器时极为常用。 赋值运算符 - `=`(直接赋值)、`+=`、`-=`、`*=`、`/=`、`%=`、`&=`、`|=`、`^=`、`<<=`、`>>=` - 功能:将右侧表达式的值赋给左侧变量,复合赋值运算符可简化书写。 自增自减运算符 - `++`(自增1)、`--`(自减1) - 功能:分为前缀(`++i`)和后缀(`i++`)形式,前缀先变化后参与运算,后缀则相反。 条件运算符 - `? :`(三元运算符),格式:`表达式1 ? 表达式2 : 表达式3` - 功能:若表达式1为真,则返回表达式2的值,否则返回表达式3的值。 逗号运算符 - `,`(逗号) - 功能:从左到右依次计算各表达式,整个逗号表达式的值为最后一个表达式的值。 sizeof 运算符 -`sizeof(类型或表达式)` - 功能:返回对象或类型所占的字节数(编译时计算)。 指针运算符 - `*`(取内容)、`&`(取地址) - 功能:通过指针间接访问变量。C51 中指针可以指向不同存储区(如 data, xdata),需要留意存储类型。 C51 特有的位运算 - 使用 `bit` 类型定义位变量,`sbit` 定义可独立寻址的位(如引脚或寄存器中的某一位)。 - 位变量可直接参与逻辑运算,如 `bit f = a && b;`或 `sbit LED = P1^0; LED =1;`。 要求: - 熟记各种数据类型支持的运算。 - 能够根据变量用途正确使用运算来完成数据处理。
五、各种类型语句学习目标:标准C的所有控制语句均适用,同时掌握C51的若干特殊语句形式。 知识点: 1. 标准控制语句 - 选择:`if ... else`,`switch ... case` - 循环:`while`,`do ... while`,`for` - 跳转:`break`,`continue`,`return`,`goto`
2. C51扩展语句/关键字 - `interrupt` – 在函数定义中声明为中断服务函数 - `using` – 指定中断服务函数使用的工作寄存器组 - `reentrant` – 声明可重入函数(允许递归或被多任务调用) - `_at_` – 绝对地址变量定位(如 `unsigned char xdata var_at_ 0x1000;`) 3. 预处理语句 - 与标准C相同:`#include`,`#define`,`#ifdef`,`#pragma` 等。 要求: - 能正确使用标准选择、循环结构设计程序流程。 - 了解中断函数和重入函数的声明语法。
六、函数定义与调用学习目标:掌握C51函数结构、参数传递方式以及中断服务函数的特殊写法。 知识点: 1. 普通函数定义 - 格式:`[存储类型] 返回值类型 函数名([参数列表]) [重入声明] { 函数体 }` - 示例: unsigned char add(unsigned char a, unsigned char b){ return a + b; } ``` 2. 函数参数与返回值 - 参数通过寄存器(R7及工作寄存器组)传递,最多3个参数用寄存器,其余用固定存储区。 - 返回值(若长度≤4B)存放于R7/R6/R5/R4。 - 原则上避免使用带大量参数的函数,以减少代码量和调用开销。 3. 中断服务函数 - 格式:`void 函数名(void) interrupt 中断号 [using 寄存器组号] { ... }` - 中断号: - 示例:
void timer0_isr(void) interrupt 1 using 1{ TH0 = 0xDC; // 重装初值 } ``` 4. 可重入函数 - 格式:`返回值 函数名(参数列表) reentrant { ... }` - 需在项目配置中占用一块模拟堆栈区(非必需时不使用,因为开销大)。 5. 函数调用规范 - 支持函数嵌套调用,不支持递归(除非声明为 `reentrant`)。 - 中断函数不可被普通函数直接调用,但普通函数可被中断函数调用。
要求: - 能编写无参、有参、有返回值的基本函数。 - 会编写及配置一个中断服务函数(包含中断号和寄存器组选择)。 - 知道递归在C51中的限制及解决办法(使用reentrant)。
七、库函数学习目标:熟悉Keil C51自带的常用库函数,能正确包含头文件并调用。 知识点: 1. 标准输入输出库 `<stdio.h>`* - 需自行实现底层字符输出函数(如 `putchar`),常用于串口打印调试。 - 常用函数:`printf`,`scanf`,`puts`,`gets` 等(受限于硬件资源,建议慎用)。 2. 数学库 `<math.h>` - 浮点运算函数:`sin`,`cos`,`sqrt`,`pow`,`abs` 等。 - 注意:浮点运算会生成较大代码量,资源紧张的芯片避免使用。 3. 字符串与内存操作 `<string.h>` - `strcpy`,`strlen`,`memcpy`,`memset`(与标准C相同)。 - 可直接操作xdata/code区的字符串。 4. 绝对地址访问库 `<absacc.h>`** - 提供 `CBYTE`(code区字节)、`DBYTE`(data区)、`XBYTE`(xdata区)等宏,用于直接读写指定地址。 - 示例:`XBYTE[0x2000] = 0x55;` 5. 内嵌函数和 intrinsics 库 `<intrins.h>` - 循环移位:`_crol_`,`_cror_`(字节循环左移/右移)。 - 空操作:`_nop_()`(对应单周期NOP指令)。 - 特殊指令:`_push_`,`_pop_`(很少直接使用)。 要求: - 记住常用库函数所属头文件及基本功能。 - 能够利用 `_nop_()` 产生精确延时,利用 `XBYTE` 访问外部设备。 - 注意库函数对ROM和RAM的消耗,谨慎用于资源限制型项目。
八、学习者应具备的知识与能力总结1. 先修基础 - 标准C语法:数据类型、运算符、表达式、流程控制、数组、指针、函数、结构体。 - 8051硬件基本概念:ROM/RAM映射、SFR地址、中断向量表、寄存器组。 2. C51核心技能 - 使用 `sfr` / `sbit` 定义或访问硬件寄存器。 - 为变量选择正确的存储类型(`code`,`data`,`xdata` 等),理解速度与空间的权衡。 - 编写普通函数与中断服务函数,掌握 `interrupt` 和 `using` 的用法。 - 调用标准库函数(尤其字符串操作、绝对地址访问、内嵌NOP和循环移位)。 - 阅读并修改由Keil生成的启动文件(STARTUP.A51)以配置堆栈和内存模式。 掌握以上内容后,学习者应能独立阅读并编写规范的C51工程代码,为后续开发实际单片机应用打下坚实基础。 3. C51学习重点与常见误区 - 误区1:认为标准C的 `int` 是32位 —— 实际为16位,注意溢出。 - 误区2:在中断函数中调用普通函数(若普通函数不可重入且被主循环调用,将导致数据错乱)。 - 误区3:错误选择寄存器组,导致中断现场被破坏。 - 重点:资源有限,优先使用无符号整数、尽量缩短函数调用栈、大数组置于xdata。
|