你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 23973|回复: 77

[STM32L476] 【NUCLEO-L476RG LL库开发】STM32【LL库】开发使用指南

  [复制链接]

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
发表于 2015-11-1 18:58:42 | 显示全部楼层 |阅读模式
本帖最后由 风子 于 2017-2-16 18:00 编辑


熟悉STM32的都知道ST官方提供了非常方便好用的库函数供用户使用,多数人都使用过STM32标准外设库,STM32Cube库(即HAL库),这个LL库是什么鬼,却从来没听说过。

好吧,我承认这个名字是我自己XJB的。。。。。。。。



一、       初识LL

最近论坛发的STM32L476RGNucleo开发板到手了,准备学习玩耍,当然第一步就是下载资料,于是我下载STM32L4Cube 1.1.0版本,打开逐个查看,

image1.png


好像和以前一样的,没什么特别嘛,于是准备开始开发。。。
等等,好像还真发现了有点不一样:


image2.png

熟悉HAL库的都知道,该库的文件几乎都是以stm32xxx_hal_xxx.h/.c命名的,为了和以前的标准库有个区分,上图中那些是什么鬼?????
前辈说,遇到问题赶紧查手册,于是我果断打开STM32L4Cube库的说明手册(UM1884):

image3.png



原来这个东西叫做LowLayer APIs,作为英文渣渣表示实在不习惯洋里洋气的高大上名字,于是擅自把他叫做【STM32LL库】了(不服的你咬我啊)。

从这里看好像是说这个东东比HAL库更接近硬件,到底什么鬼,还不清楚。但是以前好像没见过这个东西啊,就算是STM32L4Cube的1.0.0版本中都没有。看看Cube发行历史:




image4.png


原来LL库是在1.1.0版本才加上的,大概意思就是:
1.          LL APIs是寄存器级的编程,嗯,也就是我们常说的直接操作寄存器吧。
2.          LL APIs适用于xxx等一大堆外设
3.          LL APIs函数全部定义为staticinline函数,放在对应的头文件中,用户使用需要包含相关头文件
4.          参考这两个文档
看看LL库文件在Cube库中的位置,有20多个文件,全部以stm32l4xx_ll_xxx.h命名:
STM32Cube_FW_L4_V1.1.0\Drivers\STM32L4xx_HAL_Driver\Inc

image5.png


STM32L4是面向低功耗市场的,同时不失高性能,功耗和性能往往是两个矛盾的东西,ST在硬件设计上想了各种办法来实现兼顾低功耗高性能(例如各种低功耗模式,LP外设等),而在软件层面,程序也讲求效率, LL库全是直接操作寄存器,直接操作寄存器往往效率较高,而且函数定义为内联函数,调用函数时不是堆栈调用,而是直接把函数的代码嵌入到调用的地方,利于提高代码相率,我想这也是ST在STM32L4系列中推出这个直接操作寄存器的LL库的原因之一吧。


二、       怎么使用LL

先看看手册里怎么说的,它有什么特点:

image6.png


英文渣渣就不翻译了,反正大概就是说
LL库更接近硬件层,对需要复杂上层协议栈的外设不适用,直接操作寄存器等等一大堆,到这里,可以看到它的使用方法:
1.        独立使用,该库完全独立实现,可以完全抛开HAL库,只用LL库编程完成。
2.        混合使用,和HAL库结合使用。
本人就常在编程的时候库函数和寄存器操作混合,所以觉得混合使用应该是不错的方式。
最后一段还说到该库不需要额外的内存资源来存储程序状态,数据指针等东西,所有的操作都通过直接修改外设的寄存器来完成。
下面是手册中对各个LL文件的描述:


image7.png

就是讲LL库由5部分组成:每个外设对应一个头文件组成一部分,以及系统相关的bus,cortex,utils,system四个部分。

前面提到,要使用LL库,需要包含对应头文件,各头文件之间有如下关系:
image8.png

看来,我们编程的时候只需要#include某外设的头文件,就可以使用LL库了,但是同时,系统启动文件,初始化文件等一系列不能少,具体讲就是:

stm32l4xx.h
stm32l476xx.h
system_stm32l4xx.h
system_stm32l4xx.c
startup_stm32l476xx.s

这几个文件,这在标准库,Cube库都不曾变过的铁律。

顺便分享一下STM32L4Cube 库 1.1.0版本和1.1.1版本的Pack 百度网盘下载地址:https://pan.baidu.com/s/1c0wjL5m

一楼二楼是具体使用方法。
已完,上传文档和工程模板:
STM32 LL库使用指南.pdf (847.11 KB, 下载次数: 1025)

评分

参与人数 1ST金币 -1 收起 理由
ccmm520 -1

查看全部评分

回复

使用道具 举报

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
 楼主| 发表于 2015-11-1 18:59:14 | 显示全部楼层
