找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 12282|回復(fù): 6
打印 上一主題 下一主題
收起左側(cè)

【NUCLEO-L476RG LL庫開發(fā)】STM32【LL庫】開發(fā)使用指南

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主

熟悉STM32的都知道ST官方提供了非常方便好用的庫函數(shù)供用戶使用,多數(shù)人都使用過STM32標(biāo)準(zhǔn)外設(shè)庫,STM32Cube庫(即HAL庫),這個LL庫是什么鬼,卻從來沒聽說過。

好吧,我承認(rèn)這個名字是我自己XJB的。。。。。。。。



一、       初識LL

最近論壇發(fā)的STM32L476RGNucleo開發(fā)板到手了,準(zhǔn)備學(xué)習(xí)玩耍,當(dāng)然第一步就是下載資料,于是我下載STM32L4Cube 1.1.0版本,打開逐個查看,



好像和以前一樣的,沒什么特別嘛,于是準(zhǔn)備開始開發(fā)。。。
等等,好像還真發(fā)現(xiàn)了有點(diǎn)不一樣:



熟悉HAL庫的都知道,該庫的文件幾乎都是以stm32xxx_hal_xxx.h/.c命名的,為了和以前的標(biāo)準(zhǔn)庫有個區(qū)分,上圖中那些是什么鬼?????
前輩說,遇到問題趕緊查手冊,于是我果斷打開STM32L4Cube庫的說明手冊(UM1884):




