找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12355|回复: 6
收起左侧

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

[复制链接]
ID:127084 发表于 2016-6-17 14:37 | 显示全部楼层 |阅读模式

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

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



一、       初识LL

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

184850p3m22imp2jn2w82x.png


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


184852hroo3zi0q7e3pj0r.png

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

184853krnqnwwno8ogyg00.png



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

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




184854txsqlcqsnscjjvx6.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.0DriversSTM32L4xx_HAL_DriverInc

184917y2dqkkksedyy5xkk.png


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


二、       怎么使用LL

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

185442fuagdxeeipygxfzx.png


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


185450py5atc65ttbyib7p.png

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

前面提到,要使用LL库,需要包含对应头文件,各头文件之间有如下关系:
185454hexwg4x4zl6nzyqe.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 百度网盘下载地址:http://pan.baidu.com/s/1c0wjL5m

一楼二楼是具体使用方法。
已完,上传文档和工程模板:
STM32 LL库使用指南.pdf (847.11 KB, 下载次数: 125)
STM32L476_LL_工程模板.rar (768.3 KB, 下载次数: 45)
三、      开发环境搭建—— 新建STM32LL库工程模板
要开发首先要搭建开发环境,也就是简历所谓的工程模板。由于独立使用LL库的情况下不能使用Cube来建立工程,所以需要手动建立,这里的建工程方法和以前使用标准库建工程模板比较类似:
1.        准备相关文件:
新建一个文件夹用来放所有的文件
把需要用到的相关文件全部复制过来:
首先是上一节说到的几个必不可少的文件
stm32l4xx.h,stm32l476xx.h,
system_stm32l4xx.h,system_stm32l4xx.c,
startup_stm32l476xx.s
这些文件都在STM32Cube_FW_L4_V1.1.0DriversCMSISDeviceSTSTM32L4xx文件夹下,为了方便查找,我保持了和库文件中相同的文件夹结构。如果闲麻烦,可以把STM32Cube_FW_L4_V1.1.0DriversCMSIS整个文件夹复制过来,该文件夹下的其他文件如Include文件夹里面的也需要用到。
然后把所有LL库的文件复制过来,
STM32Cube_FW_L4_V1.1.0DriversSTM32L4xx_HAL_DriverInc文件夹下面所有stm32l4xx_ll_xxx.h命名的文件,也可以整个文件夹复制。

125005b8ank8aag2ag6kyl.png
其实主要就是这两个文件夹下面相关的一些文件复制过来就好。当然一股脑全部粘贴过去也没什么影响,就是工程大一点(henduo)。
最后建立Inc,Src,MDK-ARM文件夹放头文件、源文件和工程文件,,stm32l4xx_it.h/.c这两个文件其实也可以不要,因为我们可以把中断函数处理函数放在任何地方都可以,main.c/main.h自己新建或者复制个模板。
所有文件,文件夹名字都可以随便取,这里只是为了保持和库、Cube建立的工程文件结构保持一致,所以取这些名字。
125006f7grrhgqhsprjz5k.png
2.        好了,准备工作做好了,开始建工程
打开Keil MDK,新建一个工程选择型号STM32L4RG,在此之前需要确保已经安装了Keil STM32L4的Pack,不然新建工程的时候找不到对应的型号。
125007m5sammzzx1svpekn.png
然后往工程里添加刚刚准备好的相关文件:

125009lemmlqbr1nz0rz50.png

只需添加*.c和*.s文件,*.h文件设置头文件包含路径就行,也可以加到工程中方便查看。
接下来就是最重要的部分,工程设置:
有几个主要地方需要设置,
1.      定义使用的芯片型号 STM32L4xx
125009w8mc6nn0959fnv5w.png

2.      设置文件包含路径
..Inc                                                                                             //自己写的头文件路径
..DriversCMSISInclude                                                        //关于Cortex的一些头文件
..DriversCMSISDeviceSTSTM32L4xxInclude            // stm32l4xx.h,stm32l476xx.h等文件
..DriversSTM32L4xx_HAL_DriverInc                              //LL库文件的路径

125010goz4zocz2ttbafzx.png


3.      设置所用调试仿真器,使用Nucleo板载ST-Link
4.      
125015h0yklfeyy40ffy8l.png

差不多就这些了,如果芯片型号选择正确,pack安装正确,其他的工程已经默认设置好,编译一下无错误无警告,下面就是真正的开发,写代码了。

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

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

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

1.        包含头文件
main.c
#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库】了。

上个IAR工程模板:
stm32L476.7z (2.24 MB, 下载次数: 27)

回复

使用道具 举报

ID:258960 发表于 2017-12-22 11:21 | 显示全部楼层
不错的教程
回复

使用道具 举报

ID:72988 发表于 2018-10-25 06:09 | 显示全部楼层

不错的教程
回复

使用道具 举报

ID:20672 发表于 2019-2-26 16:16 | 显示全部楼层
谢谢分享,LL比较底层了,多看看才能看懂了
回复

使用道具 举报

ID:671742 发表于 2020-1-9 14:20 | 显示全部楼层
谢谢分享,这个应该就是最精减的库了吧。
回复

使用道具 举报

ID:328121 发表于 2020-1-10 08:47 | 显示全部楼层
谢谢分享,值得一看
回复

使用道具 举报

ID:336576 发表于 2021-8-12 09:49 | 显示全部楼层
支持一下。hal库, 串口到现在也是不太好
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表