gpt4 book ai didi

AVR-GCC 中 PROGMEM 中干净整洁的字符串表

转载 作者:太空狗 更新时间:2023-10-29 15:40:55 25 4
gpt4 key购买 nike

我正在寻找一种方法来在 PROGMEM 中为 AVR 项目清晰地定义字符串数组。我有一个需要命令字符串列表的命令行处理器。

在 AVR 架构上执行此操作的传统方法是分别定义每个字符串,然后是指向这些字符串的指针数组。这是非常冗长和丑陋的:

typedef struct 
{
PGM_P str; // pointer to command string
uint8_t str_len; // length of command string
uint8_t id; // CLI_COM_* ID number
} CLI_COMMAND_t;

const char CLI_STR_TEMP[] PROGMEM = "TEMP";
const char CLI_STR_POWER[] PROGMEM = "POWER";
...

const CLI_COMMAND_t cli_cmd_table[] = { { CLI_STR_TEMP, sizeof(CLI_STR_TEMP), CLI_COM_TEMP },
{ CLI_STR_POWER, sizeof(CLI_STR_POWER), CLI_COM_POWER },
...
};

(CLI_COM_* 是枚举索引,但可以用函数指针或其他东西代替)

可以使用宏定义字符串和构建表格来减少这种困惑,例如:

#define FLASH_STRING(NAME...)    const char CLI_STR_ ## NAME [] PORGMEM = #NAME;
#define FSTR(NAME...) { CLI_STR_ ## NAME, sizeof(CLI_STR_ ## NAME), CLI_COM_ ## NAME) }

FLASH_STRING(TEMP);
FLASH_STRING(POWER);

CLI_COMMAND_t cli_cmd_table[] = { FSTR(TEMP), FSTR(POWER) };

(未经测试,顺便说一句,但应该没问题)

但是,我只想定义所有字符串一次,并让宏生成单个字符串和指针/大小/枚举引用数组。

在 Arduino 平台上有一个 FLASH_STRING_ARRAY 宏,我不太明白,但似乎也无法编译。你可以在这里看到它:http://pastebin.com/pMiV5CMr也许它只是 C++ 之类的。而且它似乎只能在函数内部使用,不能全局使用。

AVR 上的字符串表长期以来一直是一种痛苦和不优雅。除了编写一个小程序来生成必要的代码之外,如果有一种方法可以用宏来定义它,那就太好了。

奖励点:使用相同的宏生成 CLI_COM_* 常量,作为枚举或使用#defines。

编辑:我想它的另一个名称是通过宏进行迭代声明。

解决方案:感谢 luser,我想出了这个解决方案:

typedef struct 
{
PGM_P str; // pointer to command string
uint8_t str_len; // length of command string
uint8_t id; // CLI_COM_* ID number
} CLI_COMMAND_LUT_t;



#define COMMAND_TABLE \
ENTRY(testA) \
ENTRY(testB) \
ENTRY(testC)

enum {
#define ENTRY(a) CLI_COM_ ## a,
COMMAND_TABLE
#undef ENTRY
};


#define ENTRY(a) const char CLI_STR_ ## a PROGMEM = #a;
COMMAND_TABLE
#undef ENTRY


CLI_COMMAND_LUT_t command_lut[] PROGMEM = {
#define ENTRY(a) {CLI_STR_ ## a, sizeof(CLI_STR_ ## a), CLI_COM_ ## a},
COMMAND_TABLE
#undef ENTRY
};

预处理器产生以下输出:

typedef struct
{
PGM_P str;
uint8_t str_len;
uint8_t id;
} CLI_COMMAND_LUT_t;

enum {
CLI_COM_testA, CLI_COM_testB, CLI_COM_testC,
};

const char CLI_STR_testA PROGMEM = "testA"; const char CLI_STR_testB PROGMEM = "testB"; const char CLI_STR_testC PROGMEM = "testC";

CLI_COMMAND_LUT_t command_lut[] PROGMEM = {

{CLI_STR_testA, sizeof(CLI_STR_testA), CLI_COM_testA}, {CLI_STR_testB, sizeof(CLI_STR_testB), CLI_COM_testB}, {CLI_STR_testC, sizeof(CLI_STR_testC), CLI_COM_testC},

};

所以所有这些都可以包含在一个区域中,我最终得到的只是每个命令的一个简单且最重要的单一定义,该定义既用作其字符串名称又用作代码的引用。

非常感谢你们,非常感谢!

最佳答案

X-Macros 可能会有所帮助。

字符串.x:

X(TEMP, "Temp")
X(POWER, "Power")

用法:

// String concatenation macros
#define CONCAT(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b

// Generate string variables
#define X(a, b) const char CONCAT(CLI_STR_, a) [] PROGMEM = b;
#include "strings.x"
#undef X

// Generate enum constants
#define X(a, b) CONCAT(CLI_COM_, a),
enum {
#include "strings.x"
};
#undef X

// Generate table
#define X(a, b) { CONCAT(CLI_STR_, a), sizeof(CONCAT(CLI_STR_, a)), CONCAT(CLI_COM_, a) },
const CLI_COMMAND_t cli_cmd_table[] = {
#include "strings.x"
};
#undef X

这是未经测试的。

关于AVR-GCC 中 PROGMEM 中干净整洁的字符串表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19047730/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com