本文主要讲述51单片机RAM部分的内存映射,其内存空间如下图所示:
51单片机内部有256个字节的RAM空间,低128个字节为工作寄存器组区(0x00H-0x1FH)、位寻址区(0x02H-0x2FH)、通用RAM区(0x30H-0x70H),SFR寄存区(0x80-0xFF)这段空间定义51单片机所有的控制寄存器和状态寄存器。下面我们就以上图中自底向上的顺序逐一介绍一下各区的功能以及访问方法。
工作寄存器区
工作寄存器区为R0-R7,它们各为1个字节,但51单片机一共有4组工作寄存器,单片机在工作过程中只能有一组工作寄存器工作。各个工作寄存器的地址以及工作寄存器组的选择如下图所示:
工作寄存器的功能是传递函数参数、局部变量的赋值、保存函数运行的结果等。此外,很多指令也都会用到工作寄存器,我们可以先来想一下这样一个问题:四个数的和能否利用51单片机实现呢?一起来看看下图:
add函数接收了三个参数a、b、c而没有d,是不是不能传递参数d呢?先来看看官方文档的解释:
Cx51编译器最多在MCU寄存器中传递三个函数参数。由于不将参数写入内存或从内存读取参数,因此该机制显著提高了系统性能。参数或参数传递可以由REGPARMS和NOREGPARMS指令控制:
原来51的确最多只能传递三个参数,可是现在超过了三个该怎么办呢?是不是只能算三个数的加减呢?如下图所示,add函数传递的参数分别是1、2、3、4,我们运行的结果是A,也就是十进制的10,那么第四个参数去哪里了呢?
经过仿真我们知道第四个参数是入栈了。(看来栈是可以在工作寄存器区的,但最好不要这样做,而是应该在.S文件中让SP指向0x60之后)
注意:51单片机中的int是2个字节! 51单片机SP上电默认值是0x07,i、j、t入栈0x07+2*3=0x13,51单片机栈是正增长的,所以第四个参数的位置就是0x14与0x15所在的位置。
2、位寻址区
0x20-0x2F一共16个字节、128位,所以寻址范围是0-0x7F,内存映射关系如下图所示:
使用方法就是C51特有的关键字,sbit关键字对应的汇编指令就是BIT。(注意: SFR寄存器也可以位寻址哦!)
关键字 sbit 修饰后指向的是P2.1所在的位置。P2^1是在SFR寄存器区通过位寻址的,之所以为1是因为还没对它进行赋值,因此其默认值为1。位寻址区是非常有用的,比如对P2.1进行位操作,不会影响到P2.0、P2.2等其他一些I/O口,所以是一种非常方便的操作方式。其实STM32也可以达到这样的效果!
3、通用RAM区
通用RAM区可以运行函数的局部变量,因为SP指针是保护调用函数和中断函数现场的。具体表现为:
1.保护断点:将PC压入栈,执行完中断函数后,弹出PC之前的值,恢复到中断前程序运行的点。
2.保护现场:对寄存器组的值进行保护。
4、SFR寄存器区
特殊功能寄存器区定义了控制和监视51单片机运行的控制寄存器和状态寄存器,定时器、I/O口、串口、中断等相关寄存器都在这里定义。同时这个区域是离散的,是为生产商而留的,但52单片机是可以访问这里的,只不过需要间接寻址,对于C语言编程而言则不需要关注这个,C语言自身可以将其转化。那么,52单片机的堆栈又增长了128个字节供我们使用。
好了,让我们再来回顾总结一下以上内容吧!
全篇主要通过KEIL以及程序介绍了51单片机RAM区各模块的作用。第一方面,通用寄存器组所占据的地址空间以及程序运行时该区产生的作用。第二方面,位寻址区的重要意义与作用,若不用位寻址就只能用读-写-改的形式,这样不仅用起来不方便,而且还会增加代码量。第三方面,通用RAM区和SFR区的重要性。