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

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

[复制链接]
STMCU小助手 发布时间:2022-4-3 22:00
01. STM32官方标准固件库简介
1 Z+ e( y! d& R' R5 mST(意法半导体)为了方便用户开发程序,提供了一套丰富的 STM32F4 固件库。( H( f( j  y6 U# G7 _; r3 k- J: Q
9 b! R0 T$ [2 [+ n) o6 H4 \
02. 库开发和寄存器开发的关系
4 \3 t' h' n/ ~) m; H+ i9 Z% F, I很多用户都是从学 51 单片机开发转而想进一步学习 STM32 开发,他们习惯了 51 单片机的寄存器开发方式,突然一个 ST 官方库摆在面前会一头雾水,不知道从何下手。下面我们将通过一个简单的例子来告诉 STM32 固件库到底是什么,和寄存器开发有什么关系?其实一句话就可以概括:固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道,向上提供用户函数调用的接口(API)。
8 c2 G3 t0 U4 L! h8 n" `  V
6 |  B* k3 _; \4 B. A1 d% T! l% {0 a在 51 的开发中我们常常的作法是直接操作寄存器,比如要控制某些 IO 口的状态,我们直接操作寄存器:" u& ^3 [0 p# f+ k
  e! z" S0 z1 W. r4 t  P* d
P0=0x11;
' c2 N0 S/ [7 F/ v' i/ I; y/ n% y0 M9 g5 l
而在 STM32 的开发中,我们同样可以操作寄存器:. v0 z+ v; k; _! `$ t/ {
4 Y' e4 G! y" Z7 r1 p7 \
  1. GPIOF->BSRRL=0x0001; //这里是针对 STM32F4 系列
复制代码
  J0 u% J% t! }2 F- c8 }
这种方法当然可以,但是这种方法的劣势是你需要去掌握每个寄存器的用法,你才能正确使用STM32,而对于 STM32 这种级别的 MCU,数百个寄存器记起来又是谈何容易。于是 ST(意法半导体)推出了官方固件库,固件库将这些寄存器底层操作都封装起来,提供一整套接口(API)供开发者调用,大多数场合下,你不需要去知道操作的是哪个寄存器,你只需要知道调用哪些函数即可。9 o. N/ S& R* E- L" |3 _
+ D2 n+ t! @: e% N( U# X1 F
比如上面的控制 BSRRL 寄存器实现电平控制,官方库封装了一个函数:$ U! F1 D3 @, Y: l' M8 D8 a5 `
' L; Y5 T5 z! x+ ]1 [) S& F# L  X
  1. void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
    ( @3 q7 x, C& x/ ?& ^
  2. {
    - d8 [$ `6 I9 x/ c( ^. q
  3.         GPIOx->BSRRL = GPIO_Pin;
    & S- J' \$ ^/ t  }1 K& A
  4. }
复制代码

: R* h9 s2 E5 T7 x6 o* G& d: C这个时候你不需要再直接去操作 BSRRL 寄存器了,你只需要知道怎么使用 GPIO_SetBits ()这个函数就可以了。在你对外设的工作原理有一定的了解之后,你再去看固件库函数,基本上函数名字能告诉你这个函数的功能是什么,该怎么使用,这样是不是开发会方便很多。
% O2 d% Q8 {+ r* F- O: h6 y6 G* x/ N' v0 \, w% m" ?
03. STM32固件库与CMSIS标准
! s( d8 |4 y3 J, @/ i2 n3 j/ cSTM32F4 固件库就是函数的集合,这里就涉及到一个 CMSIS 标准的基础知识。经常有人问到 STM32 和 ARM 以及 ARM7 是什么关系这样的问题,其实 ARM 是一个做芯片标准的公司,它负责的是芯片内核的架构设计,而 TI,ST 这样的公司,他们并不做标准,他们是芯片公司,他们是根据 ARM 公司提供的芯片内核标准设计自己的芯片。所以,任何一个做 Cortex-M4 芯片,他们的内核结构都是一样的,不同的是他们的存储器容量,片上外设,IO 以及其他模块的区别。所以你会发现,不同公司设计的Cortex-M4 芯片他们的端口数量,串口数量,控制方法这些都是有区别的,这些资源他们可以根据自己的需求理念来设计。同一家公司设计的多种 Cortex-M4 内核芯片的片上外设也会有很大的区别,比如 STM32F407 和 STM32F429,他们的片上外设就有很大的区别。# i% D9 a2 s/ h8 Y
# q+ l; ~! f) o9 D1 u3 s0 m5 f5 A1 N
既然大家都使用的是 Cortex-M4 核,也就是说,本质上大家都是一样的,这样 ARM 公司为了能让不同的芯片公司生产的 Cortex-M4 芯片能在软件上基本兼容,和芯片生产商共同提出了一套标准 CMSIS 标准(Cortex Microcontroller Software Interface Standard) ,翻译过来是“ARM Cortex™ 微控制器软件接口标准”。ST 官方库就是根据这套标准设计的。
* J. l" F. c8 V0 v' }& k) V: m/ ?0 ]: t: n; {! R7 F- o! i
3I@L[Q1B_G9C@Q)IR2[YGLK.png
& M4 h2 k9 E, K! v" n
) d% u4 Z8 L& |8 D0 @( h% |, K1 m) B8 iCMSIS 分为 3 个基本功能层:4 l. o) m  Z2 u. G' c7 k6 J& @

  Q7 R9 S& q7 c6 u, S% @核内外设访问层:ARM 公司提供的访问,定义处理器内部寄存器地址以及功能函数。
) r7 G* i  |" \8 }+ M5 E( h中间件访问层:定义访问中间件的通用 API。由 ARM 提供,芯片厂商根据需要更新。' A$ s3 _5 ~) Y4 A/ v
外设访问层:定义硬件寄存器的地址以及外设的访问函数。
$ s: q4 R4 e6 xCMSIS 层在整个系统中是处于中间层,向下负责与内核和各个外设直接打交道,向上提供实时操作系统用户程序调用的函数接口。如果没有 CMSIS 标准,那么各个芯片公司就会设计自己喜欢的风格的库函数,而 CMSIS 标准就是要强制规定,芯片生产公司设计的库
0 H. l' }$ }/ x) L函数必须按照 CMSIS 这套规范来设计。其实不用这么讲这么复杂的,一个简单的例子,我们在使用 STM32 芯片的时候首先要进
# ]( n' A$ J' M7 @  Y行系统初始化,CMSIS 规范就规定,系统初始化函数名字必须为 SystemInit,所以各个芯片公司写自己的库函数的时候就必须用 SystemInit 对系统进行初始化。CMSIS 还对各个外设驱动文件的文件名字规范化,以及函数名字规范化等等一系列规定。上一节讲的函数GPIO_ResetBits 这个函数名字也是不能随便定义的,是要遵循 CMSIS 规范的。
5 c. ]% r; t, t  j+ S3 a2 ?
8 Y/ X! @! f- s' w0 A04. STM32F4标准固件库下载
* p: F$ b" g$ ]8 u3 C这一节内容主要讲解 ST 官方提供的 STM32F4 固件库包的结构。ST 官方提供的固件库完整包可以在官方网站下载。0 G# t0 J' W2 b, i
2 P* {. H  E- E, T! B& N% f% v
官方下载网址:https://www.st.com/en/embedded-s ... eral-libraries.html" h* T6 q0 ], M$ _( J, r

! v; P: F# E( \! u7 r  ?! q D$W4RVQEOP)DS98QKP)1[~H.png
# Q8 k' E+ j/ Y% `7 x/ v8 @$ ?& m# r! U! m

: v7 {2 S2 |: t下载之后得到文件 STM32F4xx_DSP_StdPeriph_Lib_V1.8.0.zip0 b( C7 Q8 b$ q; V. F) C- y

# c/ @5 ?6 ~4 Q5 _+ o05. STM32F4标准固件库介绍1 }/ N# N) W# M% f* t
解压之后得到以下文件# q8 {6 ]0 ]! ]9 ]! Q; P+ a
6 @5 [0 {6 C' a3 \7 ~) s) w
PF7V`4R47M$FBY(USW8EL[T.png 7 d( |- C( @3 A8 `( O! h

/ J! z, u* g) L1 w4 JLibraries 文件夹下面有CMSIS和 STM32F4xx_StdPeriph_Driver 两个目录,这两个目录包含固件库核心的所有子文件夹和文件。
7 ?$ t' [6 C7 U9 g: t3 ?+ ~4 y" d& G
CMSIS文件夹存放的是符合CMSIS规范的一些文件。包括STM32F4核内外设访问层代码,DSP 软件库,RTOS API,以及 STM32F4 片上外设访问层代码等。我们后面新建工程的时候会从这个文件夹复制一些文件到我们工程。
- ?" p) j& a8 {- g% X; P- u6 K( w1 u
STM32F4xx_StdPeriph_Driver 放的是 STM32F4 标准外设固件库源码文件和对应的头文件。inc 目录存放的是 stm32f4xx_ppp.h 头文件,无需改动。src 目录下面放的是 stm32f4xx_ppp.c 格式的固件库源码文件。每一个.c 文件和一个相应的.h 文件对应。这里的文件也是固件库外设的关键文件,每个外设对应一组文件。* l& n0 l' @/ H5 V, D0 N6 \$ l" E

+ E0 Y3 ?/ o+ X2 ^  q" `- k& GLibraries 文件夹里面的文件在我们建立工程的时候都会使用到。5 f  z4 F# P8 j) z/ u* m' f+ ^

' U/ X' k, [% N) S4 z) BProject 文件夹下面有两个文件夹。顾名思义,STM32F4xx_StdPeriph_Examples 文件夹下面存放的的 ST 官方提供的固件实例源码,在以后的开发过程中,可以参考修改这个官方提供的实例来快速驱动自己的外设,很多开发板的实例都参考了官方提供的例程源码,这些源码对以后的学习非常重要。STM32F4xx_StdPeriph_Template 文件夹下面存放的是工程模板。
6 [( q7 w  x) Q- `* R- ?4 B0 E7 N
: Q6 O4 C+ W- x/ L3 Z7 M' Q$ s- YUtilities 文件下就是官方评估板的一些对应源码,这个对于本手册学习可以忽略不看。  p* M7 O+ H1 A! i1 B6 H1 p2 p( Y) l
! G6 Q  t$ e/ G7 s/ Z8 F3 u) t
根目录中还有一个 stm32f4xx_dsp_stdperiph_lib_um.chm 文件,直接打开可以知道,这是一个固件库的帮助文档,这个文档非常有用,只可惜是英文的,在开发过程中,这个文档会经常被使用到。0 u5 {2 p9 K' E2 x( _
3 b/ l3 z2 Z/ C& ^" z% O, K$ @$ j
STM32F4工程中比较重要的文件
- Y3 s; g) W: c" a
: n, s2 o  \% ^2 s4 j6 [0 S$ @
(`}LZMYUN$}_OL)5QT]V.png . l6 @& H! z! ]0 E; l& R: i! R2 @0 _
2 R* H6 F' r  u
core_cm4.h 文件位于\STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\CMSIS\Include 目录下面的,这个就是 CMSIS 核心文件,提供进入 M4 内核接口,这是 ARM 公司提供,对所有CM4 内核的芯片都一样。你永远都不需要修改这个文件。
1 d8 z! t2 J  f# o# f( R# u1 C8 k/ P- a9 H6 C
stm32f4xx.h 和 system_stm32f4xx.h 文件存放在文件夹\STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\CMSIS\Device\ST\STM32F4xx\Include 下面。8 D  p9 u" E( m% i$ A, A
system_stm32f4xx.h 是片上外设接入层系统头文件。主要是申明设置系统及总线时钟相关的函数。与其对应的源文件 system_stm32f4xx.c 在目录\STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Project\STM32F4xx_StdPeriph_Templates 可以找到。这, B0 f" V2 t- f0 z6 {# m; [" r* G
个里面有一个非常重要的 SystemInit()函数申明,这个函数在我们系统启动的时候都会调用,用来设置系统的整个系统和总线时钟。% R1 I& X" ?8 v
0 Y& r+ q0 A- I1 [$ e& T2 w
stm32f4xx.h 是 STM32F4 片上外设访问层头文件。这个文件就相当重要了,只要你做STM32F4 开发,你几乎时刻都要查看这个文件相关的定义。这个文件打开可以看到,里面非常多的结构体以及宏定义。这个文件里面主要是系统寄存器定义声明以及包装内存操作,同时该文件还包含了一些时钟相关的定义,FPU 和 MPU 单元开启定义,中断相关定义等等。
( k2 a; W5 X' I: {1 e  B0 p- s0 h8 y' m& d# O
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 里面是用来编写中断服务函数,中断服务函数也可以随意编写在工程里面的任意一个文件里面,个人觉得这个文件没太大意义。# P, O* u8 y! c7 }) Y8 g& [% j5 D

7 M# n3 ]  ^( Y# C. T: ustm32f4xx_conf.h 是外设驱动配置文件。文件打开可以看到一堆的#include,这里你建立工程的时候,可以注释掉一些你不用的外设头文件。
+ Q! l7 h) Q% F8 d$ [, z5 Y" E- j/ u6 v' j7 f3 d+ e6 O
对于上图中的 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 相关的源文件和头文件是必须添加的。5 F* y' r& F3 \1 H( Z4 T
* W* I  |. ~" \4 \2 d
对于文件 stm32f4xx_ppp.c 和 stm32f4xx_ppp.h,这就是 stm32F4 标准外设固件库对应的源文件和头文件。包括一些常用外设 GPIO,ADC,USART 等。
* L; L$ `: O4 X" m# |$ a% {" b- [3 Z, D
文件 Application.c 实际就是说是应用层代码。这个文件名称可以任意取了。我们工程中,直接取名为 main.c。! L! @: w% F* L. f7 \6 Y, U$ R! c: _
  H4 w" k; r+ T7 D! ?* o
实际上一个完整的 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 l( |: B& Y. M0 T6 ?! M- B' i
$ U5 e9 J# I: s: Z2 K( U, i
  1. ; Reset handler" _+ K1 w; M) D, \2 y  y- @
  2. Reset_Handler    PROC" N' K! e* _; ]9 s- |6 e' e
  3.                  EXPORT  Reset_Handler             [WEAK]& m6 P, J6 b0 }  Z/ y- g8 N
  4.         IMPORT  SystemInit7 ^( B7 @5 k! ^2 z6 @9 p
  5.         IMPORT  __main
    6 q6 H. F' u/ b/ F

  6. 7 X# p( T+ m9 o8 K" t- Y0 `
  7.                  LDR     R0, =SystemInit
    * O7 F' h+ r4 B( ?# [& O5 D$ Y
  8.                  BLX     R0$ I( l# e4 M3 C0 N6 u
  9.                  LDR     R0, =__main" p7 ]  Y9 P( t$ C% q  d
  10.                  BX      R0
    ! @* k4 Y4 b# P7 y2 g/ m1 ~* R
  11.                  ENDP
复制代码

! `! ?3 J- ?* O5 R+ Y+ I- N2 L
! o9 `( U) k3 v% j! A这段代码的作用是在系统复位之后引导进入 main 函数,同时在进入 main 函数之前,首先要调用 SystemInit 系统初始化函数。
9 w8 ]$ \* }9 V0 h1 U" G& R( h4 h% K/ h4 h  C8 M

3 f: p8 _3 h. U6 M
收藏 2 评论0 发布时间:2022-4-3 22:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版