我正在为带有#define
宏的Arduino项目创建菜单系统(受3D打印机上Marlin固件的启发),我试图对每个菜单项都使用宏#define MENU_ITEM_EDIT()
进行概括。完整的代码真的很长,因此我省略了紧凑的代码块。但是,您可以在此处找到完整的代码:https://pastebin.com/h24itG9y
void draw_row(int row, char* value) { /* Stuff here*/ } // Draws row
char* uiToStr(int x) { /* Stuff here*/ } // Converts unsigned int to a string
#define disp_array(display, value) display[value]
#define disp_func(display, value) display(value)
#define disp_char(display, value) display
#define MENU_ITEM_EDIT(min, max, rate, display, displayType, width, label, value) \
// A bunch of stuff
draw_row(rowNum, disp_ ## displayType(display, value)); \
// More stuff
使用代码宏看起来像:
// Values
const char item1[] = "Item 1", item2[] = "Item 2", item3[] = "Item 3";
const char* const itemList[] = {item1, item2, item3};
int currentItem = 0;
uint8_t item1Val = 10;
void menu1()
{
START_MENU();
MENU_ITEM_EDIT(0, 3, 1, itemList, array, 6, "Item:", currentItem);
MENU_ITEM_EDIT(0, 255, 1, uiToStr, func, 3, "Item 1 Value:", item1Val);
END_MENU();
}
显示为:
Item: Item 1
Item 1 Value: 10
为了方便我的菜单声明,我尝试使用常见的菜单类型,例如范围从0到255的uint8_t
。然后,在菜单中,我将使用__u255_t
而不是前6个参数。
#define __u255_t 0, 255, 1, uiToStr, func, 3
void menu2()
{
int item2Val = 10;
START_MENU();
MENU_ITEM_EDIT(__u255_t, "Item 2 Value", item2Val);
END_MENU();
}
以前,我已经进行了设置,以便每次我想要不同类型的菜单时,即使我只使用一次,也必须为其定义类型以及如何在宏中对其求值。这样,对于行中通常重复出现的类型,我可以使用1个参数而不是6个参数。但是,当行中包含一组唯一的参数(例如不同范围或显示字符串列表)的行时,我仍然希望能够使用6参数选项。
但是,在此示例中,该程序无法编译,因为它将__u255_t
放入了min
宏的MENU_ITEM_EDIT()
中,而不是将__u255_t
扩展为其6个值并将它们放入MENU_ITEM_EDIT()
的前6个参数中。宏的计算结果为:
MENU_ITEM_EDIT(__u255_t, "Item 2 Value", item2Val);
// Evaluates as:
MENU_ITEM_EDIT( (0, 255, 1, uiToStr, func, 3), "Item 2 Value", item2val, , , , , );
注意:我加了一些括号以使其更清晰易懂。
但是我想要
MENU_ITEM_EDIT(__u255_t, "Item 2 Value", item2Val);
// Evaluates as:
MENU_ITEM_EDIT(0, 255, 1, uiToStr, func, 3, "Item 2 Value", item2Val);
我考虑过使用struct
,但是我不确定是否可以使用,因为根据行的不同,value
中的draw_row()
字符串可以是函数或数组。有人对如何解决此问题有任何建议吗?
另外,如果需要添加更多代码以使问题更清楚,请告诉我。