Arduino的Serial.print(F(""))问题

    好久之前在编写项目产品的Arduino库代码时发现内存(SRAM)占用偏高,想了想我也没在类内定义多少成员变量啊,也没啥大的数组啥的,后来关闭DEBUG_PRINT功能后,内存占用一下子下来了,才一拍脑袋是调试打印的字符串占用了大量的SRAM,于是就探究了一下Arduino可执行文件的内存分布问题。

    和普通程序一样,Arduino的代码编译完成后也是分为code段、data段、bss段、noinit段,从最后编译输出窗口看,可以笼统的看做是代码段和数据段(包含全局变量和堆栈空间的占用),但是程序本身的大小是code段+data段,这就是占用FLASH的大小,而占用SRAM的就是data段+bss段+noinit段。


    再列出avr单片机的程序编译输出信息(与本文程序不是同一程序):

AVR Memory Usage
----------------
Device: atmega16

Program:   14362 bytes (87.7% Full)
(.text + .data + .bootloader)

Data:        635 bytes (62.0% Full)
(.data + .bss + .noinit)

    再上一张SRAM的内存分布图:




    回归主题,当我程序中的所有代码直接DEBUG_PRINTLN("")时


产生的程序文件大小是:


    当我把所有代码都写成这样:


输出的可执行文件大小:


可以得到的结论:添加 F() 相当于为字符串常量定义了PROGMEM属性,常量字符串仍然存储在FLASH中,但是程序运行时不会再将常量字符串从FLASH中copy到SRAM中,而是直接读取FLASH中的字符串,这样一来就节约了SRAM,但是代码运行速度就下降了。

    细心的童鞋会看到节约的SRAM大小并不是完全等于增加的FLASH大小,这是因为重复的字符串被FLASH只存储了一份,Arduino做的还是很人性化的,其他的类似xxduino库就没这么机智了,比如今天正在研究的WiFiduino(基于ESP8266模组做的 一个类似Arduino框架,用户可以像操作Arduino一样操作ESP8266,内含丰富的网络操作API):



猜你喜欢

转载自blog.csdn.net/fang_chuan/article/details/80029546
今日推荐