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.h 和 system_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 文件夹(包含 inc 和 src)拷贝到 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),命名为 STARTUP、LIBRARY、USER、CMSIS。
    • 往各组添加文件:
      • STARTUP: 添加 startup_stm32f10x_hd.s (汇编启动文件)。
      • FWLB: 添加 Libraries/FWlib/src 下的所有 .c 文件。
      • USER: 添加 User 文件夹下的所有 .c 文件。
      • CMSIS: 添加 core_cm3.c 和 system_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-Link 、J-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。

相关推荐
Zw-awa2 小时前
反馈:让系统知道自己做得对不对
stm32
女神下凡4 小时前
芯参谋(38):NAND_MCP_电路设计指南
arm开发·单片机·嵌入式硬件·设计规范
嵌入式学习菌5 小时前
FreeRTOS 中断管理实战:BASEPRI 寄存器实验
单片机·嵌入式硬件
HRTOS6 小时前
HRTOS:一个名字背后的目标——不断逼近硬实时
经验分享·单片机·系统架构·51单片机
UrSpecial8 小时前
GPIO 是什么?
单片机·嵌入式硬件
剑指offer.9 小时前
ARM裸机开发-SPI
arm开发·嵌入式硬件·嵌入式·arm
修船大队长10 小时前
配置接受报文每个报文对应一个mailbox配置流程记录
网络·单片机·mcu
搁浅小泽12 小时前
二极管选型技术规范
单片机·嵌入式硬件·汽车
搁浅小泽12 小时前
电感选型技术规范
单片机·嵌入式硬件·汽车
..Dauntless..12 小时前
【stm32】串口——在MCU内部的工作过程
stm32·单片机·嵌入式硬件