程序员开发实例大全宝库

网站首页 > 编程文章 正文

STM32F030基于LL库的最小软件工程

zazugpt 2025-05-21 17:54:55 编程文章 6 ℃ 0 评论

STM32厂商为方便软件开发,提供三种软件库:标准外设库,HAL库和LL库,经过对比选择LL库进行开发。在ST官方提供的独立LL库的工程模板进行简化,只使用必需的文件,构成我们的最小工程,以后的具体项目的工程基于这个最小工程,这样有利于深刻理解软件结构,方便将来的功能扩展和性能优化。本工程文件结构如下:

各文件的说明如下表:

分组

文件名

说明

user


包含项目所有用户程序,实现产品具体功能、业务,不包含通用功能模块


startup_stm32f030x8.s

芯片的启动加载代码,用汇编实现的,从CMSIS库的位置:

STM32F0xx_HAL\CMSIS\Device\ST\STM32F0xx\Source\Templates\arm下复制到工程内,和使用的编译环境有关,arm目录下的适用于keil,iar目录下的适用于IAR, gcc编译工具则使用gcc目录下的文件;stack和heap的大小可以根据芯片资源和业务修改,其他部分不需要修改


system_stm32f0xx.c

汇编启动加载后,调用main函数前的一些系统初始化配置功能,可从CMSIS库的位置:

STM32F0xx_HAL\CMSIS\Device\ST\STM32F0xx\Source\Templates下复制到工程内,与编译环境无关, 里面根据芯片增加时钟配置代码,也可直接从设备厂商提供的工程模板中的文件复制过来


main.c

用户层的程序入口,实现产品项目的主业务逻辑


board.h

板子的硬件定义文件,如LED、KEY使用的引脚等


board.c

板子的硬件功能实现,如时钟配置、LED、KEY的硬件初始化代码等;

ll


包含LL库文件


stm32f0xx_ll_gpio.c

包含GPIO配置和控制相关功能接口


stm32f0xx_ll_utils.c

包含通用基础功能接口,如延时功能等


stm32f0xx_ll_rcc.c

包含时钟配置相关功能接口

doc


包含了说明文档,不参与编译


read.me

使用的硬件的说明和项目的功能说明,不是必需,但建议简单描述一下

关于该工程的一些说明:

1 为什么使用LL库,不用标准外设库或HAL库?

STM32开发,可以使用ST提供的标准外设库、HAL库或LL库,他们之间有以下区别

(1) 标准外设库是ST最早推出的库,实现的是比较底层的接口,直接操作芯片寄存器,编写的程序运行速度快,性能高,但是各系列的库不兼容,移植工作量较大,并且一些新的芯片不再支持,ST开发了HAL库,用来代替标准外设库;

(2)HAL库是ST的主流软件库,能够用GUI工具STM32Cube直接生成代码,它提供的是比较高层次抽象的通用接口,兼容不同STM32芯片,移植时改动小,而且HAL库的架构设计和代码风格都很好,可读性非常强,容易上手。但是为了实现高层抽象和通用,牺牲了部分执行效率,实现的程序运行较慢,浪费了一些硬件性能。HAL库适用于芯片性能较高,对性能要求不苛刻的产品;

(3) LL库正是为了弥补HAL库的硬件性能利用不够充分的缺点而设计开发的。LL库的全称是Low Layer Driver, 即底层驱动库,它和HAL库是捆绑发行的,可以认为是一个库的两种版本,它的代码风格和HAL库相似,可读性强,接口同样兼容不同STM32芯片,移植方便。而在实现上它直接读写寄存器,性能和标准外设库相近;LL库适用于配置简单的外设或者对性能要求高的外设,不太适用于配置非常复杂的外设(如USB);

现在开发新的项目建议不要用标准外设库,应该在HAL库和LL库之间选择。LL库支持独立使用,也支持和HAL库混合使用,使用STM32的嵌入式开发,应最大限度发挥硬件效率,故应优先使用LL库,遇到配置复杂的外设时,可以再引入HAL库,调用HAL库接口,避免自己编写大量硬件配置代码。STM32F0的性能较低,而外设资源使用都比较简单,单独使用LL库比较合适。

2 工程软件执行顺序如下:

(1)执行startup_stm32f030x8.s的加载、启动代码;

(2)startup_stm32f030x8.s中调用system_stm32f0xx.c里面的SystemInit函数;

(3)startup_stm32f030x8.s中调用C编译器生成的__main函数启动代码;__main函数初始化C运行环境,再调用用户的main函数;

(4)main函数调用先执行板级硬件初始化功能;包括时钟配置和外围接口初始化等(board.c);然后执行业务逻辑功能。

3 LL库的使用方式

(1)定义工程全局宏:USE_FULL_LL_DRIVER, 启用LL库功能;

(2)添加LL库的头文件路径:STM32F0xx_HAL\STM32F0xx_HAL_Driver\Inc; LL库和HAL库文件在同一个目录内;

(3)包含需要用到的LL库头文件,通用的头文件包括:

#include "stm32f0xx_ll_bus.h" // 包含总线功能定义
 #include "stm32f0xx_ll_system.h"// 包含部分FLASH特征、系统配置和调试等功能定义 
#include "stm32f0xx_ll_utils.h" // 包含芯片ID、延时和PPL等通用功能定义 
#include "stm32f0xx_ll_rcc.h" // 包含时钟配置功能

其他根据需要的功能选择,例如使用GPIO功能应包含:#include "stm32f0xx_ll_gpio.h"

(4)LL库没有专门的全局初始化函数,按需直接调用相应功能接口即可,以GPIO的初始化和控制为例:

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB) 
LL_GPIO_InitTypeDef gpioInitstruct; 
gpioInitstruct.Mode = LL_GPIO_MODE_OUTPUT; 
gpioInitstruct.Speed = LL_GPIO_SPEED_FREQ_LOW; 
gpioInitstruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
gpioInitstruct.Pull = LL_GPIO_PULL_NO; 
gpioInitstruct.Pin = LL_GPIO_PIN_4; 
if (LL_GPIO_Init(GPIOB, &gpioInitstruct) != SUCCESS) {
} 
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_4);

(5)LL库的代码风格与HAL库相似,LL库的变量、接口名都是以"LL_"为前缀(HAL库的前缀是“HAL_”),库代码是开源的,可以随时查看接口的源代码实现,在性能关键的部分可以根据源代码进一步优化。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表