?????最近因为需要学习研究一下
F
D
C
A
N
FD\quad CAN
FDCAN模块,所以买了一块野火的
S
T
M
32
H
750
X
B
H
6
STM32H750XBH6
STM32H750XBH6的开发板。拿到开发板之后准备像
S
T
M
32
F
103
STM32F103
STM32F103开发板那样到这里先下载对应的标准库,新建一个小的工程开始。可是我却发现没有
H
7
H7
H7系列的标准库了,如图1所示,最后查找资料了解到,
S
T
ST
ST公司目前普遍已经开始使用
H
A
L
HAL
HAL库,
L
L
LL
LL库等,并且
S
T
ST
ST公司提出了
S
T
M
32
C
U
B
E
STM32\quad CUBE
STM32CUBE这个概念,希望通过提高软件的可重用性来减少开发时间,节约开发成本。因此在学习
S
T
M
32
H
750
X
B
H
6
STM32H750XBH6
STM32H750XBH6的开发板开发板之前,我需要简单的先了解一下以上概念,下面将是我的一个学习的记录。
图1.
图2.
?????我们先来了解一下
H
A
L
HAL
HAL库和
L
L
LL
LL库,这部分内容主要参考图2所示的文档,该文档也可以作为我们以后在使用
H
7
H7
H7系列芯片的
H
A
L
HAL
HAL库和
L
L
LL
LL库的时候的参考文档。既然要学习,那我们还是得先把
H
A
L
HAL
HAL库和
L
L
LL
LL库下载下载看看到底是个什么样子的,我们先定位到图3所示的页面,这时你会发现这个页面就是
S
T
M
32
C
u
b
e
M
X
STM32\quad Cube\quad MX
STM32CubeMX的页面,这个不用惊奇,因为
S
T
M
32
C
u
b
e
M
X
STM32\quad Cube\quad MX
STM32CubeMX和
H
A
L
HAL
HAL库,
L
L
LL
LL库都是属于
S
T
M
32
C
u
b
e
STM32\quad Cube
STM32Cube的一部分。然后我们找到图4里面红圈所标示的
S
T
M
32
C
u
b
e
H
7
STM32CubeH7
STM32CubeH7,然后点进入就是我们所要找的
H
A
L
HAL
HAL库和
L
L
LL
LL库的下载地址了,如图5中的红圈所示。然后选择我们所要下载的版本即可,至于图5里面的那个
P
a
t
c
h
_
C
u
b
e
H
7
Patch\_CubeH7
Patch_CubeH7,我也不知道是个什么软件包,反正是和
H
7
H7
H7系列有关的,但是你把它下载下来解压之后,发现它里面的内容和
S
T
M
32
C
u
b
e
H
7
STM32CubeH7
STM32CubeH7里面的内容基本是一样的。
图3.
图4.
图5.
?????这个
S
T
M
32
C
u
b
e
H
7
STM32CubeH7
STM32CubeH7软件包除了有
H
A
L
HAL
HAL库和
L
L
LL
LL库,还有很多其它的内容,比如
S
T
M
32
STM32
STM32的
H
7
H7
H7系列的相关开发板的模板工程,示例工程,如图6和图7所示。图8是
H
A
L
HAL
HAL库和
L
L
LL
LL库的源文件所在目录。
图6.
图7.
图8.
?????从图8中可以看出,
H
A
L
HAL
HAL库和
L
L
LL
LL库通过文件名里面的
_
h
a
l
_
\_hal\_
_hal_和
_
l
l
_
\_ll\_
_ll_来进行区别,还可以看到的是有些外设的
H
A
L
HAL
HAL库驱动不止一个源文件,比如
s
t
m
32
h
7
x
x
_
h
a
l
_
s
p
i
.
c
stm32h7xx\_hal\_spi.c
stm32h7xx_hal_spi.c和
s
t
m
32
h
7
x
x
_
h
a
l
_
s
p
i
_
e
x
.
c
stm32h7xx\_hal\_spi\_ex.c
stm32h7xx_hal_spi_ex.c,按照官方文档的描述带有
e
x
ex
ex后缀的源文件是外设或模块驱动的扩展文件,它里面包含了某些特定家族或系列芯片所特有功能的驱动,它也有可能包含了对某些通用驱动文件的重写。不带有
e
x
ex
ex后缀的源文件驱动是通用的驱动且对于所有的系列都一样,都适用,具有很高的可移植性。
H
A
L
HAL
HAL库综上来说被分为了两类,通用驱动和扩展驱动。还有就是针对通用驱动或扩展驱动,对应的驱动源文件也不止一个,比如我们知道
U
S
A
R
T
USART
USART模块有智能卡的功能,在图8中我们可以看到针对
U
S
A
R
T
USART
USART模块的智能卡功能,还专门有驱动源文件
s
t
m
32
h
7
x
x
_
h
a
l
_
s
m
a
r
t
c
a
r
d
.
c
stm32h7xx\_hal\_smartcard.c
stm32h7xx_hal_smartcard.c和
s
t
m
32
h
7
x
x
_
h
a
l
_
s
m
a
r
t
c
a
r
d
_
e
x
.
c
stm32h7xx\_hal\_smartcard\_ex.c
stm32h7xx_hal_smartcard_ex.c对应。
L
L
LL
LL库就没有通用驱动和扩展驱动之分,
L
L
LL
LL库和
H
A
L
HAL
HAL库相比没有那么高的抽象性,
L
L
LL
LL库都是直接操作寄存器,因此需要对硬件有比较深的了解,可以说是面向专家级别的,因此
L
L
LL
LL库和
H
A
L
HAL
HAL库相比移植性也较差。并不是每一种模块或外设都提供了
L
L
LL
LL库,对于那些优化不是关键特性,或者需要大量软件配置,或者需要上层协议栈的模块或外设就没有对应的
L
L
LL
LL库。
typedef struct
{
uint32_t Timing;
uint32_t OwnAddress1;
uint32_t AddressingMode;
uint32_t DualAddressMode;
uint32_t OwnAddress2;
uint32_t OwnAddress2Masks;
uint32_t GeneralCallMode;
uint32_t NoStretchMode;
} I2C_InitTypeDef;
?????上面的结构体定义是我从文件
s
t
m
32
h
7
x
x
_
h
a
l
_
i
2
c
.
h
stm32h7xx\_hal\_i2c.h
stm32h7xx_hal_i2c.h里面复制过来的,用过标准库的应该还是有一种似曾相识的感觉,在标准库中我们就是用这种结构体来对整个模块或外设进行初始化,但是
H
A
L
HAL
HAL库相对于标准库具有更高的抽象性,更高的可移植性,为了做到这一点,
H
A
L
HAL
HAL库在上面这种结构体的基础之上又包装了一层结构体(
G
P
I
O
,
S
Y
S
T
I
C
K
,
N
V
I
C
,
P
W
R
,
R
C
C
,
F
L
A
S
H
GPIO,SYSTICK , NVIC, PWR,RCC, FLASH
GPIO,SYSTICK,NVIC,PWR,RCC,FLASH等模块没有这种结构体):
typedef struct __I2C_HandleTypeDef
{
I2C_TypeDef *Instance;
I2C_InitTypeDef Init;
uint8_t *pBuffPtr;
uint16_t XferSize;
__IO uint16_t XferCount;
__IO uint32_t XferOptions;
__IO uint32_t PreviousState;
HAL_StatusTypeDef(*XferISR)(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources);
DMA_HandleTypeDef *hdmatx;
DMA_HandleTypeDef *hdmarx;
HAL_LockTypeDef Lock;
__IO HAL_I2C_StateTypeDef State;
__IO HAL_I2C_ModeTypeDef Mode;
__IO uint32_t ErrorCode;
__IO uint32_t AddrEventCount;
#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
void (* MasterTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* MasterRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* SlaveTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* SlaveRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* ListenCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* MemTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* MemRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* ErrorCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* AbortCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* AddrCallback)(struct __I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode);
void (* MspInitCallback)(struct __I2C_HandleTypeDef *hi2c);
void (* MspDeInitCallback)(struct __I2C_HandleTypeDef *hi2c);
#endif
} I2C_HandleTypeDef;
?????这种结构体被称之为
H
a
n
d
l
e
Handle
Handle,可以看到这种
H
a
n
d
l
e
Handle
Handle结构体把模块寄存器结构体,模块初始化结构体都包含在这个结构体之中,当然还有
D
M
A
DMA
DMA的相关结构体。还有就是
H
A
L
HAL
HAL库里面已经为我们实现了中断函数的初始版本,我们需要在
I
2
C
x
_
E
V
_
I
R
Q
H
a
n
d
l
e
r
I2Cx\_EV\_IRQHandler
I2Cx_EV_IRQHandler和
I
2
C
x
_
E
R
_
I
R
Q
H
a
n
d
l
e
r
I2Cx\_ER\_IRQHandler
I2Cx_ER_IRQHandler等函数中调用下面的初始版本函数。
H
A
L
HAL
HAL库里面也有大量的回调函数,至于这种回调函数的具体使用,我现在也不是太清楚,只有在具体使用过
H
A
L
HAL
HAL库之后才能对这一机制有比较清晰的了解,我只知道这种回调函数主要在中断机制中被调用。文件
s
t
m
32
h
7
x
x
_
h
a
l
_
i
2
c
.
h
stm32h7xx\_hal\_i2c.h
stm32h7xx_hal_i2c.h中,初始版本的中断函数以及回调函数声明如图9所示。还有这些回调函数一般都是被声明为
_
_
w
e
a
k
\_\_weak
__weak属性,如图10所示,也就是用户可以定义一个同名的函数,且最后调用这个名字的函数时,如果用户重新定义了这个函数,则实际调用的是用户定义的这个函数。
void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c);
void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c);
图9.
图10.
?????图11是
H
A
L
HAL
HAL库中头文件的包含结构示意图。虽然
H
A
L
HAL
HAL库和
L
L
LL
LL库的头文件和源文件都各自的在同一个文件夹中,但是
H
A
L
HAL
HAL库和
L
L
LL
LL库都是相互独立的,相互之间没有依赖关系。虽然如此,
H
A
L
HAL
HAL库和
L
L
LL
LL库都可以各自独立使用,但是也可以结合使用。我们前面提到过
L
L
LL
LL库基本都是直接操作寄存器的,有朋友可能会想到
L
L
LL
LL库是不是就是和标准库差不多,但是等你打开
L
L
LL
LL库的源文件和头文件之后你就不会有这样的想法了。文件
s
t
m
32
h
7
x
x
_
l
l
_
i
2
c
.
c
stm32h7xx\_ll\_i2c.c
stm32h7xx_ll_i2c.c里面只有和初始化和恢复默认值的几个接口函数,如图12所示,但是我看单独使用
L
L
LL
LL库的例子中基本可以不用这几个函数。然后其它的接口函数都定义在文件
s
t
m
32
h
7
x
x
_
l
l
_
i
2
c
.
h
stm32h7xx\_ll\_i2c.h
stm32h7xx_ll_i2c.h中,且这些接口都是直接操作寄存器的,并都定义为
_
_
i
n
l
i
n
e
\_\_inline
__inline,即内联,函数类型。如图13所示。
图11.
图12.
图13.
?????
S
T
M
32
C
u
b
e
STM32\quad Cube
STM32Cube是
S
T
ST
ST公司的一项原始创新,这一项原始创新通过减少开发成本,时间来提高开发者的效率。
S
T
M
32
C
u
b
e
STM32\quad Cube
STM32Cube基本上涵盖了所有的
S
T
ST
ST公司的系列信号芯片。
S
T
M
32
C
u
b
e
STM32\quad Cube
STM32Cube包含几部分内容,
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX是
S
T
M
32
C
u
b
e
STM32\quad Cube
STM32Cube其中的一部分,
S
T
M
32
C
u
b
e
STM32\quad Cube
STM32Cube所包含的内容如图14所示。
图14.
图15.
图16.
?????
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX是一种图形化工具,我开始听说它的时候,我以为从此之后
S
T
M
32
STM32
STM32所有的代码开发都可以通过简单的点点鼠标就可以了,但是通过我的了解之后我还是觉得我想多了。下面我对
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX的介绍都是基于图15的文档。
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX具有图16所示的特性,但是向我们这种初学者话,用的比较多的可能就是图16中红圈中的功能,也就是构建初始化工程,以及生成时钟配置函数(这里要注意的是
H
A
L
HAL
HAL库在芯片上电复位调用的
v
o
i
d
S
y
s
t
e
m
I
n
i
t
(
v
o
i
d
)
void\quad SystemInit (void)
voidSystemInit(void)函数里面是没有调用像标准库里面那样的配置时钟的函数,
v
o
i
d
S
e
t
S
y
s
C
l
o
c
k
(
v
o
i
d
)
void\quad SetSysClock (void)
voidSetSysClock(void),的,这种时钟配置函数要么我们自己实现或者使用
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX来生成,当然使用
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX来生成还是方便很多)。
图17.
图18.
?????
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX的下载地址如图18所示,选择相应的版本下载就可以。这里因为我也是初学,我就不详细的去介绍
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX,具体的细节可以参考图15的文档。下面我直接介绍一下一个最基础的构建工程模板的过程。
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX打开之后的界面如图19所示,这时可以通过点击红框中的
A
C
C
E
S
S
T
O
M
C
U
S
E
L
E
C
T
O
R
ACCESS\quad TO\quad MCU\quad SELECTOR
ACCESSTOMCUSELECTOR或
F
i
l
e
File
File下拉菜单的
N
e
w
P
r
o
j
e
c
t
New\quad Project
NewProject来开始新建
S
T
M
32
C
u
b
e
M
X
STM32\quad CubeMX
STM32CubeMX工程。之后的页面如图20所示,这时我们需要根据自己的芯片型号来选择对应的芯片型号,图20左边的是搜索你的预期芯片的一些过滤选项,设置好之后就会出现相关的芯片型号,如图20的右下角所示,因为我这边的开发板的芯片的型号为
S
T
M
32
H
750
X
B
H
6
STM32H750XBH6
STM32H750XBH6,所以我这里点击选中该型号(注意这里鼠标一定要点击,不然右上角的
S
t
a
r
t
P
r
o
j
e
c
t
Start\quad Project
StartProject将会是灰色的),然后点击
S
t
a
r
t
P
r
o
j
e
c
t
Start\quad Project
StartProject。
图19.
图20.
?????接下来将会出现图21所示的界面,这个提示应该是和
M
P
U
MPU
MPU相关的,这里关系应该不太大,选
Y
e
s
Yes
Yes或
N
o
No
No应该都可以,但是它建议你选择
Y
e
s
Yes
Yes。接下来就会出现图22所示的界面,这时我们先点击一下
P
r
o
j
e
c
t
M
a
n
a
g
e
r
Project\quad Manager
ProjectManager配置一下工程的名字,存放位置,生成的模板工程使用的
I
D
E
IDE
IDE(这里我使用的是
K
E
I
L
KEIL
KEIL,因此这里我选择的是
M
D
K
?
A
R
M
MDK-ARM
MDK?ARM),模板工程堆和栈空间的大小等等,当然还有其它一些选项,大家可以参考图15的文档。
图21.
图22.
图23.
?????接下来我们来配置一下系统的时钟,因为我们这里准备使用
H
S
E
HSE
HSE作为时钟源,因此这里我们首先要在图23所在的
P
i
n
o
u
t
C
o
n
f
i
g
u
r
a
t
i
o
n
Pinout\quad Configuration
PinoutConfiguration界面使能
H
S
E
HSE
HSE,然后我们切换到图25所示的时钟配置界面,因为野火的开发板的
H
S
E
HSE
HSE时钟为
25
M
H
Z
25MHZ
25MHZ,因此这里
H
S
E
HSE
HSE时钟的输入频率方框我们填
25
M
H
Z
25MHZ
25MHZ。我们这里配置
H
S
E
HSE
HSE时钟5分频,然后160倍频之后再除以2,
P
L
L
PLL
PLL时钟源选择
H
S
E
HSE
HSE,系统时钟源选择
P
L
L
PLL
PLL,因此配置的系统时钟,
S
Y
S
C
L
K
SYSCLK
SYSCLK,的频率为
400
M
H
Z
400MHZ
400MHZ,
H
C
L
K
HCLK
HCLK的频率为
200
M
H
Z
200MHZ
200MHZ,
A
P
B
1
APB1
APB1,
A
P
B
2
APB2
APB2,
A
P
B
,
3
APB,3
APB,3和
A
P
B
4
APB4
APB4的频率都为
100
M
H
Z
100MHZ
100MHZ。这里的模板工程我想用简单的
U
S
A
R
T
USART
USART模块的通信来验证,因此这里我在图25的界面也简单的配置了一下
U
S
A
R
T
1
USART1
USART1模块,这些配置好之后,我们点击一下图25中右上角的
G
E
N
E
R
A
T
E
C
O
D
E
GENERATE\quad CODE
GENERATECODE就可以生成我们的模板工程了。
图24.
图25.
?????当然我们也可以自己手动构建模板工程。这个过程其实和
S
T
M
32
F
103
STM32F103
STM32F103的标准库的手动构建工程模板的工程基本一样,可以参考一下我的这篇文章,只是在细节上会有一些差别。首先我们还是先新建一些文件夹来把需要的各个源文件放置好,我们首先将图26的文件夹中的所有文件放在一个新建的名字位
c
o
r
e
core
core的文件夹中,这个文件夹里面基本都是和内核有关的文件,虽然这里面有很多文件,但是实际的工程里面用到可能就几个而已,但是为了方便我这里把他们全部都放进来了。然后新建一个叫
u
s
e
r
user
user的文件夹,然后找到
H
750
H750
H750的模板工程,并将图26和图27里面的
m
a
i
n
.
c
main.c
main.c和
m
a
i
n
.
h
main.h
main.h文件复制到这个文件夹里面,当然你也可以自己生成这两个文件。然后新建一个叫
h
a
l
hal
hal的文件夹,将图28里面的
I
n
c
Inc
Inc文件夹和
S
r
c
Src
Src文件夹放到这个文件夹里面,这两个文件夹里面分别是
H
A
L
HAL
HAL库和
L
L
LL
LL库的头文件和源文件。然后新建一个叫做
s
t
a
r
t
_
u
p
start\_up
start_up的文件夹并将图29中红圈标示的启动文件放在这个文件夹里面。然后分别新建
p
r
o
j
e
c
t
project
project,
o
b
j
_
o
u
t
p
u
t
obj\_output
obj_output以及
l
i
s
t
i
n
g
listing
listing三个文件夹,这三个文件夹分别用来放项目配置文件,编译输出的中间文件以及
l
i
s
t
list
list文件。然后新建一个
s
t
m
stm
stm文件夹,这个文件夹里面又新建了两个文件夹,
I
n
c
l
u
d
e
Include
Include和
S
o
u
r
c
e
Source
Source,然后将图30和图31的头文件放到
I
n
c
l
u
d
e
Include
Include文件夹里面。然后将图32里面的三个红圈标示的源文件放到
S
o
u
r
c
e
Source
Source文件夹里面。图31和图32的目录和前面取
m
a
i
n
.
c
main.c
main.c和
m
a
i
n
.
h
main.h
main.h文件得目录都是同一个模板工程。
的文件也是
S
T
ST
ST公司提供的一个模板工程的目录里面。但是其实这里
图26.
图27.
图28.
图29.
图30.
图31.
图32.
?????因为
m
a
i
n
.
c
main.c
main.c和
m
a
i
n
.
h
main.h
main.h文件这两个文件是我们从模板工程里面复制出来的,可能编译会有错误,因此我们需要根据自己的需求做相应的修改。还有就是图33中的
s
t
m
32
h
7
x
x
_
h
a
l
_
m
s
p
_
t
e
m
p
l
a
t
e
.
c
stm32h7xx\_hal\_msp\_template.c
stm32h7xx_hal_msp_template.c,这个文件在使用的时候需要去掉
t
e
m
p
l
a
t
e
template
template关键字,然后复制到对应的目录并根据需求做相应的修改,从这个文件的名字我们也可以看出,这是一个模板文件,由于我们已经从模板工程里面获取了这个文件,因此这个文件就不要参与编译了,同样图34中那几个红圈中的文件名带有
t
e
m
p
l
a
t
e
template
template关键字的文件也都不要参与编译了,否则可能会有错误,在有相应需求的时候再把它们修改之后再参与编译。另外还要注意一下
s
y
s
t
e
m
s
t
m
32
h
7
x
x
.
c
system_stm32h7xx.c
systems?tm32h7xx.c这个文件,前面也提到过了这个文件是从
S
T
M
32
C
u
b
e
H
7
STM32CubeH7
STM32CubeH7固件包里面的
H
750
H750
H750模板工程复制过来的,
S
T
M
32
C
u
b
e
H
7
STM32CubeH7
STM32CubeH7固件包里面
有很多的
H
750
有很多的H750
有很多的H750示例工程,每一个工程里面都有这个文件,如果你仔细去看的话有些工程的这个文件与其它的工程有一定的差异,主要是
v
o
i
d
S
y
s
t
e
m
I
n
i
t
(
v
o
i
d
)
void\quad SystemInit (void)
voidSystemInit(void)这个函数,比如
Q
S
P
I
QSPI
QSPI的示例工程,或者是从外部存储器启动的示例工程,这应该是这些工程的特殊目的造成的,所以如果我们有相应的特殊需求的时候
s
y
s
t
e
m
s
t
m
32
h
7
x
x
.
c
system_stm32h7xx.c
systems?tm32h7xx.c这个文件可以参考相应的工程,对于一般的工程我们直接从图32的模板工程里面去取。这里要注意的是在我构建的这个模板工程中,文件
s
y
s
t
e
m
s
t
m
32
h
7
x
x
.
c
system_stm32h7xx.c
systems?tm32h7xx.c中的
v
o
i
d
S
y
s
t
e
m
I
n
i
t
(
v
o
i
d
)
void\quad SystemInit (void)
voidSystemInit(void)函数的一个位置需要注意一下,如图35所示,这里有一个宏需要定义一下,这个宏定义了你预期的程序代码放置的首地址,因为我这里预期从内部
F
L
A
S
H
FLASH
FLASH启动,所以在图36中这个宏我定义位内部
F
L
A
S
H
FLASH
FLASH的起始地址
0
x
08000000
0x08000000
0x08000000,在图36里面的
P
r
e
p
r
o
c
e
s
s
o
r
S
y
m
b
o
l
s
Preprocessor\quad Symbols
PreprocessorSymbols的位置我还加上了宏
U
S
E
_
H
A
L
_
D
R
I
V
E
R
USE\_HAL\_DRIVER
USE_HAL_DRIVER,
U
S
E
_
F
U
L
L
_
L
L
_
D
R
I
V
E
R
USE\_FULL\_LL\_DRIVER
USE_FULL_LL_DRIVER以及
S
T
M
32
H
750
x
x
STM32H750xx
STM32H750xx因为这样就可以同时使用
H
A
L
HAL
HAL库和
L
L
LL
LL库,当然你也可以根据你自己的需求定义宏
U
S
E
_
H
A
L
_
D
R
I
V
E
R
USE\_HAL\_DRIVER
USE_HAL_DRIVER和宏
U
S
E
_
F
U
L
L
_
L
L
_
D
R
I
V
E
R
USE\_FULL\_LL\_DRIVER
USE_FULL_LL_DRIVER中的一个。因为我这里使用的芯片是
S
T
M
32
H
750
X
B
H
6
STM32H750XBH6
STM32H750XBH6,因此需要定义宏
S
T
M
32
H
750
x
x
STM32H750xx
STM32H750xx。有了以上准备再参考一下我用
S
T
M
32
F
103
STM32F103
STM32F103的标准库的手动构建工程模板的流程,看这里,基本上建立一个工程模板是没有问题的。我的模板工程在这里。
图34.
图35.
图36.
|