原來這個東西叫做LowLayer APIs,作為英文渣渣表示實(shí)在不習(xí)慣洋里洋氣的高大上名字,于是擅自把他叫做【STM32LL庫】了(不服的你咬我。。

從這里看好像是說這個東東比HAL庫更接近硬件,到底什么鬼,還不清楚。但是以前好像沒見過這個東西啊,就算是STM32L4Cube的1.0.0版本中都沒有?纯碈ube發(fā)行歷史:






原來LL庫是在1.1.0版本才加上的,大概意思就是:
1.          LL APIs是寄存器級的編程,嗯,也就是我們常說的直接操作寄存器吧。
2.          LL APIs適用于xxx等一大堆外設(shè)
3.          LL APIs函數(shù)全部定義為staticinline函數(shù),放在對應(yīng)的頭文件中,用戶使用需要包含相關(guān)頭文件
4.          參考這兩個文檔
看看LL庫文件在Cube庫中的位置,有20多個文件,全部以stm32l4xx_ll_xxx.h命名:
STM32Cube_FW_L4_V1.1.0DriversSTM32L4xx_HAL_DriverInc



STM32L4是面向低功耗市場的,同時不失高性能,功耗和性能往往是兩個矛盾的東西,ST在硬件設(shè)計(jì)上想了各種辦法來實(shí)現(xiàn)兼顧低功耗高性能(例如各種低功耗模式,LP外設(shè)等),而在軟件層面,程序也講求效率, LL庫全是直接操作寄存器,直接操作寄存器往往效率較高,而且函數(shù)定義為內(nèi)聯(lián)函數(shù),調(diào)用函數(shù)時不是堆棧調(diào)用,而是直接把函數(shù)的代碼嵌入到調(diào)用的地方,利于提高代碼相率,我想這也是ST在STM32L4系列中推出這個直接操作寄存器的LL庫的原因之一吧。


二、       怎么使用LL

先看看手冊里怎么說的,它有什么特點(diǎn):



英文渣渣就不翻譯了,反正大概就是說
LL庫更接近硬件層,對需要復(fù)雜上層協(xié)議棧的外設(shè)不適用,直接操作寄存器等等一大堆,到這里,可以看到它的使用方法:
1.        獨(dú)立使用,該庫完全獨(dú)立實(shí)現(xiàn),可以完全拋開HAL庫,只用LL庫編程完成。
2.        混合使用,和HAL庫結(jié)合使用。
本人就常在編程的時候庫函數(shù)和寄存器操作混合,所以覺得混合使用應(yīng)該是不錯的方式。
最后一段還說到該庫不需要額外的內(nèi)存資源來存儲程序狀態(tài),數(shù)據(jù)指針等東西,所有的操作都通過直接修改外設(shè)的寄存器來完成。
下面是手冊中對各個LL文件的描述:



就是講LL庫由5部分組成:每個外設(shè)對應(yīng)一個頭文件組成一部分,以及系統(tǒng)相關(guān)的bus,cortex,utils,system四個部分。

前面提到,要使用LL庫,需要包含對應(yīng)頭文件,各頭文件之間有如下關(guān)系:

看來,我們編程的時候只需要#include某外設(shè)的頭文件,就可以使用LL庫了,但是同時,系統(tǒng)啟動文件,初始化文件等一系列不能少,具體講就是:

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

這幾個文件,這在標(biāo)準(zhǔn)庫,Cube庫都不曾變過的鐵律。

順便分享一下STM32L4Cube 庫 1.1.0版本和1.1.1版本的Pack 百度網(wǎng)盤下載地址:http://pan.baidu.com/s/1c0wjL5m

一樓二樓是具體使用方法。
已完,上傳文檔和工程模板:
STM32 LL庫使用指南.pdf (847.11 KB, 下載次數(shù): 125)
STM32L476_LL_工程模板.rar (768.3 KB, 下載次數(shù): 45)
三、      開發(fā)環(huán)境搭建—— 新建STM32LL庫工程模板
要開發(fā)首先要搭建開發(fā)環(huán)境,也就是簡歷所謂的工程模板。由于獨(dú)立使用LL庫的情況下不能使用Cube來建立工程,所以需要手動建立,這里的建工程方法和以前使用標(biāo)準(zhǔn)庫建工程模板比較類似:
1.        準(zhǔn)備相關(guān)文件:
新建一個文件夾用來放所有的文件
把需要用到的相關(guān)文件全部復(fù)制過來:
首先是上一節(jié)說到的幾個必不可少的文件
stm32l4xx.h,stm32l476xx.h,
system_stm32l4xx.h,system_stm32l4xx.c,
startup_stm32l476xx.s
這些文件都在STM32Cube_FW_L4_V1.1.0DriversCMSISDeviceSTSTM32L4xx文件夾下,為了方便查找,我保持了和庫文件中相同的文件夾結(jié)構(gòu)。如果閑麻煩,可以把STM32Cube_FW_L4_V1.1.0DriversCMSIS整個文件夾復(fù)制過來,該文件夾下的其他文件如Include文件夾里面的也需要用到。
然后把所有LL庫的文件復(fù)制過來,
STM32Cube_FW_L4_V1.1.0DriversSTM32L4xx_HAL_DriverInc文件夾下面所有stm32l4xx_ll_xxx.h命名的文件,也可以整個文件夾復(fù)制。

其實(shí)主要就是這兩個文件夾下面相關(guān)的一些文件復(fù)制過來就好。當(dāng)然一股腦全部粘貼過去也沒什么影響,就是工程大一點(diǎn)(henduo)。
最后建立Inc,Src,MDK-ARM文件夾放頭文件、源文件和工程文件,,stm32l4xx_it.h/.c這兩個文件其實(shí)也可以不要,因?yàn)槲覀兛梢园阎袛嗪瘮?shù)處理函數(shù)放在任何地方都可以,main.c/main.h自己新建或者復(fù)制個模板。
所有文件,文件夾名字都可以隨便取,這里只是為了保持和庫、Cube建立的工程文件結(jié)構(gòu)保持一致,所以取這些名字。
2.        好了,準(zhǔn)備工作做好了,開始建工程
打開Keil MDK,新建一個工程選擇型號STM32L4RG,在此之前需要確保已經(jīng)安裝了Keil STM32L4的Pack,不然新建工程的時候找不到對應(yīng)的型號。
然后往工程里添加剛剛準(zhǔn)備好的相關(guān)文件:


只需添加*.c和*.s文件,*.h文件設(shè)置頭文件包含路徑就行,也可以加到工程中方便查看。
接下來就是最重要的部分,工程設(shè)置:
有幾個主要地方需要設(shè)置,
1.      定義使用的芯片型號 STM32L4xx

2.      設(shè)置文件包含路徑
..Inc                                                                                             //自己寫的頭文件路徑
..DriversCMSISInclude                                                        //關(guān)于Cortex的一些頭文件
..DriversCMSISDeviceSTSTM32L4xxInclude            // stm32l4xx.h,stm32l476xx.h等文件
..DriversSTM32L4xx_HAL_DriverInc                              //LL庫文件的路徑



3.      設(shè)置所用調(diào)試仿真器,使用Nucleo板載ST-Link
4.      

差不多就這些了,如果芯片型號選擇正確,pack安裝正確,其他的工程已經(jīng)默認(rèn)設(shè)置好,編譯一下無錯誤無警告,下面就是真正的開發(fā),寫代碼了。

