我对使用PIC芯片还比较陌生,所以这可能是一个新手级别的问题,但是我试图编写一个头文件,其中包括所有I / T的TRIS / ODC / INIT掩码。 O端口。
在此芯片内置的PCB上,任何给定的组件都可能使用来自多个端口的引脚,并且大概有十几个单独的组件需要详细注释。例如,与特定的SPI ADC模块接口时,使用端口A,D和F的引脚。
对我来说,似乎方便读者的编写方式是按组件组织文件,以便读者一眼就能知道正在使用的引脚,是配置为输入还是输出。 ,以及它们的初始化方式。
例如,仅显示TRIS掩码信息,这是我用来演示我在说什么的特定ADC模块的代码片段:
#define PORTD_TRIS_MASK 0x00
#define PORTF_TRIS_MASK 0x00
// ...
// lots of hardware configuration stuff goes here
// ...
// ANALOG INPUT - THERMOCOUPLE 1
// Thermocouple ADC chip MAX31856 DNP communicates over SPI
// Accepts any type of thermocouple
// TC1_CS pulled high
// TC1_DRDY pulled high
#define TC1_MOSI LATAbits.LATA14
#define TC1_MISO PORTDbits.RD10
#define TC1_SCK LATDbits.LATD11
#define TC1_CS LATFbits.LATF6
#define TC1_DRDY PORTFbits.RF7
#define TC1_MISO_SHIFT 1<<10
#define TC1_DRDY_SHIFT 1<<7
#define PORTD_TRIS_MASK ( PORTD_TRIS_MASK | TC1_MISO_SHIFT )
#define PORTF_TRIS_MASK ( PORTF_TRIS_MASK | TC1_DRDY_SHIFT )
上面的代码不会引发任何错误,但是会引发警告:
HardwareProfile.h:1173:0: warning: "PORTD_TRIS_MASK" redefined
HardwareProfile.h:1029:0: note: this is the location of the previous definition
HardwareProfile.h:1174:0: warning: "PORTF_TRIS_MASK" redefined
HardwareProfile.h:1095:0: note: this is the location of the previous definition
编译器在抱怨它的事实向我表明,这可能不是鼓励的行为,但对我而言,这似乎没有内在的问题。我是否缺少某些内容,还是这是一种合理的方式来组织代码,以使引脚配置详细信息保持在其定义附近?]
或者,在保持更广泛使用或可接受的可读性方面,还有一种更常规的方式来完成我想完成的工作吗?
更新:也许我在原始帖子中不够清晰。之所以这样构造,是因为头文件中有十几个这样的代码块。假设恰好有13个这样的代码块,则任何特定的掩码最初都将定义为0x00并重新定义13次,其想法是每次重新定义都会添加与特定块有关的配置信息。
预处理器的工作方式与代码不同。例如,考虑以下代码:
int main(void)
{
int A = (B+C);
int B = (C+2);
int C = 3;
int x = A;
return x;
}
这不起作用,因为在声明之前使用了B和C。编译器的输出为:
cc -Wall demo.c -o demo
demo.c:3:14: error: use of undeclared identifier 'B'
int A = (B+C);
^
demo.c:3:16: error: use of undeclared identifier 'C'
int A = (B+C);
^
demo.c:4:14: error: use of undeclared identifier 'C'
int B = (C+2);
^
现在使用A,B和C的#define
尝试相同的事情:
#define A (B+C)
#define B (C+2)
#define C 3
int main(void)
{
int x = A;
return x;
}
这次,即使#define
出现故障,也没有警告或错误。当预处理器看到#define
时,它只是在其字典中添加一个条目。因此,在阅读了三个#define
之后,字典包含
Search Replacement
Text Text
--------------------
A (B+C)
B (C+2)
C 3
请注意,预处理器尚未评估替换文本。它只是存储文本。当预处理器在代码中找到搜索词时,它将使用替换文本。所以这行
int x = A;
成为
int x = (B+C);
执行替换后,预处理器将重新扫描文本以查看是否可以进行更多替换。在第二次扫描后,我们有:
int x = ((C+2)+3);
最终结果是:
int x = ((3 +2)+3);
大多数编译器可以选择在预处理完成后输出代码。对于gcc或clang,请使用-E
选项获取预处理器输出。
好的,现在我们应该有足够的背景来实际解决您的问题。考虑以下定义:
#define PORTD_TRIS_MASK 0x00
#define PORTD_TRIS_MASK ( PORTD_TRIS_MASK | TC1_MISO_SHIFT )
#define PORTD_TRIS_MASK ( PORTD_TRIS_MASK | SB1_DATA_SHIFT )
我们在这里有3个主要问题:
PORTD_TRIS_MASK
时,预处理器将其替换为( PORTD_TRIS_MASK | SB1_DATA_SHIFT )
。然后重新扫描,并再次找到PORTD_TRIS_MASK
。结果是无限递归。幸运的是,预处理器可以防止此类情况发生,并且会产生错误。解决方案是为每个组件创建唯一命名的定义
#define TRIS_MASK_D1 TC1_MISO_SHIFT
#define TRIS_MASK_F1 TC1_DRDY_SHIFT
#define TRIS_MASK_D2 SB1_DATA_SHIFT
#define TRIS_MASK_F2 0
然后将它们全部或在一起
#define PORTD_TRIS_MASK (TRIS_MASK_D1 | TRIS_MASK_D2 | ... | TRIS_MASK_D13)
#define PORTF_TRIS_MASK (TRIS_MASK_F1 | TRIS_MASK_F2 | ... | TRIS_MASK_F13)