2. STM32 HAL库MDK工程模板创建
工程结构参考引用自正点原子
1. 新建工程文件夹
新建一个工程目录,在里边创建一下子目录
2. 目录说明
文件夹 | 说明 |
---|---|
Drivers | 存放与硬件相关的驱动层文件 |
Middlewares | 存放中间层文件 |
Output | 存放工程编译输出文件 |
Projects | 存放 MDK工程文件 |
User | 存放 HAL库用户配置文件、main.c、中断处理文件,以及分散加载文件 |
2.1 Drivers文件夹
文件夹 | 作用 |
---|---|
BSP | 存放开发板板级支持包驱动代码,如各种外设驱动 |
CMSIS | 存放 CMSIS 底层代码,如启动文件(.s 文件)等 |
SYSTEM | 存放系统级核心驱动代码,如 sys.c、delay.c 和 usart.c 等 |
STM32F1xx_HAL_Driver | 存放 ST 提供的 F1 系列 HAL 库驱动源码 |
2.2 Middlewares文件夹
这个文件夹主要存放的是中间层代码(组件/Lib 等),比如:FATFS、USB、LWIP、FreeRTOS,各种 GUI 等等。但作为模板工程,文件夹暂时空置即可。
2.3 Output文件夹
该文件夹用于存放编译器编译工程输出的中间文件,比如:.hex、.bin、.o 文件等。
2.4 Projects文件夹
该文件夹用于存放编译器(MDK、 IAR 等)工程文件,我们主要用 MDK,为了方便区分,在该文件夹下新建: MDK-ARM 文件夹,用于存放 MDK 的工程文件。
2.5 User文件夹
该文件夹用于存放用户编写的代码,如:HAL 库用户配置文件、main.c 文件、中断处理文件,以及分散加载文件等。
3. 工程框架配置
3.1 新建工程
打开keil, 新建工程
3.2 选择芯片
需要提前安装对应的固件包,可以参考:https://blog.csdn.net/qq_51355375/article/details/143273553
本模板使用的时stm32f103c8t6,选择如下, 选定后点ok
跳过即可
3.3 删除文件夹
因为定义了Output文件夹用于存放编译器编译工程输出的中间文件, 所以删除Listings和Objects两个文件夹
4. 添加文件
4.1 复制HAL 库驱动代码
使用stm32CubeMX 下载固件包
选择需要的版本, 这里选历史版本1.8
等待下载完成后,查看下载目录
去对应的目录下找对应固件驱动包
复制STM32Cube_FW_F1_V1.8.0\Drivers\STM32F1xx_HAL_Driver下的Inc和Src目录到我们自己的Drivers\STM32F1xx_HAL_Driver下
4.2 HAL 库用户配置文件和中断处理文件到我们的 User 文件夹
从官方STM32Cube_FW_F1_V1.8.0\Projects\STM3210E_EVAL\Templates 下的Inc 和 Src 文件夹里面,在这两个文件夹里面找到:stm32f4xx_it.c、stm32f4xx_it.h、stm32f4xx_hal_conf.h 这三个文件,并且拷贝到我们的 User 文件夹下。
4.3 设置工程名和分组名
在 Project→Target 上右键,选择 Manage Project Items…进入工程管理界面
设置工程名字为:Template,并设置四个分组:
Startup(存放启动文件)、User(存放 main.c 等用户代码)、Drivers/SYSTEM(存放系统级驱
动代码)Driver/STM32F1xx_HAL_Driver(存放 HAL 库代码)、Readme(存放工程说明文件),
设置好之后,我们点击 OK,回到 MDK 主界面,可以看到我们设置的工程名和分组名如图
这里我们只是新建了一个简单的工程,并没有添加 BSP、Middlewares 等分组,后面随着工
程复杂程度的增加,我们需要一步步添加对应的分组。为了让工程结构清晰,尽量让 MDK 的工程分组和我们前面新建的工程文件夹对应起来,由于 MDK 分组不支持多级目录,因此我们将路径也带入分组命名里面,以便区分。如:User 分组对应 User 文件夹里面的源码,Drivers/SYSTEM 分组,对应 Drivers/SYSTEM文件夹里面的源码,Drivers/BSP 分组对应 Drivers/BSP 文件夹里面的源码等。
4.4 添加启动文件
复制CMSIS 文件夹
复制上边cubeMx下载的官方包里STM32Cube_FW_F1_V1.8.0\Drivers下的CMSIS 文件夹 下的所有内容到我们自己的工程模板下的Drivers\CMSIS文件夹
由于固件包里面的 CMISIS 兼容了太多芯片,导致非常大, 需要根据实际情况,对其进行了大幅精简
,最简单做法是只保留Device和Include目录,也可以不精简
右键打开项目管理
在刚才添加的\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\arm目录下找到对应的启动文件。
点Add 后如下则添加成功
点击ok后工程目录变化
4.5 添加 SYSTEM 源码
这里使用的文件直接是复制原子的工程中的
同样操作如上,添加三个目录下的源文件到SYSTEM分组即可
4.6 添加USER分组
同样操作如上,将Users目录下的源文件到Users分组即可
4.7 添加驱动添加驱动文件
同样如上操作,将Drivers\STM32F1xx_HAL_Driver\Src 目录下的文件添加到对应分组,可以添加全部或者只添加对应的。
5. 魔术棒设置
5…1 Target选项卡
5.2 Output
5.3 Listing选项卡
经过 Output 和 Listing 这两步设置,原来存储在 Objects 和 Listings 文件夹的内容(中间文
件)就都改为输出到 Output 文件夹
5.4 C/C++选项卡
下图 define 中间定义用英文逗号分隔
引用原子的相对路径解释:
上图中我们设置了 6 个头文件包含路径,其中 3 个在 Drivers 文件夹下,一个在 User 文件
夹下,一个在 Middlewares 文件夹下。为避免频繁设置头文件包含路径,正点原子最新源码的
include 全部使用相对路径,也就是我们只需要在头文件包含路径里面指定一个文件夹,那么该
文件夹下的其他文件夹里面的源码,如果全部是使用相对路径,则无需再设置头文件包含路径
了,直接在 include 里面就指明了头文件所在。
关于相对路径,这里大家记住 3 点:
1,默认路径就是指 MDK 工程所在的路径,即.uvprojx 文件所在路径(文件夹)
2,“./”表示当前目录(相对当前路径,也可以写做“.\”)
3,“../”表示当前目录的上一层目录(也可以写做“..\”)
再举个例子,在完成上图所示的头文件包含路径设置以后,我们在代码里面编写:
#include "./SYSTEM/sys/sys.h"
即表示当前头文件包含路径所指示的 4 个文件夹里面,肯定有某一个文件夹包含了:
SYSTEM/sys/sys.h 的路径,实际上就是在 Drivers 文件夹下面,两者结合起来就相当于:
#include "../../Drivers/SYSTEM/sys/sys.h"
这就是相对路径。它既可以减少头文件包含路径设置(即减少 MDK 配置步骤,免去频繁
设置头文件包含路径的麻烦),同时又可以很方便的知道头文件具体在那个文件夹,因此我们推
荐在编写代码的时候使用相对路径。
5.5 设置 Debug 选项卡
5.6 设置 Utilities 选项卡
6. 添加 main.c,并编写代码
在 MDK 主界面,右键选择Users分组, 添加新项目到分组
点Add添加后,打开项目管理发现main.c也已经新建并加入了分组
编写测试代码:
#include "SYSTEM/sys/sys.h"
#include "SYSTEM/uart1/uart1.h"
#include "SYSTEM/delay/delay.h"
#define LED_CLK() __HAL_RCC_GPIOB_CLK_ENABLE()
#define LED_GPIO GPIOB
#define LED_PIN GPIO_PIN_8
void led_init(void); /* LED初始化函数声明 */
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* LED初始化 */
uart1_init(115200);
printf("running...\r\n");
while(1)
{
HAL_GPIO_WritePin(LED_GPIO,LED_PIN,GPIO_PIN_SET);
delay_ms(500);
HAL_GPIO_WritePin(LED_GPIO,LED_PIN,GPIO_PIN_RESET);
delay_ms(500);
}
}
/**
* @brief 初始化LED相关IO口, 并使能时钟
* @param 无
* @retval 无
*/
void led_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
LED_CLK(); /* IO口时钟使能 */
gpio_initstruct.Pin = LED_PIN; /* LED0引脚 */
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_initstruct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(LED_GPIO, &gpio_initstruct); /* 初始化LED0引脚 */
}
注意: 这里要注意头文件的引入方式
修改代码:
编译下载验证:
出现错误
移除这三个
报错:
需要将: Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates 下的 system_stm32f1xx.c 添加到Users分组下, 右键Users分组,添加到已存在分组
再次编译: