0

我正在进行一个带有 EFM32 PG12 入门套件和简单工作室的显微镜微控制器项目。在这个项目中,我在 .h 文件 global_definitions.h 中做了一些全局引脚和端口定义

这样做是因为复杂。不同文件中的许多功能直接访问引脚、考虑定时器或通过 PRS。

这里有一些 global_definitions.h:

#pragma once //not working

#define startUpMessage  "I:000:Initialization finished"

#define prsChannel 6

//pin definitions for the lasers

unsigned int laserPinNumbers[]={2,3,12,13,14,15};
unsigned int laserPorts[]={gpioPortA,gpioPortA,gpioPortD,gpioPortD,gpioPortD,gpioPortD};

unsigned int laserTimers[]={0,0,1,1,1,1};
#define timer0 WTIMER0
#define timer1 WTIMER1

等等 ...

如果我尝试编译我的项目,我会收到错误:

arm-none-eabi-gcc -g3 -gdwarf-2 -mcpu=cortex-m4 -mthumb -T "SLM_PG12_3.ld" -Xlinker --gc-sections -Xlinker -Map="SLM_PG12_3.map" -mfpu=fpv4-sp-d16 -mfloat-abi=softfp --specs=nano.specs -o SLM_PG12_3.axf "./CMSIS/EFM32PG12B/startup_efm32pg12b.o" "./CMSIS/EFM32PG12B/system_efm32pg12b.o" "./emlib/em_cmu.o" "./emlib/em_core.o" "./emlib/em_gpio.o" "./emlib/em_prs.o" "./emlib/em_rtc.o" "./emlib/em_rtcc.o" "./emlib/em_system.o" "./emlib/em_timer.o" "./emlib/em_usart.o" "./emlib/udelay.o" "./src/i2c.o" "./src/izi_usart.o" "./src/laserSequences.o" "./src/leds.o" "./src/main.o" -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
./src/leds.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:12: multiple definition of `laserPinNumbers'
./src/laserSequences.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:12: first defined here
./src/leds.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:13: multiple definition of `laserPorts'
./src/laserSequences.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:13: first defined here
...
collect2: error: ld returned 1 exit status
make: *** [SLM_PG12_3.axf] Error 1

包括后卫

#ifndef GLOBAL_DEFINITIONS
#define GLOBAL_DEFINITIONS
...
#endif

也不工作。

在c中进行全局定义的正确方法是什么?

谢谢。

4

1 回答 1

0

#pragma once在编译单个源文件时保护头文件免受多个包含。因此,如果您leds.c多次编译并尝试包含此文件,可能来自不同包含级别的其他包含文件,则编译指示保证该文件在此编译期间仅解析一次。编译时也会发生同样的情况laserSequences.c

现在您已经编译了至少 2 个源文件 inte .oform。每个人都包含过一次头文件,并且每个人都从这个头文件中声明了全局变量。链接器抱怨是因为它不知道使用哪一个。

解决方法是永远不要在头文件中声明变量。您只提供其外部链接的定义。声明必须在一个且只有一个源文件中完成,例如:

global_definitions.h:

#pragma once 

#define startUpMessage  "I:000:Initialization finished"
#define prsChannel 6

extern unsigned int laserPinNumbers[];
extern unsigned int laserPorts[];
extern unsigned int laserTimers[];
...

现在在其中一个文件中,无论是在您拥有的.c文件中还是在其他文件中,例如,global_definitions.c您可以声明变量:

unsigned int laserPinNumbers[]={2,3,12,13,14,15};
unsigned int laserPorts[]={gpioPortA,gpioPortA,gpioPortD,gpioPortD,gpioPortD,gpioPortD};

unsigned int laserTimers[]={0,0,1,1,1,1};

此外,#pragma once它是一个相对较新的添加(它可能在旧版本的编译器中不起作用)替换保护宏的标准。它们的工作方式相同。

于 2020-05-10T14:23:38.123 回答