单片机的内存和寄存器是什么?代码中的变量和内存之间有什么关系?

基础概念

单片机有寄存器和内存。

内存就是RAM、ROM/FLASH,这里的内存的概念和电脑的不太一样,不要搞混,眼着于单片机即可。

ROM/FLASH:程序存储区(只读存储器),不变的东西都存这俩里头,并且存里头的东西只读。
RAM:随机存储器,可以简单理解为变量都存这里。

暂且写这样理解,初始化后会有变化,后文会说。

单片机都有自带ROM/FLASH、RAM,但是很多厂商也会给他们外扩一些,即片外RAM、片外FLASH、ROM。

内存和寄存器之间的关系?

寄存器和内存都可以存东西,但是我们的代码的所有数据一般都存在内存中,除非你用一些命令将命令其将东西存入寄存器,例如register之类的命令(我自己也没用过,不足之处请指正,感谢!)。那么cpu要使用内存中的东西的时候,是直接去内存中拿吗?不,如果cpu要用内存的东西,cpu会先向寄存器要,然后寄存器帮cpu去内存中找到要的东西,然后内存将东西取到。
为什么要这样做呢?因为寄存器存取速度快,它就像一个热于帮助他人的人,你们动作太慢了,我来帮你们跑腿,这样就快了。

另外突然想起最近看到的const和code关键字的区别,记录一下(可跳过)。

在Keil 51中,code修饰的变量放在ROM(Flash)中,而const修饰的变量为只读(不可修改),放在RAM中,我想这也就是为什么说const修饰后的变量明明不可变,我们却还认为他是变量,因为他在RAM中,只是不可变罢了!可以用“code const”修饰变量,表示变量存储在ROM中,且为只读,由此看来“code”与“code const”修饰变量有一样的功用。

Keil MDK中的const与code

在Keil MDK中,如进行STM32的开发,code修饰符无法使用,使用的话会报错。那么要怎么来修饰存放在ROM中的变量?此时是用到const,用const修饰的变量是存放在ROM中的。

总结,注意不同编译器对于const与code的规定。code一般用于51中,而const应用则非常广泛,注意其在不同的编译环境中表现的数据存储位置。

关于程序代码和内存之间的关系,内存如何合理使用?

以下内容转自:https://www.cnblogs.com/AmilyandFamily/p/10288544.html

单片机内存的合理使用对于一名嵌入式软件工程师来说是至关重要的,这深深关系到项目代码的稳定性。

初始化前:

初始化后:

什么是初始化呢?就是startup,程序运行前,系统会进行初始化和代码优化。

嗯...可以看到,初始化时RW-data从flash拷贝到RAM,所以在程序跑起来了Rw-data是在RAM里面的。

其中:Code为程序代码部分
RO-data 表示 程序定义的常量const temp;
RW-data 表示 已初始化的全局变量
ZI-data 表示 未初始化的全局变量

(以上这一段是copy的,原地址在:http://anlx27.iteye.com/blog/1575848)

而栈区(stack)、堆区(heap)、全局区(静态区)(static)、文字常量区和程序代码区和上面所介绍的code、RO-data等的关系。

1、栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 这些值是可读写的,那么stack应该被包含在RW-data(读写数据存储区),也就是单片机的sram中。

2、堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。可以理解,这些也是被包含在单片机的sram中的。

3、全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放。这些数据也是可读可写的,和stack、heap一样,被包含在sram中。

4、文字常量区:常量字符串就是放在这里的。这些数据是只读的,分配在RO-data(只读数据存储区),则被包含在flash中。

5、程序代码区:存放函数体的二进制代码,可以想象也是被包含在flash,因为对于MCU来说,当其重新上电,代码还会继续运行,并不会消失,所以存储在flash中。

(然而上这一段还是copy的,原地址在:http://www.51hei.com/mcu/4293.html)

下面是网上找的例子:

int a = 0; // RW-data 全局初始化区
char *p1; // ZI-data 全局未初始化区
const int b = 0; // RO-data 只读变量区
main(void)
{
int b; // RW-data 栈区
char s[] = "abc"; // RW-data 栈区
char *p2; // RW-data 栈区
char *p3 = "123456"; // "123456/0" 在Ro-data 常量区,p3在RW-data 栈区
static int c =0; // 全局(静态)初始化区 rw-data -> static区

p1 = (char *)malloc(10);
p2 = (char *)malloc(20); // 分配得来的10和20字节的区域就在Rw-data 堆区

strcpy(p1, "123456"); // "123456/0" 放在常量区,编译器可能会将它
// 与p3所指向的"123456"优化成一个地方
}

所以,重点来了,在实际编程中,应当实时关注.map的内容来判断单片机内存的使用情况。

在keil中,右击工程就会出现opne map flie的选项,打开它,浏览到最后一段

可以看到该工程占用单片机ram12.43kb,flash13.91kb。

完美~~

(0)

相关推荐