【STM32】基础知识 第八课 MDK 工程
- 准备工作
- 新建寄存器版本 MDK 工程步骤
- 新建工程文件夹
- 添加文件
- 魔术棒设置
- 绝对路径和相对路径对比
- 测试程序
- 新建 HAL 库版本 MDK 工程
- CMSIS
- HAL 库简介
- Drivers
- Middlewares
- Device 和 Include
- HAL 库文件介绍
- HAL 库 API 函数和比那辆命名规则
- HAL 库对寄存器位操作的相关宏定义
- HAL 库回调函数
- HAL 库使用注意事项
- 新建 HAL 库版本 MDK 工程步骤
准备工作
- 下载相关 STM32Cube 官方固件包 (F1/F4/F7/H7), ST 官网搜索 STM32Cube
- 搭建开发环境
新建寄存器版本 MDK 工程步骤
- 新建工程文件夹
- 新建一个工程框架
- 添加文件
- 魔术棒设置
- 添加 main.c, 并编写代码
新建工程文件夹
在桌面新建一个工程根目录文件夹, 并在该文件夹里新建 D/M/O/P/U 文件夹.
文件名称 | 作用 |
---|---|
Drivers | 存放与硬件相关的驱动层文件 |
Middlewares | 存放正点原子提供的中间层组文件和第三方中间层文件 |
Output | 存放工程编译输出文件 |
Projects | 存放 MDK 工程文件 |
User | 存放 HAL 库用户配置文件, main.c, 中断处理文件, 以及分散加载文件 |
Drivers 文件夹
文件夹名称 | 作用 |
---|---|
BSP | 存放开发板板级支持包驱动代码, 如各种外设驱动 |
CMSIS | 存放 CMSIS 底层代码, 如启动文件 (.s 文件) 等 |
SYSTEM | 存放正点原子系统核心驱动代码, 如 sys.c, delay.c 和 usart.c 等 |
Middlewares 文件夹:
该文件夹用来存放中间层代码 (组件 / Lib 等). 比如: USMART, MALLOC, TEXT, FATFS, USB, LWIP, 各种 OS, 各种 GUI 等.
Output 文件夹:
该文件夹用于存放编译工程输出的中间文件, 比如: .hex, .bin, .o 文件等.
Projects 文件夹:
该文件夹用于存放编译器 (MDK, IAR 等) 工程文件, 我们主要用 MDK, 为了方便区分, 我们在该文件夹下新建: MDK-ARM 文件夹, 用于存放 MDK 的工程文件.
User 文件夹:
该文件夹用于存放用户编写的代码, 如: main.c 等.
添加文件
添加文件步骤:
- 设置工程名和分组名
- 添加启动文件
- 添加 SYSTEM 源码
工程名: Template
分组名: Startup, User, Drivers/SYSTEM, Readme
魔术棒设置
魔术棒设置:
- Target 选项卡: 设置使用的编译器版本, 外部晶振频率
- Output 选项卡: 设置 Objects 输出文件 , 生成 .hex 文件, 输出浏览信息
- Listing 选项卡: 设置 Listing 输出文件夹
- C/C++ 选项卡: 设置全局宏定义, 优化等级, C99 Mode, 设置头文件包含路径
- Debug 选项卡: 设置使用的仿真器类型, 选择的下载接口等
- Utilities 选项卡: 设置下载功能, 下载算法, 下载算法起始地址和大小等
- Linker 选项卡 (可选): 添加分散加载文件 (北极星 / MiniPro H750)
AC5 和 AC6 编译器对比
对比项 | AC5 | AC6 | 说明 |
---|---|---|---|
中文支持 | 较好 | 较差 | AC6 对中文支持极差, goto definition 无法使用, 误报等 |
代码兼容性 | 较好 | 交差 | AC6 对某些代码优化可能导致运行异常, 需慢慢调试 |
编译速度 | 较慢 | 较快 | AC6 编译速度比 AC5 快 |
语法检查 | 一般 | 严格 | AC6 语法检查非常严格, 代码严谨性较好 |
绝对路径和相对路径对比
绝对路径是指目录下的绝对位置, 直接到达目标位置, 通常是从盘符开始的路径. 相对路径就是指由某个文件所在的路径引起的跟其它文件 (或文件夹)的路径关系.
对于相对路径, 大家记住 3 点:
- 默认路径就是指 MDK 工程所在路径, 即 .uvprojx 文件所在路径 (文件夹)
./
表示当前目录 (相对当前路径, 也可以写做.\
)../
表示当前目录的上一层目录 (也可以写做..\
)
测试程序
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
int main(void)
{
uint8_t t = 0;
sys_stm32_clock_init(9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(72, 115200); /* 串口初始化 */
while (1)
{
printf("t:%d\r\n", t);
delay_ms(500);
t++;
}
}
编译:
assembling startup_stm32f103xe.s...
compiling delay.c...
compiling usart.c...
compiling sys.c...
linking...
Program Size: Code=1924 RO-data=336 RW-data=4 ZI-data=1412
FromELF: creating hex file...
"..\..\Output\atk_f103.axf" - 0 Error(s), 0 Warning(s).
Build Time Elapsed: 00:00:01
新建 HAL 库版本 MDK 工程
CMSIS
CMSIS (Cortex Microcontroller Software Interface Standard), 微控制器软件接口标准, 是由 ARM 和与其合作的芯片厂商, 软件工具厂商, 共同指定的标准.
HAL 库简介
ST 为了方便用户开发 STM32 芯片开发提供了三种库:
- 标准外设库 (Standard Peripheral Libraries)
- HAL 库 (硬件抽象层): Hardware Abstraction Layer
- LL 库: Lower Layer
对比:
- 直接操作寄存器: 执行效率高, 时间成本高
- 标准库: F0/F1/F2/F3/F4/L1, 目前已停止维护
- HAL 库: 全系列兼容, ST 目前主推的库, 兼容性, 易移植性
- LL 库: 全系列兼容, 与 HAL 库绑发布, 轻量级, 效率高, 不匹配部分复杂外设
Drivers
文件夹名称 | 作用 |
---|---|
BSP | 板级支持包, 用于适配 ST 官方的开发板 (可参考) |
CMSIS | 符合 CMSIS 的组件, 包括: DSP 库, Cortex-M 内核及其设备文件, 微控制专用头文件, 启动文件, 专用系统文件等 |
STM32F1xx_HAL_Driver | HAL 库外设驱动源码, 包括 F1 系列 HAL 库源文件和头文件 |
Middlewares
文件夹名称 | 文件 | 作用 |
---|---|---|
ST | STemWin | StemWin 工具包 |
ST | STM32_USB_Device_Library | USB 从机设备支持包 |
ST | STM32_USB_Host_Library | USB 主设备支持包 |
Third_Party | FatFs | FAT 文件系统支持包 |
Third_Party | FreeRTOS | FreeRTOS 实时系统支持包 |
Third_Party | LwIP | LwIP 网络通信协议支持包 |
Device 和 Include
文件名称 | 描述 |
---|---|
stm32f1xx.h | 是所有 F1 系列的顶层头文件, 通过条件编译来包含某个芯片的头文件, 定义通用的枚举类型, 定义通用的宏定义 |
stm32f103xe.h | 包含: 中断编号定义, 外设寄存器结构体类型定义, 寄存器映射, 寄存器位定义, 外设判定 |
system_stm32f1xx.c system_stm32f1xx.h | 定义了系统初始化函数 Systemlnit 和系统时钟更新函数 SystemCoreClockUpdate |
startup_stm32f103xe.s | 大容量 F103 系芯片的启动文件 |
HAL 库文件介绍
文件 | 描述 |
---|---|
stm32f1xx_hal.c stm32f1xx_hal.h | HAL 库初始化, 系统滴答, HAL 库延时等相关函数 |
stm32f1xx_hal_conf.h | HAL 库的用户配置文件, 系统滴答, HAL 库延时等相关函数 |
stm32hxx_hal_def.h | 包含 HAL 库通用的枚举类型数据和宏定义 |
stm32fxx_hal_cortex.h | 内核通用函数定义和声明, 如 NVIC, MPU, 系统软复位, Systick 等, 其实主要是对 core_cm3.h 文件的相关函数再次封装 |
stm32f1xx_hal_ppp.c stm32f1xx_hal_ppp.h | 某任意外设驱动源码, PPP 表示任意外设 |
stm32f1xx_hal_ppp_ex.c stm32f1xx_hal_ppp_ex.h | 主要是存放外设的扩展 (特殊) 功能的驱动源码, PPP 表示任意外设 |
stm32f1xx_ll_ppp.c stm32f1xx_ll_ppp.h | LL 库驱动源码, 在部分 STM32F1xx_hal_ppp.c 或 stm32f1xx_hal_ppp_ex.c 中会被调用 |
HAL 库 API 函数和比那辆命名规则
文件名 | stm32f1xx_hal_ppp.(c/h) | stm32发xx_hal_ppp_ex.(c/h) |
---|---|---|
函数名 | HAL_PPP_Function | HAL_PPPx_Function |
外设句柄 | PPP_HandleTypeDef | 无 |
外设工作参数 初始化结构体 | PPP_InitTypeDef | PPP_InitTypeDef |
配置参数结构体 | PPP_YyyyConfTypeDef | PPP_YyyyConfTypeDef |
- 初始化 / 反初始化函数:
HAL_PPP_Init()
,HAP_PPP_DeInit()
- 外设读写函数:
HAL_PPP_Read()
,HAL_PPP_Write()
,HAL_PPP_Receive()
- 控制函数:
HAL_PPP_Set()
,HAL_PPP_Get()
- 状态和错误:
HAL_PPP_GetState()
,HAL_PPP_GetError()
HAL 库对寄存器位操作的相关宏定义
宏定义结构 | 用途 |
---|---|
__HAL_PPP_ENABLE_IT(__HANDLE__,__INTERRUPT__) | 使能外设中断 |
__HAL_PPP_DISABLE_IT(__HANDLE__,___INTERRUPT__) | 禁用外设中断 |
__HAL_PPP_GET_IT(__HANDLE__,__INTERRUPT__) | 获取外设某一中断源 |
__HAL_PPP_CLEAR_IT(__HANDLE__,__INTERRUPT__) | 清除外设中断 |
__HAL_PPP_GET_FLAG(__HANDLE__,__INTERRUPT__) | 获取外设的状态标记 |
__HAL__PPP_CLEAR_FLAG(__HANDLE__,__FLAG__) | 获取外设的状态标记 |
__HAL_PPP_ENABLE(__HANDLE__) | 开启某一外设 |
__HAL_PPP_DISABLE(__HANDLE__) | 禁用某一外设 |
__HAL_PPP_XXXX(__HANDLE__,__PARAM___) | 针对外设的特殊操作 |
__HAL__PPP_GET_IT_SOURCE(__HANDLE__,__INTERRUPT__) | 检查外设的中断源 |
HAL 库回调函数
回调函数 | 举例 |
---|---|
HAL_PPP_MspInit() / _DeInit() | 举例: HAL_USART_MspInit() 会被 HAL_PPP_Init() 函数调用, 该函数主要用于存放外设使用到的 GPIO, CLOCK, NVIC, DMA 等初始化代码 |
HAL_PPP_ProcessCpltCallback | 举例: HAL_USART_TxCpltCallback 由外设中断或 DMA 中断调用, HAL 库中断公共处理函数已经实现对中断标记位读取, 判断和清除操作, 用户只需要专注于中断逻辑功能的实现即可 |
HAL_PPP_ErrorCallback | 举例: HAL_USART_ErrorCallback 外设或 DMA 中断发生的错误, 用于发生错误处理 |
HAL 库使用注意事项
- 使用 HAL 库出现问题, 还是得通过参考手册检查硬件操作是否有问题
- 尽量不通过修改库源码实现功能, 这样不方便库更新
- HAL 库可能会存在错误, 要有质疑精神
- 有些 HAL 库 API 函数执行效率偏低, 我们可能会直接通过操作寄存器的方式代替
新建 HAL 库版本 MDK 工程步骤
出处: 笔记摘自正点原子