*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'D:\webdownload\ARM\ARMCC\Bin' Rebuild target 'Target 1' assembling startup_stm32f10x_md.s... compiling stm32f10x_flash.c... compiling misc.c... compiling stm32f10x_fsmc.c... compiling stm32f10x_adc.c... compiling stm32f10x_can.c... compiling stm32f10x_cec.c... compiling stm32f10x_exti.c... compiling system_stm32f10x.c... compiling stm32f10x_dac.c... compiling stm32f10x_dbgmcu.c... compiling stm32f10x_crc.c... compiling stm32f10x_bkp.c... compiling stm32f10x_dma.c... compiling core_cm3.c... compiling stm32f10x_gpio.c... compiling stm32f10x_i2c.c... compiling stm32f10x_iwdg.c... compiling stm32f10x_pwr.c... compiling stm32f10x_rtc.c... compiling stm32f10x_rcc.c... compiling stm32f10x_sdio.c... compiling stm32f10x_spi.c... compiling stm32f10x_wwdg.c... compiling Delay.c... compiling stm32f10x_usart.c... compiling Key.c... compiling LED.c... compiling HC_SR04.c... HC_SR04.h(15): warning: #1-D: last line of file ends without a newline SysTick.h(4): warning: #1-D: last line of file ends without a newline HC_SR04.c(103): warning: #1-D: last line of file ends without a newline } HC_SR04.c: 3 warnings, 0 errors compiling OLED.c... compiling SysTick.c... SysTick.h(4): warning: #1-D: last line of file ends without a newline SysTick.c(26): warning: #1-D: last line of file ends without a newline } SysTick.c: 2 warnings, 0 errors compiling stm32f10x_tim.c... compiling main.c... User\main.c(3): error: #5: cannot open source input file "HC_SR04.h": No such file or directory #include "HC_SR04.h" User\main.c: 0 warnings, 1 error compiling stm32f10x_it.c... ".\Objects\Project.axf" - 1 Error(s), 5 Warning(s). Target not created. Build Time Elapsed: 00:00:03
时间: 2025-07-23 15:06:15 浏览: 37
<think>我们分析用户的问题:编译错误是"cannot open source input file HC_SR04.h",这意味着Keil在包含路径中找不到HC_SR04.h头文件。同时,用户还遇到了"main.h"找不到的问题。另外,之前的编译输出中还有关于文件末尾缺少换行的警告。
解决方案:
1. 确保所有自定义头文件(如HC_SR04.h, main.h)都存在于工程目录中,并且被正确添加到Keil的包含路径(Include Paths)中。
2. 检查头文件的内容,确保它们被正确定义,并且文件末尾有一个空行(以避免警告)。
3. 由于用户使用了HC-SR04超声波模块,我们需要提供完整的HC_SR04驱动代码以及正确的main函数。
下面我们提供完整的代码,包括:
- main.h:主要包含一些宏定义和函数声明
- HC_SR04.h:超声波模块的头文件
- HC_SR04.c:超声波模块的实现
- main.c:主程序
- 另外,根据之前的错误,用户还使用了SysTick,所以我们提供SysTick的延时函数(如果需要的话)
注意:我们假设硬件连接为:
TRIG -> PA0
ECHO -> PA1
步骤:
1. 在Keil工程中,确保这些文件都被添加。
2. 设置正确的包含路径(包括这些文件所在的文件夹)。
由于用户之前的代码中包含了"HC_SR04.h"和"main.h",我们首先创建这两个头文件。
我们先写main.h:</think># STM32 Keil编译错误 "cannot open source input file HC_SR04.h" 解决方案
## 问题分析
编译错误 `cannot open source input file HC_SR04.h` 通常由以下原因引起:
1. **头文件路径未正确配置**:Keil MDK找不到头文件所在目录
2. **头文件命名或位置错误**:文件可能被重命名或移动到其他目录
3. **工程配置问题**:头文件未被添加到工程中或包含路径设置错误
4. **版本兼容性问题**:不同版本的MDK或STM32库可能有不同的头文件命名规则[^1]
## 完整解决方案
### 步骤1:检查头文件位置
确保 `HC_SR04.h` 文件位于以下位置之一:
- 工程根目录下的 `User/` 文件夹
- 专门的头文件目录如 `Inc/` 或 `Headers/`
- 与源文件相同的目录
### 步骤2:配置Keil包含路径
1. 打开Keil MDK工程
2. 点击 `Options for Target` 图标
3. 转到 `C/C++` 选项卡
4. 在 `Include Paths` 中添加头文件所在目录路径
### 步骤3:创建缺失的头文件
如果找不到 `HC_SR04.h`,请创建以下内容:
#### HC_SR04.h
```c
#ifndef __HC_SR04_H
#define __HC_SR04_H
#include "stm32f10x.h"
// 引脚定义
#define TRIG_GPIO_PORT GPIOA
#define TRIG_GPIO_PIN GPIO_Pin_0
#define ECHO_GPIO_PORT GPIOA
#define ECHO_GPIO_PIN GPIO_Pin_1
// 函数声明
void HC_SR04_Init(void);
float Get_Distance(void);
void Delay_us(uint32_t us);
#endif /* __HC_SR04_H */
```
#### main.h
```c
#ifndef __MAIN_H
#define __MAIN_H
#include "stm32f10x.h"
#include "HC_SR04.h" // 包含超声波模块头文件
// 系统时钟频率定义
#define SYSTEM_CLOCK_FREQ 72000000 // 72MHz
// 函数声明
void SystemClock_Config(void);
void Error_Handler(void);
#endif /* __MAIN_H */
```
### 步骤4:创建源文件
#### HC_SR04.c
```c
#include "HC_SR04.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
volatile uint32_t echo_start = 0, echo_end = 0;
volatile uint8_t capture_complete = 0;
// 微秒级延时函数
void Delay_us(uint32_t us) {
us *= (SYSTEM_CLOCK_FREQ / 1000000) / 5; // 根据系统时钟调整
while(us--) {
__NOP(); // 空操作指令
}
}
// 超声波模块初始化
void HC_SR04_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_InitStruct;
// 开启GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// TRIG引脚配置(输出)
GPIO_InitStruct.GPIO_Pin = TRIG_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(TRIG_GPIO_PORT, &GPIO_InitStruct);
// ECHO引脚配置(输入)
GPIO_InitStruct.GPIO_Pin = ECHO_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(ECHO_GPIO_PORT, &GPIO_InitStruct);
// 开启TIM2时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 定时器配置(1MHz计数频率)
TIM_InitStruct.TIM_Prescaler = (SystemCoreClock / 1000000) - 1; // 1MHz计数
TIM_InitStruct.TIM_Period = 0xFFFF;
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2, &TIM_InitStruct);
TIM_Cmd(TIM2, ENABLE); // 启动定时器
}
// 获取距离(单位:厘米)
float Get_Distance(void) {
// 发送10us触发脉冲
GPIO_SetBits(TRIG_GPIO_PORT, TRIG_GPIO_PIN);
Delay_us(10);
GPIO_ResetBits(TRIG_GPIO_PORT, TRIG_GPIO_PIN);
// 等待ECHO高电平开始
uint32_t timeout = 100000; // 超时计数器
while(!GPIO_ReadInputDataBit(ECHO_GPIO_PORT, ECHO_GPIO_PIN) && timeout--);
if(timeout == 0) return 0.0; // 超时返回0
// 记录高电平开始时间
uint32_t start = TIM_GetCounter(TIM2);
// 等待ECHO高电平结束
timeout = 100000; // 重置超时计数器
while(GPIO_ReadInputDataBit(ECHO_GPIO_PORT, ECHO_GPIO_PIN) && timeout--);
if(timeout == 0) return 0.0; // 超时返回0
// 记录高电平结束时间
uint32_t end = TIM_GetCounter(TIM2);
// 计算高电平持续时间(微秒)
uint32_t duration = (end > start) ? (end - start) : (0xFFFF - start + end);
// 计算距离(声速340m/s = 0.034cm/us)
float distance = (duration * 0.034) / 2; // 往返距离需除以2
return distance;
}
```
#### main.c
```c
#include "main.h"
int main(void) {
// 系统时钟配置
SystemClock_Config();
// 初始化超声波模块
HC_SR04_Init();
while(1) {
// 获取距离
float distance = Get_Distance();
// 此处可添加串口输出或显示代码
// printf("Distance: %.2f cm\r\n", distance);
// 延时500ms
for(int i = 0; i < 500000; i++) __NOP();
}
}
// 系统时钟配置
void SystemClock_Config(void) {
RCC_DeInit();
// 开启外部高速晶振
RCC_HSEConfig(RCC_HSE_ON);
// 等待HSE稳定
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
// 设置PLL参数
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); // 8MHz * 9 = 72MHz
// 开启PLL
RCC_PLLCmd(ENABLE);
// 等待PLL稳定
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
// 设置系统时钟源为PLL
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// 等待系统时钟源切换完成
while(RCC_GetSYSCLKSource() != 0x08);
// 更新SystemCoreClock变量
SystemCoreClockUpdate();
}
// 错误处理函数
void Error_Handler(void) {
while(1) {
// 错误处理代码
}
}
```
### 步骤5:解决文件末尾警告
在文件末尾添加空行解决警告:
```c
// 在HC_SR04.c、main.c等文件末尾添加空行
```
## 常见问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---------|---------|---------|
| 距离测量为0 | 硬件连接错误 | 检查TRIG和ECHO引脚连接 |
| 测量值不稳定 | 环境干扰 | 添加软件滤波算法 |
| 编译通过但无输出 | 串口未配置 | 添加串口初始化代码 |
| 超时错误频繁 | 测量距离过远 | 添加最大距离限制(约4米) |
## 硬件连接建议
```
HC-SR04模块 STM32F10x
---------------------------
VCC → 5V
GND → GND
TRIG → PA0
ECHO → PA1
```
## 性能优化建议
1. **添加中值滤波**:连续采样3-5次,取中间值作为最终结果
2. **温度补偿**:根据环境温度调整声速值
3. **超时处理**:添加更完善的超时检测机制
4. **中断驱动**:使用输入捕获模式提高测量精度
```c
// 中值滤波实现示例
float Get_Filtered_Distance(void) {
float samples[5];
for(int i = 0; i < 5; i++) {
samples[i] = Get_Distance();
Delay_us(10000); // 10ms间隔
}
// 冒泡排序
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4-i; j++) {
if(samples[j] > samples[j+1]) {
float temp = samples[j];
samples[j] = samples[j+1];
samples[j+1] = temp;
}
}
}
return samples[2]; // 返回中值
}
```
## 参考文献
[^1]: STM32库版本差异导致头文件命名变化,需更新为`stm32f10x.h`等标准头文件名称
[^2]: HC-SR04工作原理:发送10μs TTL脉冲触发测量,ECHO高电平时间与距离成正比
[^3]: 声速计算公式:$v = 331.3 + 0.606T$ m/s,其中$T$为摄氏温度
阅读全文
相关推荐




