本帖最后由 风子 于 2015-11-2 12:53 编辑

三、      开发环境搭建—— 新建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命名的文件,也可以整个文件夹复制。
image9.png
其实主要就是这两个文件夹下面相关的一些文件复制过来就好。当然一股脑全部粘贴过去也没什么影响,就是工程大一点(henduo)。
最后建立Inc,Src,MDK-ARM文件夹放头文件、源文件和工程文件,,stm32l4xx_it.h/.c这两个文件其实也可以不要,因为我们可以把中断函数处理函数放在任何地方都可以,main.c/main.h自己新建或者复制个模板。
所有文件,文件夹名字都可以随便取,这里只是为了保持和库、Cube建立的工程文件结构保持一致,所以取这些名字。
image10.png
2.        好了,准备工作做好了,开始建工程
打开Keil MDK,新建一个工程选择型号STM32L4RG,在此之前需要确保已经安装了Keil STM32L4的Pack,不然新建工程的时候找不到对应的型号。
image11.png
然后往工程里添加刚刚准备好的相关文件:
image12.png
只需添加*.c和*.s文件,*.h文件设置头文件包含路径就行,也可以加到工程中方便查看。
接下来就是最重要的部分,工程设置:
有几个主要地方需要设置,
1.      定义使用的芯片型号 STM32L4xx
image13.png
2.      设置文件包含路径
..\Inc                                                                                             //自己写的头文件路径
..\Drivers\CMSIS\Include                                                        //关于Cortex的一些头文件
..\Drivers\CMSIS\Device\ST\STM32L4xx\Include            // stm32l4xx.h,stm32l476xx.h等文件
..\Drivers\STM32L4xx_HAL_Driver\Inc                              //LL库文件的路径
image14.png
3.      设置所用调试仿真器,使用Nucleo板载ST-Link
4.      
image15.png
差不多就这些了,如果芯片型号选择正确,pack安装正确,其他的工程已经默认设置好,编译一下无错误无警告,下面就是真正的开发,写代码了。

趁中午休息把开发环境搭建好,晚上回去写两个简单例子,这篇帖子就算是完结了!
回复 支持 反对

使用道具 举报

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
 楼主| 发表于 2015-11-1 18:59:31 | 显示全部楼层
本帖最后由 风子 于 2015-11-2 23:38 编辑

四、      LL库  第一个程序——点亮LED

首先点亮LED来验证下工程设置,代码编写是否正确。

1.        包含头文件
main.c
  1. #include "main.h"
复制代码
main.h
  1. #include "stm32l4xx_ll_bus.h"
  2. #include "stm32l4xx_ll_rcc.h"
  3. #include "stm32l4xx_ll_system.h"
  4. #include "stm32l4xx_ll_utils.h"
  5. #include "stm32l4xx_ll_gpio.h"
  6. #include "stm32l4xx_ll_exti.h"
复制代码

包含需要使用的相关模块,要用那些就包含哪些,不知道用哪几个就全部包含进去。

2.        配置时钟
用这个LL库开发STM32跟用标准外设库很像,很类似,只不过封装层次更低。首先第一步要配置时钟,因为启动文件里没有默认配置,这和STM32F1早期的标准外设库一样,不过较高版本和后来的系列就可以不用了(如果使用默认配置的话),启动文件里默认配置了时钟。怎么配置这里就不细说了,看代码应该都能懂。
  1. __STATIC_INLINE void SystemClock_Config(void)
  2. {
  3.   LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
  4.   
  5.   LL_RCC_HSI_Enable();
  6.   while(LL_RCC_HSI_IsReady() != 1)
  7.   {
  8.   };
  9.   LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_1, 10, LL_RCC_PLLR_DIV_2);
  10.   LL_RCC_PLL_Enable();
  11.   LL_RCC_PLL_EnableDomain_SYS();
  12.   while(LL_RCC_PLL_IsReady() != 1) ;

  13.   LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  14.   LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
  15.   while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) ;
  16.   
  17.   LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
  18.   LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);

  19.   LL_Init1msTick(80000000);

  20.   LL_SetSystemCoreClock(80000000);
  21. }
复制代码

函数声明为__STATIC_INLINE(即staticinline)是因为该库所有函数都是__STATIC_INLINE,前面提到这样做不需要额外的内存,因此这样最是为了保持这一点。


3.        将LED对应引脚PA5配置为推挽输出模式
  1. __STATIC_INLINE void Configure_GPIO(void)
  2. {
  3.   LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);

  4.   LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_OUTPUT);
  5.   LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_5,  LL_GPIO_OUTPUT_PUSHPULL);
  6.   LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_5,  LL_GPIO_SPEED_LOW);
  7.   LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_5,  LL_GPIO_PULL_NO);
  8. }
复制代码

