keil5编译报错*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS的解决办法

       这种错误叫做多个公共定义,一般都是同一个变量,连续初始化了多次,

      比如说我在这个文件当中这里定义了这个Position这个变量,当你想要在其他文件中使用时,于是你复制过去使用 “extern” 关键字进行声明,如下图,就是会导致编译报这种错误的示范。     变量在声明时是不能初始化其参数的,只有第一次定义时才可以,把这一条修改为

    extern unsigned char Position; 再编译,该错误就会消除。

<think>嗯,用户问的是Keil编译时出现的错误*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS,特别是涉及符号SCK。我需要先理解这个错误的根本原因,然后逐步解释给用户。 首先,L104错误通常是因为同一个符号被多次定义。在C语言中,公共符号(public definitions)通常指全局变量或函数,如果在多个文件中重复定义,就会导致这个错误。SCK可能是一个变量,被多次声明为全局变量,或者在头文件中定义而没有防止重复包含。 接下来,我得想用户可能的代码结构。比如,用户可能在头文件里定义了SCK,然后在多个源文件包含该头文件,导致每个包含的文件都有一个SCK的定义。或者,用户在多个.c文件中都声明了SCK为全局变量,而没有使用extern关键字。 然后,我需要给出解决方案。首先是检查所有SCK的定义,确保全局变量只在头文件中用extern声明,在某个.c文件中定义一次。其次是检查头文件的防护措施,比如#ifndef...#define...#endif,防止重复包含。另外,可能用户不小心在头文件里初始化了变量,导致每个包含该头文件的源文件都生成一个定义。 还要提醒用户检查拼写错误,是否有其他变量名拼写错误导致重复。比如,是否有SCK和Sck这样的不同拼写,但编译器认为相同的情况。此外,检查链接器是否包含了重复的目标文件,或者在不同的库中重复定义了SCK。 可能用户的问题出现在51单片机编程中,SCK可能是SPI时钟线的引脚定义,比如用sbit SCK = P1^3;这样的方式。如果这个定义出现在头文件,并且被多个源文件包含,就会导致多次定义。正确的做法是在一个源文件中定义,头文件中用extern声明。 最后,总结解决步骤:查找所有SCK的定义,确保只在一个地方定义,其他地方用extern;检查头文件的防护;检查拼写错误和链接文件。这样用户就能逐步排除问题,解决L104错误。</think>*** ERROR L104: MULTIPLE PUBLIC DEFINITIONSKeil C51 编译器在链接阶段报出的错误,表示同一个符号(如变量、函数)被重复定义。以下将逐步分析问题本质和解决方案: #### 错误本质分析 - 🔍 根本原因:`SCK` 符号在多个文件中被定义为全局变量(public symbol),导致链接器无法确定唯一地址 - 📌 常见场景: 1. 在头文件(.h)中直接定义变量 `sbit SCK = P1^3;`,且该头文件被多个源文件(.c)包含 2. 在不同源文件中重复定义同名全局变量 `unsigned char SCK;` 3. 函数定义被多个文件包含(非声明) #### 诊断步骤 1. **全局搜索 `SCK` 定义** - 在工程中搜索所有包含 `SCK` 的位置 - 特别注意 `.c` 文件和 `.h` 文件中的定义语句: ```c sbit SCK = P1^3; // 定义语句 unsigned char SCK; // 定义语句 ``` 2. **识别定义类型** - 合格声明:`extern sbit SCK;`(仅声明) - 错误定义:`sbit SCK = P1^3;`(重复定义) #### 解决方案 1. **单一定义原则** - 选择 **一个**.c 文件(如 `SPI.c`)进行实体定义: ```c sbit SCK = P1^3; // 仅在此处定义 ``` - 在对应头文件(`SPI.h`)中声明: ```c extern sbit SCK; // 声明而非定义 ``` 2. **头文件保护** 确保头文件包含条件编译防护: ```c #ifndef __SPI_H__ #define __SPI_H__ extern sbit SCK; #endif ``` 3. **检查特殊语法** - 对于51内核的特殊寄存器定义: ```c __sfr __at (0x80) SCK; // 特殊语法也需遵循单一定义 ``` #### 扩展排查 - 📂 检查文件包含关系:使用 Keil 的 `Options for Target -> Listing -> C Compiler Listing` 生成 `.lst` 文件查看宏展开 - 🔗 检查链接顺序:在 `Options for Target -> Linker` 中确认没有重复链接目标文件 - 🔤 注意大小写:C51 默认不区分大小写,`SCK` 和 `sck` 会被视为同一符号 #### 应用示例 ✅ 正确配置: ```c /* SPI.h */ #ifndef __SPI_H__ #define __SPI_H__ extern sbit SCK; // 声明 #endif /* SPI.c */ #include "SPI.h" sbit SCK = P1^3; // 唯一实体定义 ``` ❌ 错误配置: ```c /* main.c */ #include "SPI.h" sbit SCK = P1^5; // 重复定义 /* SPI.c */ #include "SPI.h" sbit SCK = P1^3; // 重复定义 ``` 通过以上方法系统排查,可有效解决 L104 错误。建议使用 Keil 的 `Browse Information` 功能(需在 Options for Target -> Output 中勾选)查看符号交叉引用关系。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉缘铭尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值