.\Objects\empty_LP_MSPM0G3507_nortos_keil.axf: Error: L6200E: Symbol fputc multiply defined (by bsp_mpu6050.o and empty.o).
时间: 2025-07-22 08:20:42 浏览: 113
<think>我们正在解决Keil编译错误:L6200E,Symbol fputc multiply defined(符号fputc被多重定义)。这个错误通常发生在同一个符号(函数或变量)在多个源文件中被定义,导致链接器无法确定使用哪个定义。
根据引用[1]和引用[2]提供的信息,这种错误通常是由于全局变量或函数在头文件中定义,然后被多个源文件包含,导致每个源文件都有一份定义,从而在链接时出现重复定义。
具体到`fputc`函数,这个函数是标准库中用于字符输出的函数。在Keil中,用户有时会重定义`fputc`以重定向printf输出(例如到串口)。如果这个重定义被放在了头文件中,并且该头文件被多个源文件包含,那么就会导致多个源文件都定义了`fputc`,从而引发链接错误。
解决方法:
1. 避免在头文件中定义函数或变量(除非使用static关键字,但static会使每个文件有自己的副本,可能不适用于需要全局唯一的情况)。
2. 将函数定义放在一个源文件中(如.c文件),然后在头文件中只放声明(使用extern关键字)。
针对`fputc`的解决方法:
- 检查你的代码,找到`fputc`函数的定义。通常它可能出现在一个头文件(如`uart.h`)或某个源文件中。
- 如果定义在头文件中,将其移到一个源文件中(例如`main.c`或`uart.c`),并在头文件中改为声明(使用extern)。但是注意,`fputc`是标准库函数,我们通常重写它,所以正确的做法是只在一个源文件中定义它。
具体步骤:
1. 在你的工程中,搜索`fputc`,找到其定义。通常它看起来像这样:
```c
int fputc(int ch, FILE *f)
{
// 例如,将字符发送到串口
USART_SendData(USART1, (uint8_t) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
return ch;
}
```
2. 如果这个函数定义在头文件(.h)中,请将其移动到某个源文件(.c)中,比如`main.c`或`uart.c`。注意,只能在一个源文件中定义。
3. 确保没有其他源文件包含这个函数的定义。如果其他源文件也需要使用这个函数,那么应该通过包含声明了该函数的头文件来使用(即在头文件中使用extern声明,但通常我们不声明`fputc`,因为它是标准库函数,我们只是覆盖它,所以不需要在其他地方声明)。
4. 实际上,重定义的`fputc`只需要在一个源文件中定义一次即可。链接器会自动覆盖标准库中的定义。
另外,还有一种情况:你可能在多个源文件中都包含了这个重定义,而每个源文件都定义了自己的`fputc`。这时,你需要确保只有一个源文件定义了它。
例如,如果你在`file1.c`和`file2.c`中都定义了`fputc`,那么就会冲突。你需要删除其中一个定义。
总结步骤:
- 确保整个工程中`fputc`只在一个源文件中定义。
- 如果之前定义在头文件中,将其移到一个源文件中,并删除头文件中的定义。
- 清理工程并重新编译。
注意:有时在Keil中,你可能需要检查是否在多个地方(比如某个库文件和你自己的文件)都定义了`fputc`。确保只有你自己的一个文件定义了它。
如果问题仍然存在,可以尝试在工程选项中设置忽略标准库中的`fputc`,但通常不需要,因为用户重定义会自动覆盖。
根据引用[2]中提到的,还可以通过将函数声明为static来避免,但这样每个文件都有一个副本,可能不是我们想要的(因为重定向输出我们只需要一个全局的)。所以不推荐。
因此,推荐的方法是:确保`fputc`只在一个源文件中定义。
§§相关问题§§
1. Keil中如何重定向printf到串口?
2. 如何避免Keil中的多重定义错误?
3. Keil链接错误L6200E的其他常见原因有哪些?</think>### Keil编译错误 L6200E: Symbol fputc multiply defined 解决方法
该错误表示 `fputc` 函数在多个文件中被重复定义,导致链接器无法确定使用哪个版本。以下是逐步解决方案:
#### 原因分析
1. **重定义冲突**:`fputc` 是标准库函数(如 `stdio.h`),用户自定义实现时若被多个源文件包含,会导致重复定义。
2. **头文件错误**:若在头文件(`.h`)中直接定义函数而非声明,所有包含该头文件的源文件(`.c`)都会生成独立副本[^1][^2]。
#### 解决方法
1. **检查自定义 `fputc` 的位置**
- 搜索工程中所有 `fputc` 定义:在 Keil 中按 `Ctrl+Shift+F` 全局搜索。
- 确认是否在头文件中定义(错误做法):
```c
// 错误示例:在 .h 文件中定义函数
int fputc(int ch, FILE *f) { // 会导致多重定义
UART_SendChar(ch); // 串口发送实现
return ch;
}
```
2. **修正为单一定义**
- **正确做法**:将函数定义移至**一个源文件**(如 `main.c` 或 `retarget.c`):
```c
// 正确示例:仅在 .c 文件中定义一次
#include "uart.h" // 声明UART相关函数
int fputc(int ch, FILE *f) {
HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 100); // STM32 HAL示例
return ch;
}
```
- **头文件仅保留声明**(如需共享):
```c
// 在 .h 文件中使用 extern 声明(非必须)
extern int fputc(int ch, FILE *f); // 声明而非定义[^2]
```
3. **检查库文件冲突**
- 若使用标准库(如 `MicroLIB`),确保未在多个位置重定义:
- 打开工程选项:`Project → Options for Target → Target`
- 检查是否勾选 `Use MicroLIB`(通常需启用以支持重定向)。
4. **清理并重建工程**
- 删除编译缓存:`Project → Clean Targets`
- 重新编译:`F7` 或 `Rebuild All`
#### 验证示例
假设工程结构如下:
```
├── Core/Src/main.c // 在此定义fputc
├── Core/Src/uart.c // 串口驱动
└── Core/Inc/uart.h // 仅包含函数声明
```
在 `main.c` 中添加:
```c
#include "uart.h"
int fputc(int ch, FILE *f) { // 唯一实现
uart_send(ch); // 调用串口发送函数
return ch;
}
```
#### 预防措施
- **避免在头文件中定义函数**:头文件应只包含声明(`extern`)和宏。
- **使用静态函数**:若函数仅限单文件使用,添加 `static` 关键字:
```c
static int fputc(...) { ... } // 仅当前文件可见
```
阅读全文
相关推荐




















