构建#define 指令数组

Building an Array of #define Directives

我有一些微控制器代码使用了一些头文件,其中 GPIO 引脚定义如下:

#define PA3 GPIO(GPIO_PORTA, 3)

使用 IDE,我可以导航到 GPIO 的实现,我发现:

#define GPIO(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))

其中 pin 定义为:

const uint8_t pin

port 是一个 enum 定义为:

enum gpio_port { GPIO_PORTA, GPIO_PORTB, GPIO_PORTC, GPIO_PORTD, GPIO_PORTE }

我想创建一个包含所有 GPIO 定义(PA3PA4 等)的数组,可以通过串行端口传递的整数对其进行索引。

我尝试了以下方法:

GPIO knavePinList[] = {PA3, PA4, PA21, PB4, PHY_RESET_PIN, PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9};

但这显然行不通,因为 GPIO 不是公认的 C 类型,而是一个宏。尝试构建时,我收到此错误消息:

unknown type name 'GPIO'

我什至可以声明一个宏数组吗?如果是这样,我将如何记录我正在使用的类型?

谢谢。

#define 语句执行文本替换,它们没有固有类型。如您所述,GPIO 不是有效类型,它是一个似乎计算引脚 numbers/addresses 的宏(实际上 GPIO 未定义,而 GPIO(a,b) 是宏)。

如果你想存储其中许多的数组,那么你需要知道它们的计算结果都是什么实际类型。鉴于 GPIO 宏 returns 一个 port 和一个 pin 值的总和,其中 port 是一个枚举,其基础类型是 int(从技术上讲,它是特定于实现的整数类型 - 请参阅 What is the underlying type of a c++ enum?)并且 pinuint8_t,数组值的实际类型也将是整数类型 - 具体取决于哪个类型关于您的实施和可能值的范围。

不,您不能创建这样的宏数组。

如果要根据输入执行特定的宏,则需要使用 if-elseswitch 语句。如果输入是一个整数,你可以这样做:

switch( input )
{
  case 0: PA3; break;
  case 1: PA4; break;
  case 2: PA21; break;
  ...
 }

你post的数组是完全合法的,我想你没有测试过。无论如何,最好用一个可测试的例子来问,(见How to create a Minimal, Complete, and Verifiable example)但是代码:

GPIO knavePinList[] = {PA3, PA4, PA21, PB4, PHY_RESET_PIN, PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9};

将生成一个完全合法初始化的整数数组,其中包含您从宏扩展的常量的按位值。尝试使用

cpp source.c | more

看看数组声明实际上是如何展开的。顺便说一下,您的代码中还有另一个不同的问题...您正在使用 相同的标识符 GPIO 来指示 GPIO 宏名称,和数组元素的类型,所以当宏处理器遇到它时,它看不到任何参数,这不是你 #defined 它的方式,并且抱怨没有调用的两个参数宏 GPIO完全没有参数。

您必须测试您的代码...并发送 1. 您期望的...和 ​​2. 您得到的...因为错误应该是显而易见的,如果您只是停下来阅读它。

您的问题的解决方案是将宏 GPIO 重命名为 GPIO_BITS,例如...然后更改所有定义:

#define GPIO_BITS(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))

...

#define PA3 GPIO_BITS(GPIO_PORTA, 3)

所以遇到数组定义时,类型名没有尝试展开为宏