一、新建工程前的准备工作
二、新建寄存器版本MDK工程步骤
三、下载验证
四、总结
STM32Cube官网
路径:战舰 V4资料:资料→8,STM32 参考资料→1,STM32CubeXX固件包
请参考 搭建开发环境
这是一个典型的STM32工程的目录结构,按照这样的结构可以更好地组织项目文件,使得代码清晰有序,方便团队协作和后期维护。这样的划分主要是基于不同类型的文件和功能进行分类。一般来说:
Drivers
文件夹存放芯片厂商提供的驱动文件,这里可能包括 STM32 提供的 HAL 库、LL 库等。Middlewares
文件夹存放一些中间件组件,这可能包括正点原子提供的中间层组件,或者其他第三方中间件。Output
文件夹用于存放编译输出的文件,比如生成的可执行文件、库文件等。Projects
文件夹是专门用于存放MDK工程文件的,这样可以将不同类型的文件分开,方便维护。User
文件夹通常存放用户自定义的文件,包括 main.c
主程序文件、中断处理文件等。这样的结构在大型嵌入式项目中是比较常见的,有助于保持项目的整洁和有序。
在 Drivers
文件夹中,你进一步细分了一些子文件夹,这是一个更加详细和模块化的组织结构。这种方式可以更好地根据功能和层次关系来组织代码。
BSP
(Board Support Package)文件夹存放开发板的板级支持包,其中包括各种外设的驱动代码。这个文件夹可能包含与具体硬件平台相关的代码,如GPIO、UART、SPI等外设的初始化和操作。
CMSIS
文件夹存放 Cortex Microcontroller Software Interface Standard (CMSIS) 库的底层代码,比如启动文件(startup 文件,通常是.s文件),这是与 Cortex-M 内核相关的一些底层代码。
SYSTEM
文件夹存放正点原子提供的系统级核心驱动代码,包括一些通用的系统级功能,比如延时(delay)函数、系统初始化等。
这种结构更具有模块化的特点,使得不同功能和层次的代码能够被更清晰地管理和维护。
列出了一些新建工程框架的基本步骤和文件夹结构,这些步骤主要针对 Keil μVision 软件进行 STM32 工程的创建。
下面是详细的步骤来新建一个 STM32 工程。这里以 Keil μVision 为例:
新建工程:
选择主控型号:
配置目标选项:
添加源文件:
配置系统文件和驱动文件:
构建工程:
下载和调试:
这就是一个基本的 STM32 工程的创建和配置流程。具体的步骤可能会有细微差别,具体取决于你使用的工具链和硬件。
编译过程产生的链接列表、调试信息、预览、lib 等文件,统称为中间文件。为了统一管理,方便使用,我们会把输出在 Listings 和 Objects 文件夹的内容,统一改为输出到 Output 文件夹(通过魔术棒设置),我们先把 MDK 自动生成的这两个文件夹(Listings 和 Objects)删除。
启动文件存放在 STM32CubeF1 软件包的:Drivers→CMSIS→Device→ST→STM32F1xx→Source→Templates→arm 文件夹下。因为我们开发板使用的是 STM32F103ZET6,对应的启动文件为:startup_stm32f103xe.s,为了节省空间,在精简版 CMSIS 文件夹里面我们把其他启动文件都删了。
而且,为了更好的匹配寄存器版本代码,我们对 startup_stm32f103xe.s 做了 2 处修改:
1,我们用不到编译器的内存管理函数,为节省内存,将 Heap_Size 改成 0,源码如下:
;未用到编译器自带的内存管理(malloc,free 等),设置 Heap_Szie 为 0
Heap_Size EQU 0x00000000
2,寄存器代码不需要调用 SystemInit 函数,因此修改 Reset_Handler 函数,去掉 SystemInit
调用,源码如下:
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
; 寄存器版本代码,注释掉 SystemInit 的调用
; HAL 库版本代码,建议加上这里(提供 SystemInit 函数),以初始化 stm32 时钟等。
; IMPORT SystemInit
; LDR R0, =SystemInit
; BLX R0
LDR R0, =__main
BX R0
ENDP
最后,我们如果使用 AC6 编译器,则在图 6.1.4.4 的 Misc Controls 处需要设置:-Wnoinvalid-source-encoding,避免中文编码报错,如果使用 AC5 编译器,则不需要该设置!!
绝对路径和相对路径是计算机领域中用于指定文件或目录位置的两种不同方式。
C:\Users\YourUsername\Documents\Project\file.txt
(Windows 系统)./folder/file.txt
表示当前目录下的 folder
目录中的 file.txt
。../parentfolder/file.txt
表示当前目录的上一级目录中的 parentfolder
目录中的 file.txt
。\
,而在 Unix/Linux 使用 /
。在 MDK 工程中,相对路径通常指的是相对于工程文件(.uvprojx
文件)所在的目录。
以下是添加分散加载文件的一般步骤:
打开 Keil MDK 工程。
在工程管理器中,找到 “Project” 菜单,然后选择 “Options for Target”。
在弹出的对话框中,选择 “Linker” 选项卡。
在 “Scatter File” 一栏中,可以选择 “Browse” 按钮,或者手动输入分散加载文件的路径。
如果选择 “Browse”,会弹出一个文件选择对话框,你可以在其中选择分散加载文件。
如果手动输入路径,确保路径是相对于工程文件的相对路径或者是绝对路径。
选择完分散加载文件后,点击 “OK” 保存设置。
最后,点击 “Rebuild” 或 “Build” 来重新构建工程,使得新的链接设置生效。
分散加载文件(Scatter File)通常以 .sct
或 .ld
为扩展名。在这个文件中,你可以定义存储器区域(Memory Regions)、存储器块(Memory Blocks)等,从而确定程序的存储布局。
在 Keil MDK 中使用分散加载文件可以更灵活地控制代码和数据的存放位置,适应不同的硬件平台和应用需求。
分散加载文件(Scatter File) 在 寄存器版本和使用 HAL 库版本的工程中可能会有一些差异。这主要是因为这两种工程的初始化和存储器布局可能不同。
在使用寄存器版本的工程中,你可能会直接定义存储器区域(Memory Regions)和存储器块(Memory Blocks),以明确指定程序在存储器中的布局。例如,在 Cortex-M系列微控制器的寄存器版本工程中,你可以使用类似如下的分散加载文件:
LR_IROM1 0x08000000 0x00100000 { ; load region size_region
ER_IROM1 0x08000000 0x00100000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00020000 { ; RW data
.ANY (+RW +ZI)
}
}
上述代码定义了加载的Flash存储器区域和RAM存储器区域。
而在使用 HAL 库版本的工程中,HAL 库会提供一个包含了初始化过程的 SystemInit 函数,通常会配置系统时钟等。因此,在分散加载文件中,可能需要调用 SystemInit 函数。这样的文件可能包含以下内容:
LR_IROM1 0x08000000 0x00100000 { ; load region size_region
ER_IROM1 0x08000000 0x00100000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00020000 { ; RW data
.ANY (+RW +ZI)
}
}
; Include HAL-specific sections
INCLUDE STM32F1xx_HAL_CORTEX.S
INCLUDE STM32F1xx_HAL_FLASH.S
INCLUDE STM32F1xx_HAL_RCC.S
; ... include other HAL sections as needed
在上述的例子中,STM32F1xx_HAL_CORTEX.S
,STM32F1xx_HAL_FLASH.S
,STM32F1xx_HAL_RCC.S
是 HAL 库提供的特定部分,用于初始化 Cortex 内核、Flash 存储器和系统时钟等。
总的来说,根据工程的具体需求和使用的库,分散加载文件的内容可能会有所不同。