医疗电子技术网|技术阅读
登录|注册

您现在的位置是:医疗电子技术网 > 技术阅读 > 【MCU】一种单片机节省内存的方法

【MCU】一种单片机节省内存的方法


    今天主要跟大家分享一个MCU省内存的办法,同时也欢迎大家在文末问答留言讨论。


本文补充省内存办法


1

const的使用    关于const的用法应该是老生常谈的知识点了,如果还有不是特别清楚的小伙伴可以参考<>一文,bug菌就不重复造轮子了,直接以stm32单片机为例看看const变量的的存储方式。参考demo: 1#include "led.h"
2#include "delay.h"
3#include "usart.h"
4
5#define DEV_NUM_MAX   (3)
6#define DEV_PARAM_MAX (2)
7
8typedef struct _tag_DevParam
9{
10    char* Name;                     //设备名称
11    uint32_t Param[DEV_PARAM_MAX];  //设备参数
12}sDevParam;
13
14
15 const sDevParam stDevParam[DEV_NUM_MAX] = {
16                                {"Uart1",57600,0},
17                                {"Uart2",57600,1},
18                                {"CAN",1000000,0},
19                                };
20/***************************************
21 * Fuction:const内存分配测试
22 * Author :bug菌                                
23 **************************************/

24 int main(void)
25 {
26    uint8_t t = 0;
27    uint8_t devCnt = 0;
28
29    delay_init();            //延时函数初始化    
30    uart_init(115200);   //串口初始化
31
32    printf("\n*******************const Test*******************\r\n");
33
34    for(devCnt = 0 ;devCnt < DEV_NUM_MAX;devCnt++)
35    {
36        printf("DevName = %s,Param1 = %d,Param2 = %d\r\n",stDevParam[devCnt].Name,\
37                                                      stDevParam[devCnt].Param[0],\
38                                                      stDevParam[devCnt].Param[1]);
39    }
40    printf("stDevParam Size : %d \r\n",sizeof(stDevParam));
41    printf("stDevParam Addr : 0x%X \r\n",stDevParam);
42    printf("\n***********欢迎关注公众号:最后一个bug************\n");
43    while(1)
44    {
45        delay_ms(10); 
46        if(++t > 150){LED0=0;}else{LED0=1;}
47    }    
48 }
运行结果:

分析一下:
  • 对于stm32的所有存储映像都在对应工程所编译生成的.map文件中,对.map文件(其文件在工程目录中)的熟悉度就在一定程度上彰显你对stm32单片机的熟练程度。

  • 程序编译成功以后,就可以直接在map文件中查找const修饰的数组名,从而得到如下结果:


  • 从上图我们了解到其stDevParam变量位置0x080016b8数据区且位于(.contdata段--只读数据段)并占用了36个字节,与我们串口输出结果是相符合的。


2

const数据的存储    通过上面的测试程序显示了const数据的存储位置,那么我们看一下该位置位于stm32的哪块存储区域,是RAM还是FLASH?    因为我们节省内存主要就是通过占用更小的RAM来实现相同的项目需求,那么对于MCU而言最好就是的借助Flash,通过时间来置换空间,拿出对应的数据手册看看这些存储范围是如何分配的。

上图来源于ST手册Memory Mapping
    很明显前一节测试的const stDevParam变量位置0x080016b8处,正好处于FLASH存储位置,所以其并没有占用RAM资源。

3

const数据使用    很多写单片机程序的小伙伴都喜欢把一些只读的变量用全局变量来保存,然而这些变量基本上只保存一些参数,这对于单片机的RAM资源是非常浪费的。    bug菌曾经接手过一个前同事项目,怎么说呢?可能这个项目他也是接手别人的,该项目MCU还外部扩展了一个16M的SDRAM,大家都觉得反正RAM大,变量随便定,也不去管数据范围,动不动就float,double,真的是牛。    直到bug菌接手内存占用率已高达95%,后面稍微添加一些需求感觉RAM就要爆掉了,没办法这样下去终究会出问题,于是申请了代码重构,通过优化代码结构、设计等RAM占用率直接降到了50%左右,可以想象一下之前的开发人员是多么的任性。    所以一句话说得好"前人栽树,后人乘凉;前人挖坑,后人入fen"。前面我们分析了stm32的const数据位于Flash上,一般Flash都会比RAM打上好几倍:(如下图所示:)

上图来源于ST官网

    这样对于一些预先设置好的参数等等都可以整理以后统一放到类似于前面demo中这样的结构体数组中,从而可以大大减少对RAM的占用。    注意一点的是 : 访问RAM一般来说会比访问Flash要快一些,然而大部分项目对于这样的差异影响非常之小,后面bug菌会为大家再带来一篇文章讲讲这块的知识。    

小结


    那单片机使用const节省内存先为大家讲到这里,如果大家还有什么好的方法欢迎在文末的分享留言

推荐阅读: