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

【经验分享】 STM32官方标准固件库概述

[复制链接]
STMCU小助手 发布时间:2022-6-10 19:28
01. STM32官方标准固件库简介
  h: V% {/ J' Q2 {6 `8 eST(意法半导体)为了方便用户开发程序,提供了一套丰富的 STM32F4 固件库。! S+ @$ L, u7 l1 k" B

+ W. C& l% A+ U9 \, h02. 库开发和寄存器开发的关系
- N5 U. a4 s! [) L3 Y( _) K很多用户都是从学 51 单片机开发转而想进一步学习 STM32 开发,他们习惯了 51 单片机的寄存器开发方式,突然一个 ST 官方库摆在面前会一头雾水,不知道从何下手。下面我们将通过一个简单的例子来告诉 STM32 固件库到底是什么,和寄存器开发有什么关系?其实一句话就可以概括:固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道,向上提供用户函数调用的接口(API)。
* m2 a9 K6 _3 `, Y' g' x4 T! A$ Z
+ ?$ S) l+ N  _7 L  |
在 51 的开发中我们常常的作法是直接操作寄存器,比如要控制某些 IO 口的状态,我们直接操作寄存器:
  V% D$ c: Q' F! L" c" z2 i' K1 U' |; J" H- I
  1. P0=0x11;
复制代码

5 h. A$ V, k) W. U; O; O而在 STM32 的开发中,我们同样可以操作寄存器:, w% _0 x  p$ Z! l; P
7 [1 \( l$ d2 E5 t  {2 Q/ O
  1. GPIOF->BSRRL=0x0001; //这里是针对 STM32F4 系列
复制代码

1 h# F% l( w( h& w这种方法当然可以,但是这种方法的劣势是你需要去掌握每个寄存器的用法,你才能正确使用STM32,而对于 STM32 这种级别的 MCU,数百个寄存器记起来又是谈何容易。于是 ST(意法半导体)推出了官方固件库,固件库将这些寄存器底层操作都封装起来,提供一整套接口(API)供开发者调用,大多数场合下,你不需要去知道操作的是哪个寄存器,你只需要知道调用哪些函数即可。
4 r& H/ C. n. ^3 U! w) U
# a4 t; \' m/ P$ a+ X
比如上面的控制 BSRRL 寄存器实现电平控制,官方库封装了一个函数:8 ^* |" k. n  w/ i! D

; e6 {- i' L4 D1 L# H" O( s
  1. <font face="Tahoma"><font size="3">void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)</font></font>
    5 K3 G7 S# Y, P
  2. <font face="Tahoma"><font size="3">{</font></font>* N- Q: Y! \% }
  3. <font face="Tahoma"><font size="3">        GPIOx->BSRRL = GPIO_Pin;</font></font>
    & u7 b) e! K6 `* S0 [. V
  4. <font face="Tahoma"><font size="3">}</font></font>
复制代码
7 A/ v3 J4 M! H# P: L1 E4 q) C
这个时候你不需要再直接去操作 BSRRL 寄存器了,你只需要知道怎么使用 GPIO_SetBits ()这个函数就可以了。在你对外设的工作原理有一定的了解之后,你再去看固件库函数,基本上函数名字能告诉你这个函数的功能是什么,该怎么使用,这样是不是开发会方便很多。
. X' J% b: _" C, @% s. L' U* f, r* ?) n$ M/ ^6 m6 o! C: }
* }( g3 F, d7 ]/ d; Q
03. STM32固件库与CMSIS标准" m* }" h9 m: d. A
STM32F4 固件库就是函数的集合,这里就涉及到一个 CMSIS 标准的基础知识。经常有人问到 STM32 和 ARM 以及 ARM7 是什么关系这样的问题,其实 ARM 是一个做芯片标准的公司,它负责的是芯片内核的架构设计,而 TI,ST 这样的公司,他们并不做标准,他们是芯片公司,他们是根据 ARM 公司提供的芯片内核标准设计自己的芯片。所以,任何一个做 Cortex-M4 芯片,他们的内核结构都是一样的,不同的是他们的存储器容量,片上外设,IO 以及其他模块的区别。所以你会发现,不同公司设计的Cortex-M4 芯片他们的端口数量,串口数量,控制方法这些都是有区别的,这些资源他们可以根据自己的需求理念来设计。同一家公司设计的多种 Cortex-M4 内核芯片的片上外设也会有很大的区别,比如 STM32F407 和 STM32F429,他们的片上外设就有很大的区别。
5 g) V+ l4 P9 ?3 q' R8 q
& m( \" [) }5 z  r  h既然大家都使用的是 Cortex-M4 核,也就是说,本质上大家都是一样的,这样 ARM 公司为了能让不同的芯片公司生产的 Cortex-M4 芯片能在软件上基本兼容,和芯片生产商共同提出了一套标准 CMSIS 标准(Cortex Microcontroller Software Interface Standard) ,翻译过来是“ARM Cortex™ 微控制器软件接口标准”。ST 官方库就是根据这套标准设计的。. o8 U& V; \0 p0 l9 r1 o. |7 o4 R
8 ^9 W% w# u/ G/ S- [
FXO7GXR$LTSU9P$EA0D6U5E.png + o# u7 N$ o9 G+ h/ A6 n

2 B" U3 }. i! ~+ |CMSIS 分为 3 个基本功能层:& G* L) F) W' ?/ q2 T4 k/ s
1.核内外设访问层:ARM 公司提供的访问,定义处理器内部寄存器地址以及功能函数。
1 U3 i" W* L: q6 q* b" A7 ^2.中间件访问层:定义访问中间件的通用 API。由 ARM 提供,芯片厂商根据需要更新。
5 t- {$ N% d* H; k' Z3.外设访问层:定义硬件寄存器的地址以及外设的访问函数。
* l+ u$ E* g) S
CMSIS 层在整个系统中是处于中间层,向下负责与内核和各个外设直接打交道,向上提供实时操作系统用户程序调用的函数接口。如果没有 CMSIS 标准,那么各个芯片公司就会设计自己喜欢的风格的库函数,而 CMSIS 标准就是要强制规定,芯片生产公司设计的库' P- s: H6 K( a7 [# L: J* H
函数必须按照 CMSIS 这套规范来设计。其实不用这么讲这么复杂的,一个简单的例子,我们在使用 STM32 芯片的时候首先要进$ ?0 l1 `: e7 l' h+ I
行系统初始化,CMSIS 规范就规定,系统初始化函数名字必须为 SystemInit,所以各个芯片公司写自己的库函数的时候就必须用 SystemInit 对系统进行初始化。CMSIS 还对各个外设驱动文件的文件名字规范化,以及函数名字规范化等等一系列规定。上一节讲的函数GPIO_ResetBits 这个函数名字也是不能随便定义的,是要遵循 CMSIS 规范的。# c6 N3 @: ?: y+ V: L7 D
) A6 T$ w( N+ W) j* r  Q; b

% E0 P5 j. h. q; F! K' p9 x04. STM32F4标准固件库下载
6 E, j1 f' L! c! w, M+ u$ ~
这一节内容主要讲解 ST 官方提供的 STM32F4 固件库包的结构。ST 官方提供的固件库完整包可以在官方网站下载。6 X/ U  K; ?$ v) _
9 s. i( }( d% T/ K7 m
1BXS0Z`EGHGL)7N8UWM0FTC.png
2 ^( y7 H9 i7 {
0 w0 L7 R: q0 H7 Y4 `* C! h
下载之后得到文件 STM32F4xx_DSP_StdPeriph_Lib_V1.8.0.zip# \5 _+ k+ Q% k* \0 o8 n
9 Q; l- V0 Y  ^5 {0 Y: n

/ T. v% V0 m7 U3 Q05. STM32F4标准固件库介绍
4 j' b  k  K& n. m; M
解压之后得到以下文件* p9 W) n- a1 S* G( s

( M1 b" v+ A' y7 h/ [
6WC75_S_H~[00A074C`_R9U.png
1 N- o1 _  u8 V: i7 m5 x+ w- {, Q5 H8 t
Libraries 文件夹下面有CMSIS和 STM32F4xx_StdPeriph_Driver 两个目录,这两个目录包含固件库核心的所有子文件夹和文件。' f0 g; F& w% }( z& d( ~! d4 X

. V' Y4 L/ I) \+ N" z6 J( YCMSIS文件夹存放的是符合CMSIS规范的一些文件。包括STM32F4核内外设访问层代码,DSP 软件库,RTOS API,以及 STM32F4 片上外设访问层代码等。我们后面新建工程的时候会从这个文件夹复制一些文件到我们工程。; V: ?( T/ U1 }4 j! p
' v& I: h5 X: k: ~5 _
STM32F4xx_StdPeriph_Driver 放的是 STM32F4 标准外设固件库源码文件和对应的头文件。inc 目录存放的是 stm32f4xx_ppp.h 头文件,无需改动。src 目录下面放的是 stm32f4xx_ppp.c 格式的固件库源码文件。每一个.c 文件和一个相应的.h 文件对应。这里的文件也是固件库外设的关键文件,每个外设对应一组文件。  j, I9 F9 g( K% w

$ s; p6 G0 f/ p5 mLibraries 文件夹里面的文件在我们建立工程的时候都会使用到。
: v! F; G% y5 g) ?# Z1 V2 X
  [! }) k1 Y, D2 |, g3 Y$ }
Project 文件夹下面有两个文件夹。顾名思义,STM32F4xx_StdPeriph_Examples 文件夹下面存放的的 ST 官方提供的固件实例源码,在以后的开发过程中,可以参考修改这个官方提供的实例来快速驱动自己的外设,很多开发板的实例都参考了官方提供的例程源码,这些源码对以后的学习非常重要。STM32F4xx_StdPeriph_Template 文件夹下面存放的是工程模板。
- u( ]/ H1 m9 P: T" @
! I* v/ z0 u4 w6 s* U
Utilities 文件下就是官方评估板的一些对应源码,这个对于本手册学习可以忽略不看。
5 \9 P. }. w; l0 v8 Q+ i8 w# G
4 I8 ?2 L- B" u$ s7 I0 i6 W6 i根目录中还有一个 stm32f4xx_dsp_stdperiph_lib_um.chm 文件,直接打开可以知道,这是一个固件库的帮助文档,这个文档非常有用,只可惜是英文的,在开发过程中,这个文档会经常被使用到。/ I+ {4 P1 t6 n. S
3 V8 E: @/ l' r5 d

1 U* P' b! d$ q' b6 FSTM32F4工程中比较重要的文件; M5 u5 F# i1 I8 [! F2 o6 o! M

# _) U7 e" w  @) @
PTM8~~J{RQR26H9P[WN)L[9.png / m- x3 A6 u. D: m5 d

" ~+ i/ L! c' G7 ~9 u( M; t, A
( w( C6 J0 u0 v4 H% U. u# g
core_cm4.h 文件位于\STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\CMSIS\Include 目录下面的,这个就是 CMSIS 核心文件,提供进入 M4 内核接口,这是 ARM 公司提供,对所有CM4 内核的芯片都一样。你永远都不需要修改这个文件。' P% a! C% S$ Q" ]: @/ I: q
. d. K. n9 G- p0 m9 h: R/ t3 G
stm32f4xx.h 和 system_stm32f4xx.h 文件存放在文件夹\STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\CMSIS\Device\ST\STM32F4xx\Include 下面。
' x& o3 z4 F+ I& |' f4 {9 X! Hsystem_stm32f4xx.h 是片上外设接入层系统头文件。主要是申明设置系统及总线时钟相关的函数。与其对应的源文件 system_stm32f4xx.c 在目录\STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Project\STM32F4xx_StdPeriph_Templates 可以找到。这
( r: Z/ Z& ?, ]- q/ z% a8 d: {" N个里面有一个非常重要的 SystemInit()函数申明,这个函数在我们系统启动的时候都会调用,用来设置系统的整个系统和总线时钟。
% O+ _8 x/ E8 z2 A

4 D- Q! `7 Y9 ~' {stm32f4xx.h 是 STM32F4 片上外设访问层头文件。这个文件就相当重要了,只要你做STM32F4 开发,你几乎时刻都要查看这个文件相关的定义。这个文件打开可以看到,里面非常多的结构体以及宏定义。这个文件里面主要是系统寄存器定义声明以及包装内存操作,同时该文件还包含了一些时钟相关的定义,FPU 和 MPU 单元开启定义,中断相关定义等等。& }$ ~4 Q3 f0 ]% U- ^6 C
$ P' K* R$ m: F3 ~4 ?& r' B1 f
stm32f4xx_it.c,stm32f4xx_it.h 以 及 stm32f4xx_conf.h 等 文 件 , 我 们 可 以 从\STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Project\STM32F4xx_StdPeriph_Templates文件夹中找到。这几个文件我们后面新建工程也有用到。stm32f4xx_it.c 和 stm32f4xx_it.h 里面是用来编写中断服务函数,中断服务函数也可以随意编写在工程里面的任意一个文件里面,个人觉得这个文件没太大意义。9 ^% k4 z" N/ `

6 |+ }! t' A! P+ y2 cstm32f4xx_conf.h 是外设驱动配置文件。文件打开可以看到一堆的#include,这里你建立工程的时候,可以注释掉一些你不用的外设头文件。
2 }* f$ B" L" f

: H% e4 v1 B0 y8 a# \对于上图中的 misc.c,misc.h,stm32f4xx_ppp.c,stm32f4xx_ppp.h 以及 stm32f4xx_rcc.c 和stm32f4xx_rcc.h 文件,这些文件存放在目录 Libraries\STM32F4xx_StdPeriph_Driver。这些文件是 STM32F4 标准的外设库文件。其中 misc.c 和 misc.h 是定义中断优先级分组以及 Systick 定时器相关的函数。stm32f3xx_rcc.c 和 stm32f4xx_rcc.h 是与 RCC 相关的一些操作函数,作用主要是一些时钟的配置和使能。在任何一个 STM32 工程 RCC 相关的源文件和头文件是必须添加的。
) }" O0 F2 k# V. D: e# c, f3 \$ a5 y; N4 [$ W- K" u
对于文件 stm32f4xx_ppp.c 和 stm32f4xx_ppp.h,这就是 stm32F4 标准外设固件库对应的源文件和头文件。包括一些常用外设 GPIO,ADC,USART 等。+ A& G+ W& v. }% C. N; O" D0 U

4 V( O. \) Q' w  G; g" w2 I文件 Application.c 实际就是说是应用层代码。这个文件名称可以任意取了。我们工程中,直接取名为 main.c。
7 H- F, p6 z/ E" M1 X( s' ?& D' G* H4 K4 I3 ~" }. B' k
实际上一个完整的 STM32F4 的工程光有上面这些文件还是不够的。还缺少非常关键的启动文件。STM32F4 的启动文件存放在目录\STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm 下面。对于不同型号的 STM32F4 系列对应启动文件也不一样。我们的开发板是 STM32F407 系列所以我们选择的启动文件为startup_stm32f40_41xxx.s。 启动文件到底什么作用,其实我们可以打开启动文件进去看看。启动文件主要是进行堆栈之类的初始化,中断向量表以及中断函数定义。启动文件要引导进入main 函数。Reset_Handler 中断函数是唯一实现了的中断处理函数,其他的中断函数基本都是死循环。Reset_handler 在我们系统启动的时候会调用,下面让我们看看 Reset_handler 这段代码:5 U6 H7 D* c+ P( L2 Z% V# B" j
4 G  b3 Z6 `  d
  1. <font face="Tahoma"><font size="3">; Reset handler</font></font>
    ; Y! R' E+ p0 [6 s/ q
  2. <font face="Tahoma"><font size="3">Reset_Handler    PROC</font></font>
    . C8 {& X  {: @& ^
  3. <font face="Tahoma"><font size="3">                 EXPORT  Reset_Handler             [WEAK]</font></font>+ ]7 ?0 N/ q2 T) s  I
  4. <font face="Tahoma"><font size="3">        IMPORT  SystemInit</font></font>4 q9 w6 A: @0 H% m! D, r- w
  5. <font face="Tahoma"><font size="3">        IMPORT  __main</font></font>6 L& p9 s0 O9 _: e) e7 K
  6. <font face="Tahoma"><font size="3">
    9 y0 D* l2 h  o  |
  7. </font></font>
      ]' `# K3 T' B
  8. <font face="Tahoma"><font size="3">                 LDR     R0, =SystemInit</font></font>7 S$ \7 q( W# _- ^* i
  9. <font face="Tahoma"><font size="3">                 BLX     R0</font></font>
    2 b3 ]+ A2 B+ ~& Y
  10. <font face="Tahoma"><font size="3">                 LDR     R0, =__main</font></font>
    * T0 ~- O% W" z& s& Z% Q
  11. <font face="Tahoma"><font size="3">                 BX      R0</font></font>
    4 i6 S$ a1 W5 L3 B6 W
  12. <font face="Tahoma"><font size="3">                 ENDP</font></font>
复制代码

+ {) k9 S- n- b' r. y6 b) v- d' X4 P这段代码的作用是在系统复位之后引导进入 main 函数,同时在进入 main 函数之前,首先要调用 SystemInit 系统初始化函数。
8 v) j$ o1 I: n8 d$ s* {+ C3 j- y5 D* V# f) C

/ l5 O& l! K2 q( n- n" N
( E0 E- T) Y4 n! _: r- r+ S
赞 收藏 评论0 发布时间:2022-6-10 19:28

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版