gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 10:09:20 25 4
gpt4 key购买 nike

我对使用 PIC 芯片比较陌生,所以这可能是一个新手级别的问题,但我正在尝试编写一个头文件,其中包含所有 I/O 端口的 TRIS/ODC/INIT 掩码等.

在该芯片内置的 PCB 上,任何给定组件都可能使用来自多个端口的引脚,并且可能有十几个单独的组件需要详细评论。例如,与特定 SPI ADC 模块的接口(interface)使用端口 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 次,其想法是每次重新定义都会添加与特定 block 相关的配置信息。

更新:
在回答有关如何使用这些宏的问题时,它们仅用于一次配置端口中的所有引脚。在这个 PIC24 上,每个端口有 16 个引脚,每个引脚都有一个 TRIS(数据方向控制)寄存器、ODC(开漏控制)寄存器和 LAT(锁存器)寄存器,如果配置为输出,则需要一个初始值.按照惯例,不鼓励一次写入一个位 16 次,而建议对整个端口写入一次。例如,考虑一个简化的情况,其中有四个寄存器而不是十六个。而不是这样写:
// In source file
TRISABITS.TRISA0 = 1;
TRISABITS.TRISA1 = 1;
TRISABITS.TRISA2 = 0;
TRISABITS.TRISA3 = 0;

写这个是传统的(据我所知):
// In header file
#define BIT_0_SHIFT ( 1<<0 )
#define BIT_1_SHIFT ( 1<<1 )
#define BIT_2_SHIFT ( 0<<2 )
#define BIT_3_SHIFT ( 0<<3 )
#define TRISA_MASK ( BIT_0_SHIFT | BIT_1_SHIFT | BIT_2_SHIFT | BIT_3_SHIFT )

// In source file
TRISA = TRISA_MASK;


关于可读性的另一个问题,我支持这种结构的论点是,在这个芯片上组织端口的方式在物理上没有意义。任何特定端口上的引脚不一定彼此靠近或按顺序排列,并且没有单个设备(例如外部 SPI 模块)被限制在单个端口上。按端口组织头文件意味着读者需要滚动整个头文件以检查单个设备的配置,而按设备组织文件允许整个设备的定义和配置在单个屏幕上清晰可见。

最佳答案

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

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);
^

现在使用 #define 尝试相同的操作s 代表 A、B 和 C:
#define A (B+C)
#define B (C+2)
#define C 3

int main(void)
{
int x = A;
return x;
}

这次没有警告或错误,即使 #define s 出现故障。当预处理器看到 #define它只是在其字典中添加一个条目。所以看完三部 #define s 字典包含
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个主要问题:
  • 替换文本没有被评估,所以这些位没有被 OR'd 在一起。
  • 只有一个定义(最后一个)将保存在预处理器字典中。这就是警告的原因。预处理器告诉您它已经有该搜索词的条目,它将丢弃以前的替换文本。
  • 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)

    关于c - 为 PIC24 重新定义寄存器掩码以提高可读性是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59742345/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com