I have tried comparing multiple legacy projects, and without exception, the 3.0.0 version always consumes more Flash space than the 2.X.X versions.
All configurations, microcontroller options, and third-party libraries have been kept identical.
For example, in this project, the Flash footprint after compilation is completely different.
#include <U8g2lib.h>
#include <SPI.h>
U8G2_ST7567_OS12864_F_4W_HW_SPI u8g2(U8G2_MIRROR, /*cs=*/PA4, /* dc=*/PA6);
byte ceshi = 0, showupdate = 1, SWJIAan = 0, SWJIANan = 0, fengshanciji = 2, fengshanshanye = 5;
short fanspeedt = 0, IRfanspeedt = 0, fanspeed = 0, IRfanspeed = 0, AVGdianliu = 0, zuidafanspeed = 0, zuidaIRfanspeed = 0, caiyangcishu = 1, qidongdianliu = 0;
long long AREFINT_CAL;
unsigned long currentMillis = 0, lastSWJIAtime = 0, lastSWJIANtime = 0, SWJIAfalltime = 0, SWJIANfalltime = 0, SWJIArisetime = 0, SWJIANrisetime = 0, lastjisutime = 0, fengshanjisutime = 0, zuidafanIRspeedtime = 0, dianliu = 0;
void setup() {
analogReadResolution(12); //设置ADC为12位采样
Serial.begin(115200);
delay(100);
Serial.println("风扇测速器启动中……");
pinMode(PA11, INPUT_PULLUP); //按钮SW-
pinMode(PA12, INPUT_PULLUP); //按钮SW+
pinMode(PA0, INPUT_ANALOG); //PA0读取电流
pinMode(PA1, INPUT_PULLUP); //风扇测试信号线
pinMode(PB0, INPUT_PULLUP); //红外测速信号
pinMode(PB9, OUTPUT); //风扇电源控制
attachInterrupt(PA11, SWJIA, CHANGE); //按钮SW-
attachInterrupt(PA12, SWJIAN, CHANGE); //按钮SW+
attachInterrupt(PA1, fanspeedtest, FALLING); //风扇测试信号线、下降沿触发方式
attachInterrupt(PB0, IRtestF, FALLING); //红外测速信号、下降沿触发方式
SPI.setSCLK(PA5);
SPI.setMOSI(PA7);
SPI.setMISO(PB4); //STM32G030的硬件SPI有bug,MISO即使没有用也不能用于其他功能。默认MISO PA6如被用作其他作用要在U8g2初始化之前把MISO改为暂时不用的PB4(SPI1的MISO可以使PA6、PA11、PB4)
u8g2.setBusClock(32000000); //SPI默认速度是4M,G0系列全系最高到32M。
u8g2.begin();
u8g2.sendF("c", 0x21); //屏幕开启升压,并设置升压目标。
u8g2.setContrast(255); //设置LCD屏幕对比度,3.1寸屏幕150时最清晰,1.8寸1最清楚,2.4寸45?最清楚,1.2寸建议设为20,9毛钱的1.8寸(不是M2)建议为0x24+70或者5,9毛钱的1.8寸(M2)建议为0x24+40,1.7黑色反显屏23/110,22/160/,21/255是比较合适的参数设置。
u8g2.setFlipMode(1); //设置LCD屏幕显示旋转180度
u8g2.setPowerSave(0);
u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
u8g2.setFontDirection(0);
u8g2.setFont(u8g2_font_6x13_tr);
u8g2.clearBuffer();
u8g2.drawUTF8(0, 26, " FanSpeed test");
u8g2.drawUTF8(0, 40, " S1.2");
u8g2.drawUTF8(60, 54, "2026.08.11");
u8g2.sendBuffer();
u8g2.clearBuffer();
delay(2000);
AREFINT_CAL = *(__IO uint16_t*)(0X1FFF75AA); //基准电压出厂校准值,校准温度30±5℃,电压3.0V±10mV,STM32G030系列通用地址,其他系列需要更换对应地址。
}
void loop() {
currentMillis = millis();
//SW+,短按增加风扇叶片,长按开始测试风扇转速。
if (currentMillis - SWJIArisetime > 50 && SWJIArisetime != 0) { //按钮弹起之后超过50毫秒无动作(50毫秒内的任何再次动作都判断为按键抖动)判断为一次短按键成立,并清空按钮弹起时间
SWJIAan++;
SWJIArisetime = 0;
} else if (currentMillis - SWJIAfalltime > 200 && SWJIAfalltime != 0) { //按钮按下200毫秒后判断单击、双击、长按,并清空按下时间
if (SWJIAan && SWJIAan < 10) { //单击
SWJIAfalltime = 0;
SWJIAan = 0;
if (fengshanshanye < 50) {
fengshanshanye++;
showupdate = 1;
}
} else if (SWJIAan > 9) { //点击超过9次判断为错误,清除
SWJIAfalltime = 0;
SWJIAan = 0;
//Serial.println("多击");
} else if (currentMillis - SWJIAfalltime > 2000) { //按钮初次按下后超过2000毫秒没有松开按钮判断为长按成立,清空首次按下时间并执行长按功能程序。
SWJIAfalltime = 0;
SWJIAan = 10;
//Serial.println("长按");
fanspeedt = 0;
IRfanspeedt = 0;
fanspeed = 0;
IRfanspeed = 0;
dianliu = 0;
zuidafanspeed = 0;
zuidaIRfanspeed = 0;
AVGdianliu = 0;
qidongdianliu = 0;
caiyangcishu = 1;
showupdate = 1;
ceshi = 1;
digitalWrite(PB9, 1); //开启风扇电源
fengshanjisutime = millis();
lastjisutime = millis();
zuidafanIRspeedtime = millis();
}
}
//SW-,短按减少风扇叶片,长按清空测试数据。
if (currentMillis - SWJIANrisetime > 50 && SWJIANrisetime != 0) { //按钮弹起之后超过50毫秒无动作(50毫秒内的任何再次动作都判断为按键抖动)判断为一次短按键成立,并清空按钮弹起时间
SWJIANan++;
SWJIANrisetime = 0;
} else if (currentMillis - SWJIANfalltime > 200 && SWJIANfalltime != 0) { //按钮按下200毫秒后判断单击、双击、长按,并清空按下时间
if (SWJIANan && SWJIANan < 10) { //单击
SWJIANfalltime = 0;
SWJIANan = 0;
if (fengshanshanye > 2) {
fengshanshanye--;
showupdate = 1;
} else if (fengshanshanye == 2) {
fengshanshanye = 0;
showupdate = 1;
}
} else if (SWJIANan > 9) { //点击超过9次判断为错误,清除
SWJIANfalltime = 0;
SWJIANan = 0;
//Serial.println("多击");
} else if (currentMillis - SWJIANfalltime > 2000) { //按钮初次按下后超过2000毫秒没有松开按钮判断为长按成立,清空首次按下时间并执行长按功能程序。
SWJIANfalltime = 0;
SWJIANan = 10;
//Serial.println("长按");
fengshanciji = 2;
fengshanshanye = 5;
fanspeedt = 0;
IRfanspeedt = 0;
fanspeed = 0;
IRfanspeed = 0;
dianliu = 0;
zuidafanspeed = 0;
zuidaIRfanspeed = 0;
AVGdianliu = 0;
qidongdianliu = 0;
zuidafanIRspeedtime = 0;
caiyangcishu = 1;
showupdate = 1;
}
}
if (ceshi) {
currentMillis = millis();
if (currentMillis - lastjisutime > 999) {
fanspeed = fanspeedt;
if (fengshanshanye) {
IRfanspeed = IRfanspeedt;
} else { //透明扇叶风扇专用
IRfanspeed = fanspeed;
}
fanspeedt = 0;
IRfanspeedt = 0;
lastjisutime = millis();
if (fanspeed > zuidafanspeed) {
zuidafanspeed = fanspeed;
}
if (IRfanspeed > zuidaIRfanspeed) {
zuidaIRfanspeed = IRfanspeed;
zuidafanIRspeedtime = millis();
}
if (fengshanshanye) {
fengshanciji = fanspeed / (IRfanspeed / fengshanshanye);
}
}
if (currentMillis - fengshanjisutime > 10000) {
dianliu += analogRead(PA0);
caiyangcishu++;
AVGdianliu = dianliu / caiyangcishu;
delay(10);
} else {
zuidafanIRspeedtime = millis();
dianliu = analogRead(PA0);
if (dianliu > qidongdianliu) {
qidongdianliu = dianliu;
}
}
currentMillis = millis();
if (currentMillis - zuidafanIRspeedtime > 8000) {
digitalWrite(PB9, 0); //关闭风扇电源
ceshi = 0;
}
showupdate = 1;
}
if (showupdate) {
ALLshowupdate();
showupdate = 0;
}
}
void ALLshowupdate() {
String LCDshowinfo;
long lingshidianliu;
if (ceshi) {
LCDshowinfo = "Testing";
} else {
LCDshowinfo = "STOP";
}
long long Aneibujizhun = analogRead(AVREF); //读取内部电压基准当前读数
u8g2.drawUTF8(0, 10, LCDshowinfo.c_str()); //测试状态
if(fengshanshanye){
LCDshowinfo += 60 * IRfanspeed / fengshanshanye;
}else{
LCDshowinfo += 60 * IRfanspeed / fengshanciji;
}
LCDshowinfo += "RPM";
u8g2.drawUTF8(63, 10, LCDshowinfo.c_str()); //实时转速
if (currentMillis - fengshanjisutime > 10000) {
lingshidianliu = 4000 * AREFINT_CAL * AVGdianliu / (12831 * Aneibujizhun); //4个0.47欧电阻并联,INA180A1放大20倍,3.0V最大测量电流1.25A,3.3V时1.375A
} else {
lingshidianliu = 4000 * AREFINT_CAL * dianliu / (12831 * Aneibujizhun); //4个0.47欧电阻并联,INA180A1放大20倍,3.0V最大测量电流1.25A,3.3V时1.375A;
}
LCDshowinfo += lingshidianliu / 1000;
LCDshowinfo += ".";
lingshidianliu = lingshidianliu % 1000;
if (lingshidianliu < 100) {
if (lingshidianliu < 10) {
LCDshowinfo += "00";
} else {
LCDshowinfo += "0";
}
}
LCDshowinfo += lingshidianliu;
LCDshowinfo += "A ";
u8g2.drawUTF8(0, 23, LCDshowinfo.c_str()); //当前电流
lingshidianliu = 12 * lingshidianliu;
LCDshowinfo += lingshidianliu / 1000;
LCDshowinfo += ".";
lingshidianliu = lingshidianliu % 1000;
if (lingshidianliu < 100) {
if (lingshidianliu < 10) {
LCDshowinfo += "00";
} else {
LCDshowinfo += "0";
}
}
LCDshowinfo += lingshidianliu;
LCDshowinfo += "W";
u8g2.drawUTF8(63, 23, LCDshowinfo.c_str()); //当前功率
LCDshowinfo = "MAX: ";
u8g2.drawUTF8(0, 36, LCDshowinfo.c_str()); //最大转速
LCDshowinfo += 60 * zuidaIRfanspeed / fengshanshanye; //最大转速
LCDshowinfo += "RPM ";
u8g2.drawUTF8(63, 36, LCDshowinfo.c_str()); //最大转速
LCDshowinfo = "AVG:";
lingshidianliu = 4000 * AREFINT_CAL * AVGdianliu / (12831 * Aneibujizhun); //4个0.47欧电阻并联,INA180A1放大20倍,3.0V最大测量电流1.25A,3.3V时1.375A
LCDshowinfo += lingshidianliu / 1000;
LCDshowinfo += ".";
lingshidianliu = lingshidianliu % 1000;
if (lingshidianliu < 100) {
if (lingshidianliu < 10) {
LCDshowinfo += "00";
} else {
LCDshowinfo += "0";
}
}
LCDshowinfo += lingshidianliu;
LCDshowinfo += "A";
u8g2.drawUTF8(0, 49, LCDshowinfo.c_str()); //最大电流
LCDshowinfo = "MAX:";
lingshidianliu = 4000 * AREFINT_CAL * qidongdianliu / (12831 * Aneibujizhun); //4个0.47欧电阻并联,INA180A1放大20倍,3.0V最大测量电流1.25A,3.3V时1.375A
LCDshowinfo += lingshidianliu / 1000;
LCDshowinfo += ".";
lingshidianliu = lingshidianliu % 1000;
if (lingshidianliu < 100) {
if (lingshidianliu < 10) {
LCDshowinfo += "00";
} else {
LCDshowinfo += "0";
}
}
LCDshowinfo += lingshidianliu;
LCDshowinfo += "A ";
u8g2.drawUTF8(63, 49, LCDshowinfo.c_str()); //启动电流
LCDshowinfo = "SN:";
LCDshowinfo += fengshanciji;
u8g2.drawUTF8(0, 62, LCDshowinfo.c_str()); //磁极
LCDshowinfo = "IR:";
LCDshowinfo += fengshanshanye;
u8g2.drawUTF8(63, 62, LCDshowinfo.c_str()); //扇叶数量
u8g2.sendBuffer();
u8g2.clearBuffer();
}
void SWJIA() { //PA11,按钮SW-
currentMillis = millis();
if (currentMillis - lastSWJIAtime > 100) {
if (SWJIAan == 10) {
lastSWJIAtime = millis();
SWJIAan = 0;
} else if (digitalRead(PA11)) { //按钮松开(RISING)时记录此按钮弹起时间,并更新背光灯亮起时间;
if (SWJIAfalltime != 0) {
SWJIArisetime = millis();
}
} else { //按钮按下(FALLING)时记录记录首次按下时间(按下时间不为0时不更新)并清空按钮弹起时间,按下时背光灯亮起并记录背光灯亮起时间
if (SWJIAfalltime == 0) { //如果按下时间为0则记录按下的时间
SWJIAfalltime = millis();
}
SWJIArisetime = 0; //清空按钮弹起时间
}
}
}
void SWJIAN() { //PA12,按钮SW-
currentMillis = millis();
if (currentMillis - lastSWJIANtime > 100) {
if (SWJIANan == 10) {
lastSWJIANtime = millis();
SWJIANan = 0;
} else if (digitalRead(PA12)) { //按钮松开(RISING)时记录此按钮弹起时间,并更新背光灯亮起时间;
if (SWJIANfalltime != 0) {
SWJIANrisetime = millis();
}
} else { //按钮按下(FALLING)时记录记录首次按下时间(按下时间不为0时不更新)并清空按钮弹起时间,按下时背光灯亮起并记录背光灯亮起时间
if (SWJIANfalltime == 0) { //如果按下时间为0则记录按下的时间
SWJIANfalltime = millis();
}
SWJIANrisetime = 0; //清空按钮弹起时间
}
}
}
void fanspeedtest() { //PA1,风扇转速检测。
fanspeedt++;
}
void IRtestF() { //PB0,红外转速检测。
IRfanspeedt++;
}
I have tried comparing multiple legacy projects, and without exception, the 3.0.0 version always consumes more Flash space than the 2.X.X versions.
All configurations, microcontroller options, and third-party libraries have been kept identical.
Win11 25H2
Arduino 2.3.10
U8G2 2.36.19
Debug symbols and core logs:"None"
Optimize:"Smallest (-OS) with LTO"
Board part number:"Generic G030F6Px"
U(S)ART support:"Enabled (generic ‘Serial’)"
"Optimize for debug" is not checked.
For example, in this project, the Flash footprint after compilation is completely different.
STM32 CORE 2.6.0
Sketch uses 31588 bytes (96%) of program storage space. Maximum is 32768 bytes.
Global variables use 3132 bytes (38%) of dynamic memory, leaving 5060 bytes for local variables. Maximum is 8192 bytes.
STM32 CORE 2.11.0
Sketch uses 31620 bytes (96%) of program storage space. Maximum is 32768 bytes.
Global variables use 3084 bytes (37%) of dynamic memory, leaving 5108 bytes for local variables. Maximum is 8192 bytes.
STM32 CORE 2.12.0
Sketch uses 31780 bytes (96%) of program storage space. Maximum is 32768 bytes.
Global variables use 3084 bytes (37%) of dynamic memory, leaving 5108 bytes for local variables. Maximum is 8192 bytes.
STM32 CORE 3.0.0
region `FLASH' overflowed by 3884 bytes