4.        PA5输出高电平,点亮LED
LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_5);
5.        最后需要在主函数中依次调用上诉函数,编译下载运行即可看到Nulceo上的绿色LED被成功点亮了。
  1. int main(void)
  2. {
  3.   SystemClock_Config();
  4.   Configure_GPIO();
  5.   LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_5);
  6.   while (1)
  7.   {        ;
  8.   }
  9. }
复制代码
/*碎碎念:虽然已经不知道这是第几百还是第几千次做点灯实验,依然还是不厌其烦啊,LED不愧是被称为单片机届的”Hello World!”*/

五、       添加其他程序功能

会了第一个程序,其他的就按照手册讲的写就行了,再举个简单的例子,利用按键中断模式来控制LED的闪烁频率。
只说下大概步奏,不详细说明:将按键连接的引脚配置为中断输入模式,开启中断,配置中断线,写中断服务函数来处理中断。
  1. __STATIC_INLINE void Configure_EXTI(void)
  2. {
  3.   LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
  4.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
  5.   LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_13, LL_GPIO_MODE_INPUT);
  6.   LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_13,   LL_GPIO_PULL_NO);
  7.   NVIC_EnableIRQ(EXTI15_10_IRQn);
  8.   NVIC_SetPriority(EXTI15_10_IRQn, 0);
  9.   LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTC, LL_SYSCFG_EXTI_LINE13 );
  10.   LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_13);
  11.   LL_EXTI_EnableFallingTrig_0_31(LL_EXTI_LINE_13);
  12. }
复制代码
在主函数调用Configure_EXTI()并添加代码:
  1.   while (1)
  2.   {
  3.     LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_5);
  4.          if(i == 0)
  5.          {
  6.                    LL_mDelay(100);
  7.          }
  8.          else if(i == 1)
  9.          {
  10.                    LL_mDelay(500);
  11.          }
  12.          else
  13.          {
  14.                    LL_mDelay(1000);
  15.          }
  16.   }
复制代码

实现功能:每按一次按键,LED改变一次闪烁频率,间隔0.1s,0.5s,1s三种不同频率循环闪烁。

最后,这个LL库总体给人感觉是使用方法跟标准外设库很像,但也有不同,前面也有提到,它全是直接操作寄存器,程序效率一定程度上会比较高,但使用起来有时候不一定那么方便,可移植性也不好,所以把它和HAL库结合起来使用是最好的方式,在程序要求效率的地方就可以使用这些函数,而其他地方使用HAL库,这也是我们常常使用的方法,只不过以前是使用HAL库,需要的地方我们自己直接写操作寄存器,而现在可以换成使用这个【LL库】了。
回复 支持 反对

使用道具 举报

0

主题

14

回帖

0

蝴蝶豆

初级会员

最后登录
2019-9-5
发表于 2015-12-24 23:28:32 | 显示全部楼层
上个IAR工程模板 stm32L476.rar (3.5 MB, 下载次数: 417)
回复 支持 反对

使用道具 举报

107

主题

812

回帖

5

蝴蝶豆

论坛元老

最后登录
2019-8-28
发表于 2015-11-1 19:57:49 | 显示全部楼层
哈哈,正在看,这个应该是专为低功耗设计的吧
回复 支持 反对

使用道具 举报

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
 楼主| 发表于 2015-11-1 20:06:37 | 显示全部楼层
netlhx 发表于 2015-11-1 19:57
哈哈,正在看,这个应该是专为低功耗设计的吧

我猜也是,帖子里也提了下,提高程序效率,更好地掌控功耗
回复 支持 反对

使用道具 举报

77

主题

1927

回帖

5

蝴蝶豆

论坛元老

最后登录
2020-11-18
发表于 2015-11-1 20:42:43 | 显示全部楼层
赞一个
回复 支持 反对

使用道具 举报

47

主题

3404

回帖

30

蝴蝶豆

版主

最后登录
2020-12-7
发表于 2015-11-1 20:50:28 | 显示全部楼层

赞一个
回复 支持 反对

使用道具 举报

41

主题

2476

回帖

282

蝴蝶豆

论坛元老

最后登录
2020-12-8
发表于 2015-11-1 22:41:40 | 显示全部楼层
顶一下,应该也是为了降低功耗吧
回复 支持 反对

使用道具 举报

19

主题

935

回帖

27

蝴蝶豆

论坛元老

最后登录
2019-7-29
发表于 2015-11-1 23:58:46 | 显示全部楼层
LL库好像是针对寄存器的操作的,比HAL库效率高,明年上半年会合在stm32cube中
回复 支持 反对

使用道具 举报

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
 楼主| 发表于 2015-11-2 00:17:26 | 显示全部楼层
feiante 发表于 2015-11-1 23:58
LL库好像是针对寄存器的操作的,比HAL库效率高,明年上半年会合在stm32cube中 ...

对的,全是操作寄存器的
回复 支持 反对

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版