趁中午休息把開發(fā)環(huán)境搭建好,晚上回去寫兩個簡單例子,這篇帖子就算是完結(jié)了!

四、      LL庫  第一個程序——點(diǎn)亮LED

首先點(diǎn)亮LED來驗(yàn)證下工程設(shè)置,代碼編寫是否正確。

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"
復(fù)制代碼

包含需要使用的相關(guān)模塊,要用那些就包含哪些,不知道用哪幾個就全部包含進(jìn)去。

2.        配置時鐘
用這個LL庫開發(fā)STM32跟用標(biāo)準(zhǔn)外設(shè)庫很像,很類似,只不過封裝層次更低。首先第一步要配置時鐘,因?yàn)閱游募餂]有默認(rèn)配置,這和STM32F1早期的標(biāo)準(zhǔn)外設(shè)庫一樣,不過較高版本和后來的系列就可以不用了(如果使用默認(rèn)配置的話),啟動文件里默認(rèn)配置了時鐘。怎么配置這里就不細(xì)說了,看代碼應(yīng)該都能懂。
  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. }
復(fù)制代碼

函數(shù)聲明為__STATIC_INLINE(即staticinline)是因?yàn)樵搸焖泻瘮?shù)都是__STATIC_INLINE,前面提到這樣做不需要額外的內(nèi)存,因此這樣最是為了保持這一點(diǎn)。


3.        將LED對應(yīng)引腳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.     }
復(fù)制代碼

4.        PA5輸出高電平,點(diǎn)亮LED
LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_5);
5.        最后需要在主函數(shù)中依次調(diào)用上訴函數(shù),編譯下載運(yùn)行即可看到Nulceo上的綠色LED被成功點(diǎn)亮了。
  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. }
復(fù)制代碼

/*碎碎念:雖然已經(jīng)不知道這是第幾百還是第幾千次做點(diǎn)燈實(shí)驗(yàn),依然還是不厭其煩啊,LED不愧是被稱為單片機(jī)屆的”Hello World!”*/

五、       添加其他程序功能

會了第一個程序,其他的就按照手冊講的寫就行了,再舉個簡單的例子,利用按鍵中斷模式來控制LED的閃爍頻率。
只說下大概步奏,不詳細(xì)說明:將按鍵連接的引腳配置為中斷輸入模式,開啟中斷,配置中斷線,寫中斷服務(wù)函數(shù)來處理中斷。
  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.     }
復(fù)制代碼

在主函數(shù)調(diào)用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.   }
復(fù)制代碼


實(shí)現(xiàn)功能:每按一次按鍵,LED改變一次閃爍頻率,間隔0.1s,0.5s,1s三種不同頻率循環(huán)閃爍。

最后,這個LL庫總體給人感覺是使用方法跟標(biāo)準(zhǔn)外設(shè)庫很像,但也有不同,前面也有提到,它全是直接操作寄存器,程序效率一定程度上會比較高,但使用起來有時候不一定那么方便,可移植性也不好,所以把它和HAL庫結(jié)合起來使用是最好的方式,在程序要求效率的地方就可以使用這些函數(shù),而其他地方使用HAL庫,這也是我們常常使用的方法,只不過以前是使用HAL庫,需要的地方我們自己直接寫操作寄存器,而現(xiàn)在可以換成使用這個【LL庫】了。

上個IAR工程模板:
stm32L476.7z (2.24 MB, 下載次數(shù): 27)

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:258960 發(fā)表于 2017-12-22 11:21 | 只看該作者
不錯的教程
回復(fù)

使用道具 舉報(bào)

板凳
ID:72988 發(fā)表于 2018-10-25 06:09 | 只看該作者

不錯的教程
回復(fù)

使用道具 舉報(bào)

地板
ID:20672 發(fā)表于 2019-2-26 16:16 | 只看該作者
謝謝分享,LL比較底層了,多看看才能看懂了
回復(fù)

使用道具 舉報(bào)

5#
ID:671742 發(fā)表于 2020-1-9 14:20 | 只看該作者
謝謝分享,這個應(yīng)該就是最精減的庫了吧。
回復(fù)

使用道具 舉報(bào)

6#
ID:328121 發(fā)表于 2020-1-10 08:47 | 只看該作者
謝謝分享,值得一看
回復(fù)

使用道具 舉報(bào)

7#
ID:336576 發(fā)表于 2021-8-12 09:49 | 只看該作者
支持一下。hal庫, 串口到現(xiàn)在也是不太好
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表