我有一些使用某些头文件的微控制器代码,其中的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定义(PA3
,PA4
等)的数组,这些数组可以由通过串行端口传递的整数索引。
我尝试了以下操作:
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'
我什至可以声明一个宏数组吗?如果是这样,我将如何记录我正在使用的类型?
谢谢。
答案 0 :(得分:2)
#define
语句执行文本替换,它们没有固有类型。如您所述,GPIO
不是有效的类型,它是一个似乎在计算引脚号/地址的宏(实际上GPIO
是未定义的,而GPIO(a,b)
是宏)。
如果要存储其中许多数组,则需要知道它们全部求值的实际类型。假设GPIO
宏返回一个port
和一个pin
值的和,其中port
是一个枚举,其基础类型为int
(从技术上讲,它是实现特定的整数类型-请参见,而pin
是uint8_t
,数组值的实际类型也将是整数类型-具体取决于您的实现,可能值的范围。
答案 1 :(得分:1)
否,您无法创建这样的宏数组。
如果要基于输入执行特定的宏,则需要使用if-else
或switch
语句。如果输入是整数,则可以执行以下操作:
switch( input )
{
case 0: PA3; break;
case 1: PA4; break;
case 2: PA21; break;
...
}
答案 2 :(得分:1)
您发布的数组完全合法,我认为您尚未对其进行测试。无论如何,最好问一个可测试的示例(请参见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
宏名称和类型数组元素,因此当宏处理器遇到它时,它看不到任何参数,这不是您#define
对其进行的方式,并且抱怨两个参数宏GPIO
根本没有任何参数被调用
您必须测试您的代码...,然后发送1.您期望的结果...和2.您获得的结果...,因为如果您只是停下来阅读它,错误应该是显而易见的。>
您的问题的一种解决方案是将宏GPIO
重命名为GPIO_BITS
,然后更改所有定义:
#define GPIO_BITS(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))
...
#define PA3 GPIO_BITS(GPIO_PORTA, 3)
因此,当您遇到数组定义时,不会尝试将类型名称扩展为宏。