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

查看: 23982|回复: 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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版