重新定义PIC24的寄存器掩码以提高可读性是不好的做法吗?

问题描述 投票:3回答:1

我对使用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次,其想法是每次重新定义都会添加与特定块有关的配置信息。

c microcontroller pic
1个回答
0
投票

预处理器的工作方式与代码不同。例如,考虑以下代码:

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个主要问题:

  1. 替换文本没有被评估,所以这些位不被或在一起。
  2. 这些定义中只有一个(最后一个)将保留在预处理程序字典中。这就是发出警告的原因。预处理器告诉您,该搜索词已经具​​有一个条目,并且它将丢弃之前的替换文本。
  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)
© www.soinside.com 2019 - 2024. All rights reserved.