STM32标准工程目录文件解释

文章目录

    • [1. Project (工程文件目录)](#1. Project (工程文件目录))
    • [2. Libraries (固件库目录)](#2. Libraries (固件库目录))
    • [3. User (用户代码目录)](#3. User (用户代码目录))
    • [4. Output (输出结果目录)](#4. Output (输出结果目录))
    • [5. Listing (列表清单目录)](#5. Listing (列表清单目录))
    • 手动搭建
    • 常见错误

野火(FireBull)以及大多数基于 Keil MVD 环境的 STM32 教程,采用这种文件夹结构主要是为了 实现"工程模块化" 。这种分类方式能让代码、库文件和编译生成物互不干扰,方便移植和维护。

以下是各个文件夹及其内部核心文件的详细作用说明:


1. Project (工程文件目录)

这是整个工程的"大本营",存放的是与 Keil 软件本身相关的文件。

  • 作用:保存工程的配置信息,如芯片型号、调试器设置、编译选项等。
  • 核心文件
    • *.uvprojx最重要的文件,双击它即可打开整个工程。
    • *.uvoptx:保存你的个人配置(如断点、窗口布局)。
    • *.uvguix.*:保存图形界面设置,删除不影响工程编译。

2. Libraries (固件库目录)

这里存放的是 ST 官方提供的 标准外设库 (Standard Peripherals Library)

  • 作用:提供操作寄存器的函数接口,让你不需要直接背寄存器地址。
  • 包含内容
    • CMSIS:内核支持层。包含 core_cm3.c(内核功能)stm32f10x.hsystem_stm32f10x.c(时钟配置)以及startup文件夹存放启动文件。
      • startup_stm32f10x_hd.s汇编启动文件(非常关键,负责初始化堆栈、向量表并跳转到 main)。
    • FWlib 固件库(FW的单词是Firmware,即固件的意思。)
      • inc 文件夹:存放 .h 头文件(如 stm32f10x_gpio.h)。
      • src 文件夹:存放 .c 源文件(如 stm32f10x_gpio.c)。

3. User (用户代码目录)

这是你编写逻辑代码的地方,也是开发过程中最常改动的文件夹。

  • 作用:存放用户业务逻辑、中断处理函数以及配置文件。
  • 核心文件
    • main.c:程序的入口主函数。
    • stm32f10x_it.c / .h:专门存放中断服务函数(Interrupt Service Routines)。
    • stm32f10x_conf.h:库配置头文件,用于开关各个外设库的编译。
    • 自己写的驱动文件夹,例如bsp文件夹

4. Output (输出结果目录)

这里存放的是编译器(Compiler)和链接器(Linker)运行后生成的二进制数据。

  • 作用:存放编译产生的中间文件和最终可执行文件。
  • 核心文件
    • *.hex / *.bin最终烧录到单片机里的文件
    • *.obj:每个 .c 文件编译后生成的二进制目标文件。
    • *.axf:包含调试信息的文件,仿真调试时需要它。

5. Listing (列表清单目录)

这里存放的是编译过程中的统计信息和辅助说明文件。

  • 作用:用于查看代码占用的内存大小、汇编对照等,方便优化代码。
  • 核心文件
    • *.map非常有用。它详细列出了每个函数占用的 Flash 和 RAM 空间大小,以及堆栈的分配情况。
    • *.lst:C 语言对应的汇编代码清单。

总结对照表

文件夹 属性 修改频率 建议
User 自己的代码 极高 逻辑代码全部放这里
Libraries 官方的库 极低 不要轻易修改里面的源码
Project 环境配置 备份工程时,这个文件夹是核心
Output 自动生成 无需手动修改 空间不够时可以清空,重新编译会生成
Listing 编译报告 仅查看 排查内存溢出(Stack Overflow)时看 map 文件

手动搭建

手动搭建一个标准的野火风格 STM32 工程模板,是深入理解单片机底层逻辑的必经之路。你可以按照以下 5 个核心步骤 进行:


第一步:建立文件夹结构

在电脑硬盘上新建一个工程根文件夹(如 Template),在里面手动创建以下文件夹:

  • Project:存放 Keil 工程文件。
  • Libraries:存放 ST 标准库文件。
  • User:存放用户代码。
  • Output:存放编译生成的中间文件。
  • Listing:存放编译清单文件。

第二步:导入官方库文件 (Libraries)

你需要从 ST 官网或野火提供的资料包中拷贝固件库文件:

  1. 将库中的 CMSIS 文件夹(包含内核支持文件)拷贝到 Libraries
  2. 将库中的 STM32F10x_StdPeriph_Driver 文件夹(包含 incsrc)拷贝到 Libraries并重命名FWlib。
  3. 关键:User 文件夹中放入三个必要文件:
    • main.c (自己新建)
    • stm32f10x_it.c / .h (从库例程中拷贝)
    • stm32f10x_conf.h (从库例程中拷贝,用于配置外设开关)
    • 自己编写的驱动,新建文件夹(例如bsp文件夹)

第三步:在 Keil 中新建工程 (Project)

  1. 打开 Keil5,点击 Project -> New uVision Project ,保存路径选择刚才创建的 Project 文件夹。
  2. 在弹出的设备选择框中,搜索并选择 STM32F103VE
  3. Manage Project Items (三个色块小图标)
    • 在 Project Targets 里新建组(Groups),命名为 STARTUPLIBRARYUSERCMSIS
    • 往各组添加文件:
      • STARTUP: 添加 startup_stm32f10x_hd.s (汇编启动文件)。
      • FWLB: 添加 Libraries/FWlib/src 下的所有 .c 文件。
      • USER: 添加 User 文件夹下的所有 .c 文件。
      • CMSIS: 添加 core_cm3.csystem_stm32f10x.c以及对应的头文件。

第四步:魔术棒 (Options for Target) 核心配置

这是最容易出错的一步,点击"魔术棒"图标进行设置:

  1. Output 选项卡 :点击 Select Folder for Objects,选择你创建的 Output 文件夹。勾选 Create HEX File
  2. Listing 选项卡 :点击 Select Folder for Listings,选择你创建的 Listing 文件夹。
  3. C/C++ 选项卡 (极其重要)
    • Define : 输入 STM32F10X_HD, USE_STDPERIPH_DRIVER(告诉编译器芯片容量和使用标准库)。
    • Include Paths : 点击右侧三个点,把以下路径都添加进去:
      • ..\Libraries\CMSIS
      • ..\Libraries\FWlib\inc
      • ..\User

第五步:编写 main.c 并编译

main.c 中写一个最简单的死循环:

c 复制代码
#include "stm32f10x.h"

int main(void) {
    while(1) {
        // 等待编写 GPIO 控制代码
    }
}

点击 Build (F7) 。如果下方显示 0 Error(s), 0 Warning(s),说明模板搭建成功了!


💡 一个进阶小技巧

User 文件夹里,通常建议再建一个名为 bsp (Board Support Package) 的子文件夹,专门用来放你自己写的驱动(比如 bsp_led.c, bsp_usart.c),这样你的 main.c 会变得非常清爽。

常见错误

这就好比你已经写好了一封信(代码编译成功),但邮递员(下载器)找不到邮筒 ,或者你叫错了邮递员的名字

这个错误的原因非常直接:Keil 默认设置的下载器型号和你手上实际使用的不匹配。

1. 为什么报错?

从图片看,Keil 正在尝试寻找一个叫 ULINK2/ME 的下载器,但它没找到。

  • 野火的 STM32 开发板通常配套的是 DAP-Link (最常见)或者 ST-LinkJ-Link
  • 如果你用的是野火自带的那根彩色排线的下载器,它大概率是 CMSIS-DAP(即 DAP-Link)。

2. 怎么解决?(三步修正法)

第一步:切换正确的下载器类型
  1. 点击"魔术棒"图标(Options for Target)。
  2. 切换到 Debug 选项卡。
  3. 在右上角的下拉框中,把 ULINK2/ME Cortex-M Driver 改选为 CMSIS-DAP Debugger (如果你用的是 DAP-Link)或者 ST-Link Debugger
第二步:确认硬件连接成功
  1. 选好 CMSIS-DAP Debugger 后,点击它旁边的 Settings 按钮。
  2. 在弹出的窗口中,看 SW Device 那个框里是否出现了一串 16 进制的代码和芯片名称(如 0x1BA01477 ARM CoreSight SW-DP)。
    • 如果有:说明电脑识别到了单片机,连接成功。
    • 如果是空白:检查你的下载器和开发板连接线是否插反了,或者开发板是否没上电。
第三步:配置 Flash 下载
  1. 在刚才的 Settings 窗口里,切换到 Flash Download 选项卡。
  2. 勾选 Reset and Run(这样下完程序后它会自动运行,不用你按复位键)。
  3. 点击 OK 退出。

3. 排查小清单

如果改了设置还不行,请检查:

  • USB 线:下载器是否已经插在电脑上,驱动是否安装(通常 DAP-Link 免驱)。
  • 电源:开发板上的电源开关开了吗?
  • 引脚 :下载器的排线是否对应插在了板子的 SWD 接口上?

问题2:

c 复制代码
/* 直接操作寄存器的方法控制IO */
#define	digitalHi(p,i)		 {p->BSRR=i;}	 //输出为高电平		
#define digitalLo(p,i)		 {p->BRR=i;}	 //输出低电平
#define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态

这个对ODR寄存器进行异或操作,无非是如果i是0x20 也就是第6位是1,这里和其进行异或操作,如果通过前面的BSRR寄存器,将第6位设置了高电平,也就是1,这个ODR寄存器第6位也会同步更新吗?BSRR和BRR寄存器对第6位的更改,都会同步更新到ODR吗?

核心逻辑:谁才是真正的"状态持有者"?在 STM32 的 GPIO 硬件电路中,ODR (Output Data Register) 才是那个真正连接到输出驱动器、决定引脚高低的"核心寄存器"。ODR (输出数据寄存器):它是可读可写的。它的每一位直接对应引脚的状态。如果你直接往 ODR 写 1 或 0,引脚电平就变。BSRR / BRR (设置/清除寄存器):它们是只写的。它们更像是 ODR 的"远程遥控器"。当你向 BSRR 的第 n n n 位写 1 时,硬件内部逻辑会触发一个动作,把 ODR 寄存器的第 n n n 位强制设为 1。同理,写 BRR 会把 ODR 对应位强制清 0。

相关推荐
SUNNYSPY00118 小时前
65R135 -ASEMI超结MOS管TO-220封装
单片机
jacklood19 小时前
基于STM32的车载振动曲线摆件创意设计
stm32·单片机·嵌入式硬件
jomoly20 小时前
星闪NL002开发板测评+匆匆
单片机·嵌入式硬件
17(无规则自律)21 小时前
【Linux驱动实战】:标准的按键控制LED驱动写法
linux·驱动开发·嵌入式硬件
森利威尔电子-1 天前
森利威尔SL3180替换LM5013 100V降压3.3V 5V 12V恒压芯片
单片机·嵌入式硬件·集成电路·芯片·电源芯片
Net_Walke1 天前
ESP32开发:5分钟之内添加ST7735驱动构建LVGL模板工程
单片机·物联网·iot
qq_401700411 天前
5V防过压电路
单片机·硬件
小昭在路上……1 天前
AHB和APB总线概念
单片机·嵌入式硬件
学嵌入式的小杨同学1 天前
STM32 进阶封神之路(三十):IIC 通信深度实战 —— 软件模拟 IIC + 光照传感器(BH1750)全解析(底层时序 + 代码落地)
stm32·单片机·嵌入式硬件·mcu·硬件架构·硬件工程·智能硬件
jacklood1 天前
使用STM32的迪文屏控制使用参考方式
前端·javascript·stm32