You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino如何将程序空间中的指针作为参数传递给函数

Arduino PROGMEM菜单指针传参实现方案

你的Menu_Principal是存储在Flash程序空间的常量字符串指针数组,受AVR架构Flash与RAM地址空间分离的限制,传参和读取时必须匹配专用的PROGMEM操作规则,具体实现如下:

1. 修正原定义的类型匹配问题

你原代码中Menu_Principal的元素类型和前面声明的const字符串不匹配,会触发编译警告,先修正声明:

const char _str_opcion_0[] PROGMEM = "Opción Menú 1";
const char _str_opcion_1[] PROGMEM = "Opción Menú -2";
const char _str_opcion_2[] PROGMEM = "Opción Menú --3";
const char _str_opcion_3[] PROGMEM = "Opción Menú ---4";
const char _str_opcion_4[] PROGMEM = "Opción Menú ----5";
const char _str_opcion_5[] PROGMEM = "Opción Menú -----6";
const char _str_opcion_6[] PROGMEM = "Opción Menú ------7";
const char _str_opcion_7[] PROGMEM = "Opción Menú -------8";
const char _str_opcion_8[] PROGMEM = "Opción Menú --------9";
const char _str_opcion_9[] PROGMEM = "Opción Menú ---------A";
const char _str_opcion_A[] PROGMEM = "Opción Menú ----------B";
const char _str_opcion_B[] PROGMEM = "Opción Menú -----------C";

// 修正为const char*类型匹配字符串常量
const char* const Menu_Principal [] PROGMEM =
{
    _str_opcion_0, _str_opcion_1, _str_opcion_2, _str_opcion_3, _str_opcion_4, _str_opcion_5,
    _str_opcion_6, _str_opcion_7, _str_opcion_8, _str_opcion_9, _str_opcion_A, _str_opcion_B,
    NULL
};

2. 声明接收菜单参数的函数

引入avr/pgmspace.h头文件,使用官方定义的PROGMEM指针类型作为形参,读取时必须用pgm_read_*系列函数从Flash取数据,不能直接解引用:

#include <avr/pgmspace.h>

/**
 * @brief 打印/显示PROGMEM存储的菜单
 * @param menuItems 存在PROGMEM的菜单指针数组,类型为PGM_P*
 */
void showMenu(PGM_P *menuItems) {
  uint8_t itemIndex = 0;
  PGM_P currentItemStr;
  char strBuffer[64]; // 缓冲区长度根据你最长的菜单项调整

  // 遍历到NULL结束标记为止
  while ((currentItemStr = (PGM_P)pgm_read_ptr(&menuItems[itemIndex])) != NULL) {
    // 把Flash里的字符串拷贝到RAM缓冲区
    strcpy_P(strBuffer, currentItemStr);
    
    // 这里替换成你的屏幕显示逻辑,示例用串口输出
    Serial.println(strBuffer);

    itemIndex++;
  }
}

3. 调用传参

数组名会自动退化为指向首元素的指针,直接传入Menu_Principal即可,不需要额外加取地址符:

void setup() {
  Serial.begin(115200);
  // 传入菜单指针
  showMenu(Menu_Principal);
}

void loop() {
  // 其他业务逻辑
}

关键注意事项

  • 禁止直接读取PROGMEM地址的内容,比如直接写Serial.println(menuItems[itemIndex])会读取RAM区的乱码,所有Flash数据访问必须走pgm_read_*、strcpy_P这类专用函数。
  • 上述写法兼容AVR(Uno、Mega2560)和ESP32/ESP8266等非AVR架构的Arduino开发板,跨平台编译不需要修改代码。
  • 缓冲区大小要大于最长菜单项的长度,避免字符串拷贝溢出。

内容的提问来源于stack exchange,提问作者Luis Fernando Ruiz Pereira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 20:39:19