一些c51编程技巧及原理
c51 的编译模式
- small 所有未明确说明存储区域的变量和重入堆栈默认保存在data区,总容量为128B。
- compact 所有未明确说明存储区域的变量和重入堆栈默认保存在pdata区,总容量为256B。
large 所有未明确说明存储区域的变量和重入堆栈默认保存在xdata区,总容量为64KB。
片内存储区寻址空间
- data 片内RAM的00-7FH
- idata 片内RAM的00-FFH
- bdata 片内RAM的20-2FH
- 片外存储区寻址空间
- pdata 片外RAM中的某一页(256B)
- xdata 整个片外RAM 0000H-FFFFH
栈
- 硬堆栈:由SP指针和PUSH/POP指令支持的系统堆栈,位于data区,由低向高地址生长。在编译器对全部data变量完成分配之后,紧接着安排的是硬堆栈
- 压缩栈:函数参数,局部变量;由编译器分配的固定存储位置
- 模拟栈:“可重入栈”,专门为可重入函数开辟的模拟堆栈,目的是安排可重入函数中的字节型参数和字节型局部变量
可重入
在标准C中,函数默认是可重入的,这是因为它的堆栈空间很大。51单片机的理论堆栈空间最大不超过128B/256B。在C51中,函数参数和函数中的局部变量除了一部分用寄存器来传递或分配在寄存中外,其他都是保存在编译器所分配的固定地址(压缩栈??),所以C51默认是不可重入的。可重入函数需显示声明。
同理,不可递归。
keil中函数指针
编译器无法判断函数的调用。因为ram分配采用overlay方法,若指针在中断或递归调用中会发生问题。
解决:
- 函数指针指向函数不使用内存,仅用寄存器
- 使用reentrant关键字修饰函数,并在startup.a51中初始化可重入栈
- 通知linker实际的调用关系