*** Using Compiler 'V5.06 update 5 (build 528)', folder: 'G:\Keil_v5\ARM\ARMCC\Bin' Build target 'Target 1' linking... .\Objects\Project.axf: Error: L6218E: Undefined symbol GetSystemTick (referred from main.o). Not enough information to list image symbols. Not enough information to list load addresses in the image map. Finished: 2 information, 0 warning and 1 error messages. ".\Objects\Project.axf" - 1 Error(s), 0 Warning(s). Target not created. Build Time Elapsed: 00:00:00
时间: 2025-07-20 21:27:01 浏览: 5
<think>我们遇到了一个链接错误:未定义的符号 GetSystemTick(在 main.o 中被引用)。
这个错误通常意味着在 main.c 中使用了 GetSystemTick 这个函数,但是链接器在所有的源文件和库中都没有找到这个函数的定义。
解决步骤:
1. 检查是否在某个头文件中声明了 GetSystemTick 函数,但没有定义(即没有对应的 .c 文件实现)。
2. 检查是否包含了实现 GetSystemTick 函数的源文件或库。
在代码中,我们没有看到直接调用 GetSystemTick 的地方,但可能是间接调用的(比如在某个函数中使用了,而该函数被调用)。
观察错误信息:在 main.o 中引用了 GetSystemTick,说明 main.c 中使用了这个函数。
可能的原因:
- 可能在 delay.h 或 delay.c 中使用了 GetSystemTick,但 delay.c 中没有定义这个函数。
- 或者,我们可能需要实现一个获取系统tick的函数。
在STM32中,通常使用 SysTick 定时器来提供系统时钟节拍。常见的做法是定义一个全局变量(如 sysTick)来记录系统启动以来的tick数,然后在SysTick中断服务函数中递增这个变量。然后,我们可以提供一个函数 GetSystemTick 来返回当前的 sysTick 值。
解决方案:
1. 在 delay.c 中(或者在一个单独的系统时钟模块中)实现 GetSystemTick 函数。
2. 确保在链接时包含了定义 GetSystemTick 的文件。
具体步骤:
步骤1:在某个源文件(如 delay.c)中定义 GetSystemTick 函数。
首先,我们需要一个全局变量来记录系统tick。例如:
volatile uint32_t sysTick = 0; // 在文件开头定义
步骤2:在 SysTick 中断服务函数中递增这个变量。
SysTick_Handler 函数(在 stm32f10x_it.c 中)应该包含:
extern volatile uint32_t sysTick;
sysTick++;
步骤3:在 delay.c 中实现 GetSystemTick 函数:
uint32_t GetSystemTick(void) {
return sysTick;
}
步骤4:在 delay.h 中声明这个函数:
uint32_t GetSystemTick(void);
步骤5:在 main.c 中包含 delay.h,确保函数声明可见。
但是,请注意:如果 delay.c 中已经实现了 SysTick 相关的函数,并且已经有了一个系统tick变量,那么可能我们只需要在 delay.h 中声明 GetSystemTick 函数即可。
如果我们的代码中已经有一个获取系统tick的函数,但名字不叫 GetSystemTick,那么我们可以:
- 将现有的函数重命名为 GetSystemTick,或者
- 在 delay.h 中定义一个宏: #define GetSystemTick 现有的函数名
然而,根据错误信息,我们当前使用的是 GetSystemTick 这个名称,所以我们需要确保这个函数被实现。
如果我们的 delay 模块已经有一个函数返回系统tick,比如叫做 delay_get_tick(),那么我们可以在 main.c 中定义一个别名(不推荐,因为链接器只认名字)或者修改代码使用现有的函数。
但是,为了快速解决,我们可以直接实现 GetSystemTick。
另外,还有一种可能:我们使用的 delay 模块可能需要用户提供 GetSystemTick 的实现。如果是这样,我们需要按照模块的要求实现这个函数。
根据错误信息,我们当前没有实现 GetSystemTick,所以我们需要实现它。
具体代码实现示例:
在 delay.c 文件中添加:
```c
#include "delay.h"
volatile uint32_t sysTick = 0; // 定义在文件作用域
void SysTick_Handler(void) // 如果还没有定义SysTick中断处理函数,则定义它
{
sysTick++;
}
uint32_t GetSystemTick(void)
{
return sysTick;
}
```
在 delay.h 文件中添加:
```c
extern volatile uint32_t sysTick; // 声明为外部变量,如果其他文件需要直接访问(但建议通过函数访问)
uint32_t GetSystemTick(void);
```
注意:如果 SysTick_Handler 已经在其他文件(如 stm32f10x_it.c)中定义,那么我们应该在那里增加 sysTick 的递增操作,而不是在 delay.c 中再定义一次。否则会导致重复定义。
因此,更安全的做法是:
1. 在 delay.c 中定义 sysTick 变量和 GetSystemTick 函数。
2. 在 stm32f10x_it.c 中修改 SysTick_Handler 函数,使其包含对 sysTick 的递增。
但是,这样就需要在 stm32f10x_it.c 中引用 delay.h 中的 sysTick 变量,这可能会引起循环包含问题。
因此,我们可以这样:
在 delay.h 中声明:
extern volatile uint32_t sysTick;
在 delay.c 中定义:
volatile uint32_t sysTick = 0;
在 stm32f10x_it.c 中包含 delay.h,然后在 SysTick_Handler 函数中递增 sysTick:
#include "delay.h"
void SysTick_Handler(void)
{
sysTick++;
}
这样,我们就将 sysTick 的定义放在 delay.c 中,而声明放在 delay.h 中,这样 stm32f10x_it.c 就可以通过包含 delay.h 来访问 sysTick。
但是,请注意:如果 delay.c 没有被编译进工程,那么 sysTick 就没有定义,链接会出错。所以确保 delay.c 被加入工程。
另外,我们还需要在初始化时配置 SysTick 定时器。通常在 delay_init 函数中配置。
因此,我们需要修改 delay_init 函数,启动 SysTick 定时器。例如:
```c
void delay_init()
{
// 设置 SysTick 定时器每 1ms 中断一次
if (SysTick_Config(SystemCoreClock / 1000)) {
// 错误处理
while (1);
}
}
```
总结:我们需要做以下几步:
1. 在 delay.c 中定义 volatile uint32_t sysTick = 0;
2. 在 stm32f10x_it.c 的 SysTick_Handler 函数中增加 sysTick++;
3. 在 delay.c 中实现 GetSystemTick 函数。
4. 在 delay.h 中声明 GetSystemTick 函数和 extern volatile uint32_t sysTick;
5. 确保 delay_init 中配置了 SysTick 定时器(例如1ms中断一次)。
这样,链接错误应该可以解决。
如果项目已经有一个 SysTick 配置,那么只需要检查并添加 sysTick 的递增和 GetSystemTick 的实现。
注意:如果项目使用了 HAL 库,可能会使用 HAL_IncTick 函数,那么我们可以不用自己定义 sysTick,而是使用 HAL 提供的 HAL_GetTick 函数。但是,错误信息中要求的是 GetSystemTick,所以我们可以将 GetSystemTick 定义为 HAL_GetTick 的别名(如果使用 HAL 库的话)。
但是,根据代码,我们并没有使用 HAL 库,而是直接使用标准外设库(因为包含了 stm32f10x.h)。所以,我们需要自己实现。
因此,按照上述步骤修改代码即可。
修改后,重新编译。
如果还有问题,请检查:
- delay.c 是否被加入工程并编译
- 函数声明和定义是否一致
现在,我们重新构建项目。</think>### 链接错误分析:L6218E: Undefined symbol GetSystemTick
这个链接错误表明编译器在 `main.o` 文件中发现了对 `GetSystemTick` 函数的引用,但链接器在所有目标文件和库中都找不到该函数的实现。以下是详细分析和解决方案:
#### 错误原因:
1. **函数未实现**
在工程中缺少 `GetSystemTick()` 函数的定义,可能发生在:
- 函数声明在头文件中(如 `delay.h`),但未在源文件中实现
- 包含函数实现的源文件未被添加到工程中
2. **函数签名不匹配**
函数声明和实现可能使用了不同的参数或返回类型:
```c
// 声明(delay.h)
uint32_t GetSystemTick(void);
// 实现(delay.c)
uint32_t GetSystemTick(uint8_t mode) // 参数不匹配
```
3. **编译依赖问题**
修改了头文件后未重新编译相关源文件,导致声明与实现不一致。
---
### 解决方案:
#### 步骤1:检查函数声明
在 `delay.h` 中确认声明是否正确:
```c
// delay.h
uint32_t GetSystemTick(void); // 确保无参数
```
#### 步骤2:添加函数实现
在 `delay.c` 中实现函数:
```c
// delay.c
volatile uint32_t sysTick = 0; // 全局tick计数器
uint32_t GetSystemTick(void) {
return sysTick; // 返回当前系统tick值
}
// SysTick中断处理函数(每1ms触发一次)
void SysTick_Handler(void) {
sysTick++; // 计数器递增
}
```
#### 步骤3:配置系统时钟
在 `delay_init()` 中初始化SysTick定时器:
```c
// delay.c
void delay_init() {
// 配置SysTick为1ms中断(假设系统时钟72MHz)
if (SysTick_Config(SystemCoreClock / 1000)) {
// 错误处理
while(1);
}
}
```
#### 步骤4:验证工程配置
1. 确保 `delay.c` 已加入Keil工程

2. 执行完整重建:
- Project → Clean Target
- Project → Rebuild all target files
---
### 常见错误排查表:
| 现象 | 检查点 | 解决方法 |
|------|--------|----------|
| 函数未定义 | 源文件是否在工程中 | 右键工程→Add Existing Files |
| 多重定义 | 函数是否在头文件实现 | 将实现移到.c文件 |
| 链接顺序错误 | 库文件链接顺序 | Options→Linker→Misc控制链接顺序 |
| 优化冲突 | 优化等级不一致 | 所有文件统一使用-O1优化 |
> **关键提示**:在Keil中,通过 `Options for Target → Linker → Misc controls` 添加 `--verbose` 可查看详细链接过程,定位未解析符号。
阅读全文
相关推荐


















