Arduino代码优化请求:消除else if并实现16到0计数显示图片
嘿,我完全懂你的烦恼——一大串else if不仅写起来麻烦,还占了超多Flash空间,用数组确实是解决这个问题的完美方案,大概率是你对Arduino里PROGMEM数组的用法没摸透,我来给你一步步捋清楚!
首先,先复盘下核心思路:把所有图片的存储地址放进一个数组里,然后根据当前的计数值直接索引对应的图片,这样既省代码空间,后期维护也方便。
第一步:整理你的图片定义
假设你原来的图片是存在PROGMEM里的(如果还没加,一定要加上,不然会占满宝贵的RAM),示例如下:
// 你的原有图片定义(补全你所有17张图:img16到img0) const unsigned char img16[] PROGMEM = { /* 16对应的图片数据 */ }; const unsigned char img15[] PROGMEM = { /* 15对应的图片数据 */ }; // ... 中间省略img14到img1的定义 const unsigned char img0[] PROGMEM = { /* 0对应的图片数据 */ };
第二步:创建图片指针数组
我们把所有图片的地址按16到0的顺序放进一个指针数组里,并且也把这个数组存在PROGMEM里(进一步节省RAM):
// 存储所有图片的指针,顺序对应count从16到0 const unsigned char* const imageArray[] PROGMEM = { img16, img15, img14, img13, img12, img11, img10, img9, img8, img7, img6, img5, img4, img3, img2, img1, img0 }; // 自动计算图片总数(不用手动数,避免出错) const int totalImages = sizeof(imageArray) / sizeof(imageArray[0]);
第三步:编写图片显示函数
根据当前的计数值,计算数组索引,然后从PROGMEM里读取图片指针,再调用你的显示逻辑:
void displayCountImage(int currentCount) { // 计算索引:currentCount从16→0,对应数组的0→16 int arrayIndex = 16 - currentCount; // 从PROGMEM读取对应的图片指针(这一步很关键,不然会读错数据) const unsigned char* targetImage = (const unsigned char*)pgm_read_word(&imageArray[arrayIndex]); // 这里替换成你实际的显示代码! // 举个例子,如果你用SSD1306 OLED屏,大概是这样: // oled.clearDisplay(); // oled.drawBitmap(0, 0, targetImage, 128, 64, WHITE); // 替换成你的屏尺寸 // oled.display(); }
第四步:主循环里的计数逻辑
最后在主循环里实现从16到0的计数,每步调用显示函数:
void loop() { static int count = 16; // static让变量保持上一次的值 // 显示当前计数对应的图片 displayCountImage(count); delay(1000); // 每步的延迟时间,按需调整 // 更新计数:到0后可以重置循环,也可以停止 if (count > 0) { count--; } else { count = 16; // 不需要循环的话,把这行删掉就行 } }
额外优化:如果图片尺寸不同
要是你的图片宽高不一样,可以用结构体数组来存储每个图片的完整信息,这样更灵活:
// 定义结构体,存图片数据、宽、高 typedef struct { const unsigned char* data; int width; int height; } ImageData; // 结构体数组,按顺序存所有图片的信息 const ImageData imageInfoArray[] PROGMEM = { {img16, 128, 64}, {img15, 128, 64}, // ... 补全所有图片的信息 {img0, 128, 64} }; // 获取图片信息的函数 ImageData getImageInfo(int currentCount) { int arrayIndex = 16 - currentCount; ImageData info; // 从PROGMEM读取结构体的每个成员 info.data = (const unsigned char*)pgm_read_word(&imageInfoArray[arrayIndex].data); info.width = pgm_read_word(&imageInfoArray[arrayIndex].width); info.height = pgm_read_word(&imageInfoArray[arrayIndex].height); return info; } // 显示函数就可以改成这样: void displayCountImage(int currentCount) { ImageData imgInfo = getImageInfo(currentCount); // 用imgInfo.data、imgInfo.width、imgInfo.height来显示 }
为什么这比else if好?
- 省空间:一堆
else if会生成大量分支判断的机器码,而数组只需要存储指针,代码量骤减; - 易维护:后期要加/删图片,只需要修改数组,不用改一堆条件判断;
- 更高效:直接索引数组比多次条件判断执行速度更快。
内容的提问来源于stack exchange,提问作者Marco Llerena Palomo
相关产品推荐
相关产品推荐

