STM32 LL 库使用指南
---By Fengzi
熟悉 STM32 的都知道 ST 官方提供了非常方便好用的库函数供用户使用,多数人都使用
过 STM32 标准外设库,STM32Cube 库(即 HAL 库),这个 LL 库是什么鬼,却从来没听说过。
好吧,我承认这个名字是我自己 XJB 取的。。。。。。。。
目录
一、 初识 LL 库 ......................................................................................................... 1
二、 怎么使用 LL 库 .................................................................................................. 3
三、 新建 STM32LL 库工程模板 ................................................................................ 5
四、 第一个程序——点亮 LED .................................................................................. 8
五、 添加其他程序功能 .......................................................................................... 10
………………………………………………………………………………………………………………………………………………….
一、 初识 LL 库
最近论坛发的 STM32L476RG Nucleo 开发板到手了,准备学习玩耍,当然第一步就是下
载资料,于是我下载 STM32L4Cube 1.1.0 版本,打开逐个查看,
好像和以前一样的,没什么特别嘛,于是准备开始开发。。。
等等,好像还真发现了有点不一样:
熟悉 HAL 库的都知道,该库的文件几乎都是以 stm32xxx_hal_xxx.h/.c 命名的,为了和以
前的标准库有个区分,上图中那些是什么鬼?????
前辈说,遇到问题赶紧查手册,于是我果断打开 STM32L4Cube 库的说明手册(UM1884):
原来这个东西叫做 Low Layer APIs,作为英文渣渣表示实在不习惯洋里洋气的高大上名
字,于是擅自把他叫做【STM32LL 库】了(不服的你咬我啊)。
从这里看好像是说这个东东比 HAL 库更接近硬件,到底什么鬼,还不清楚。但是以前
好像没见过这个东西啊,就算是 STM32L4Cube 的 1.0.0 版本中都没有。看看 Cube 发行历史:
原来 LL 库是在 1.1.0 版本才加上的,大概意思就是:
1.
2.
3.
LL APIs 是寄存器级的编程,嗯,也就是说我们常说的直接操作寄存器吧。
LL APIs 适用于 xxx 等一大堆外设
LL APIs 函数全部定义为 static inline 函数,放在对应的头文件中,用户使用需
要包含相关头文件
4. 参考这两个文档
看看 LL 库文件在 Cube 库中的位置,有 20 多个文件,全部以 stm32l4xx_ll_xxx.h 命
名:
STM32Cube_FW_L4_V1.1.0\Drivers\STM32L4xx_HAL_Driver\Inc
STM32L4 是面向低功耗市场的,同时不失高性能,功耗和性能往往是两个矛盾的东西,
ST 在硬件设计上想了各种办法来实现兼顾低功耗高性能(例如各种低功耗模式,LP 外设等),
而在软件层面,程序也讲求效率, LL 库全是直接操作寄存器,直接操作寄存器往往效率较
高,而且函数定义为内联函数,调用函数时不是堆栈调用,而是直接把函数的代码嵌入到调
用的地方,利于提高代码相率,我想这也是 ST 在 STM32L4 系列中推出这个直接操作寄存器
的 LL 库的原因之一吧。
二、 怎么使用 LL 库
先看看手册里怎么说的,它有什么特点:
英文渣渣就不翻译了,反正大概就是说
LL 库更接近硬件层,对需要复杂上层协议栈的外设不适用,直接操作寄存器等等一大
堆,到这里,可以看到它的使用方法:
1. 独立使用,该库完全独立实现,可以完全抛开 HAL 库,只用 LL 库编程完成。
2. 混合使用,和 HAL 库结合使用。
本人就常在编程的时候库函数和寄存器操作混合,所以觉得混合使用应该是不错的
方式。
最后一段还说到该库不需要额外的内存资源来存储程序状态,数据指针等东西,所
有的操作都通过直接修改外设的寄存器来完成。
下面是手册中对各个 LL 文件的描述:
就是讲 LL 库由 5 部分组成:每个外设对应一个头文件组成一部分,以及系统相关的 bus,
cortex,utils,system 四个部分。
前面提到,要使用 LL 库,需要包含对应头文件,各头文件之间有如下关系:
看来,我们编程的时候只需要#include 某外设的头文件,就可以使用 LL 库了,但是同
时,系统启动文件,初始化文件等一系列不能少,具体讲就是:
stm32l4xx.h
stm32l476xx.h
system_stm32l4xx.h
system_stm32l4xx.c
startup_stm32l476xx.s
这几个文件,这在标准库,Cube 库都不曾变过的铁律。
三、 新建 STM32LL 库工程模板
要开发首先要搭建开发环境,也就是简历所谓的工程模板。由于独立使用 LL 库的情况
下不能使用 Cube 来建立工程,所以需要手动建立,这里的建工程方法和以前使用标准库建
工程模板比较类似:
1. 准备相关文件:
新建一个文件夹用来放所有的文件
把需要用到的相关文件全部复制过来:
首先是上一节说到的几个必不可少的文件
stm32l4xx.h,stm32l476xx.h,
system_stm32l4xx.h,system_stm32l4xx.c,
startup_stm32l476xx.s
这些文件都在 STM32Cube_FW_L4_V1.1.0\Drivers\CMSIS\Device\ST\STM32L4xx 文件
夹下,为了方便查找,我保持了和库文件中相同的文件夹结构。如果闲麻烦,可以把
STM32Cube_FW_L4_V1.1.0\Drivers\CMSIS 整个文件夹复制过来,该文件夹下的其他文件
如 Include 文件夹里面的也需要用到。
然后把所有 LL 库的文件复制过来,
STM32Cube_FW_L4_V1.1.0\Drivers\STM32L4xx_HAL_Driver\Inc 文 件 夹 下 面 所 有
stm32l4xx_ll_xxx.h 命名的文件,也可以整个文件夹复制。
其实主要就是这两个文件夹下面相关的一些文件复制过来就好。当然一股脑全部粘
贴过去也没什么影响,就是工程大一点(henduo)。
最后建立 Inc,Src,MDK-ARM 文件夹放头文件、源文件和工程文件,,stm32l4xx_it.h/.c
这两个文件其实也可以不要,因为我们可以把中断函数处理函数放在任何地方都可以,
main.c/main.h 自己新建或者复制个模板。
所有文件,文件夹名字都可以随便取,这里只是为了保持和库、Cube 建立的工程
文件结构保持一致,所以取这些名字。
2. 好了,准备工作做好了,开始建工程
打开 Keil MDK,新建一个工程选择型号 STM32L4RG,在此之前需要确保已经安装了 Keil
STM32L4 的 Pack,不然新建工程的时候找不到对应的型号。
然后往工程里添加刚刚准备好的相关文件:
只需添加*.c 和*.s 文件,*.h 文件设置头文件包含路径就行,也可以加到工程中方便查
看。
接下来就是最重要的部分,工程设置:
有几个主要地方需要设置,
1. 定义使用的芯片型号 STM32L4xx
2. 设置文件包含路径
..\Inc
//自己写的头文件路径
..\Drivers\CMSIS\Include
..\Drivers\CMSIS\Device\ST\STM32L4xx\Include
..\Drivers\STM32L4xx_HAL_Driver\Inc
//关于 Cortex 的一些头文件
// stm32l4xx.h,stm32l476xx.h 等文件
//LL 库文件的路径
3. 设置所用调试仿真器,使用 Nucleo 板载 ST-Link
4.
差不多就这些了,如果芯片型号选择正确,pack 安装正确,其他的工程已经默认设置
好,编译一下无错误无警告,下面就是真正的开发,写代码了。
四、 第一个程序——点亮 LED
首先点亮 LED 来验证下工程设置,代码编写是否正确。