STM32固件库是STMicroelectronics公司提供的一种软件开发工具,用于在STM32微控制器上进行固件开发。该库为STM32微控制器的外设提供了一组标准的应用程序接口(API),简化了软件开发的流程,使开发者可以更加专注于应用程序的开发。该库主要包括以下几个部分:
CMSIS(Cortex Microcontroller Software Interface Standard):提供了与ARM Cortex-M处理器内核相关的一些标准接口函数和宏定义,例如NVIC(Nested Vectored Interrupt Controller)中断控制器、系统时钟控制器等。
HAL库:HAL是硬件抽象层(Hardware Abstraction Layer)的缩写,它是一种针对不同微控制器平台的通用API库,封装了硬件操作的底层细节,使得开发者可以更加方便地访问和操作硬件资源。HAL库为开发者提供了一系列的API函数,例如GPIO(General Purpose Input/Output)口控制、定时器、USART(Universal Synchronous/Asynchronous Receiver/Transmitter)串口通信等。
LL库:LL是低层(Low Layer)的缩写,它是HAL库的底层实现,提供了对芯片内部寄存器的直接访问,因此相比HAL库更加灵活。开发者可以通过LL库来实现一些高级功能,例如设置时钟分频器、控制DMA(Direct Memory Access)数据传输等。
USB库:用于实现USB(Universal Serial Bus)设备和主机的通信,包括USB设备的枚举、数据传输、电源管理等。
BSP库:BSP(Board Support Package)是针对特定开发板的支持包,提供了与该开发板相关的一些API函数和底层驱动程序,例如LCD屏幕、按键、LED等。
开发者可以根据具体应用场景选择使用STM32固件库中的哪些部分。例如,如果只需要使用GPIO口控制和USART串口通信,可以只使用HAL库;如果需要实现更为灵活和高级的功能,可以使用LL库;如果需要实现USB设备和主机的通信,可以使用USB库等等。
STM32固件库是一个开源的软件包,可在STMicroelectronics公司的官方网站上下载。它提供了一系列的驱动程序和应用程序接口,用于访问微控制器的各种外设,包括GPIO、UART、SPI、I2C、定时器、中断控制器、ADC、DAC等等。此外,STM32固件库还提供了一些常用的数据结构和算法,例如队列、堆栈、排序和搜索等,以便开发者可以更加方便地实现各种应用程序。
STM32固件库支持C语言编程,可以通过使用Keil、IAR等集成开发环境(IDE)进行编译和调试。开发者可以使用STM32固件库提供的API来访问微控制器的外设,并编写自己的应用程序。由于STM32固件库提供了一组标准的API,因此开发者可以轻松地从一个STM32微控制器移植到另一个STM32微控制器上,从而加快了软件开发的速度。
总的来说,STM32固件库是STM32微控制器软件开发的一个重要工具,它提供了一组标准的API和驱动程序,简化了软件开发的流程,提高了开发效率。如果你想在STM32微控制器上进行软件开发,那么STM32固件库是一个值得尝试的工具。
CMSIS(Cortex Microcontroller Software Interface Standard)是由ARM公司提出的一种嵌入式系统软件接口标准,旨在为Cortex-M处理器提供通用的软件开发接口。CMSIS可以简化嵌入式系统开发的过程,降低开发难度和成本。下面我们对CMSIS的标准和库层次关系进行详细介绍。
标准层次结构
CMSIS标准层次结构定义了Cortex-M处理器核心与软件之间的接口。标准层次结构包含以下组成部分:
(1)Core层
Core层是CMSIS的核心部分,它提供了与Cortex-M处理器内核相关的功能。Core层包括以下模块:
NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器):处理器内核的中断控制器,用于管理中断请求和处理。
SCB(System Control Block,系统控制块):提供一些关键的系统控制功能,如系统时钟、系统异常处理等。
SysTick:提供一个系统时钟计数器,用于操作系统的实现和其他定时任务。
MPU(Memory Protection Unit,内存保护单元):提供一种硬件机制,可在系统中保护指定的内存区域。
(2)DSP库层
DSP库层提供数字信号处理函数和算法,如FFT、滤波器、向量运算等。这些函数和算法可用于音频、图像处理等应用。CMSIS DSP库是基于C语言实现的,并针对Cortex-M处理器进行了优化。
(3)RTOS层
RTOS层提供支持实时操作系统(RTOS)的API,例如任务管理、信号量、队列等。这些API可用于构建嵌入式系统中的多任务应用程序。CMSIS RTOS API是基于C语言实现的,并支持多种RTOS内核。
(4)Device层
Device层提供与具体设备相关的功能,例如GPIO、UART、SPI等。每个设备都有自己的设备头文件和寄存器映射。Device层是由芯片厂商提供的,不同的芯片可能提供不同的设备层接口。
(5)Startup文件
Startup文件提供启动代码,例如复位向量、中断向量表等。Startup文件是由芯片厂商提供的,不同的芯片可能需要不同的Startup文件。
(6)编译器层
编译器层(Compiler abstraction layer)是最底层的层次之一,包括以下内容:
①数据类型定义:定义了通用的数据类型,例如 uint32_t、int16_t、float 等,这些数据类型在不同的编译器和处理器上具有相同的定义,可以提高代码的可移植性。
②编译器指令定义:定义了一些编译器相关的指令和语法,例如 __asm、__inline、__packed 等,可以使代码更加高效和可靠。
③内联汇编:提供了一些内联汇编函数,使程序员可以直接在 C/C++ 代码中嵌入汇编指令,以实现特定的功能。
④编译器特定的实现:针对不同的编译器,提供了特定的实现代码,以便在不同的编译器上编译和运行代码。
编译器层是 CMSIS 库的底层,主要提供了与编译器相关的接口和实现,为上层的库层和应用层提供了基础支持。
STM32 标准库可以从官网获得,也可以直接从本书的配套资料得到。本书讲解的例程全部采用3.5.0 库文件。以下内容请大家打开 STM32 标准库文件配合阅读。解压库文件后进入其目录:STM32F10x_StdPeriph_Lib_V3.5.0\软件库各文件夹的内容说明见图 ST 标准库。目录: STM32F10x_StdPeriph_Lib_V3.5.0\
• Libraries:文件夹下是驱动库的源代码及启动文件,这个非常重要,我们要使用的固件库就在这个文件夹里面。
• Project :文件夹下是用驱动库写的例子和工程模板,其中那些为每个外设写好的例程对我们非常有用,我们在学习的时候就可以参考这里面的例程,非常全面,简直就是穷尽了外设的所有功能。
• Utilities:包含了基于 ST 官方实验板的例程,不需要用到,略过即可。
• stm32f10x_stdperiph_lib_um.chm:库帮助文档,这个很有用,不喜欢直接看源码的可以在合理查询每个外设的函数说明,非常详细。这是一个已经编译好的 HTML 文件,主要讲述如何使用驱动库来编写自己的应用程序。
说得形象一点,这个 HTML 就是告诉我们: ST 公司已经为你写好了每个外设的驱动了,想知道如何运用这些例子就来向我求救吧。不幸的是,这个帮助文档是英文的,这对很多英文不好的朋友来说是一个很大的障碍。在使用库开发时,我们需要把 libraries 目录下的库函数文件添加到工程中,并查阅库帮助文档来了解 ST 提供的库函数,这个文档说明了每一个库函数的使用方法。进 入 Libraries 文 件 夹 看 到, 关 于 内 核 与 外 设 的 库 文 件 分 别 存 放 在 CMSIS 和STM32F10x_StdPeriph_Driver 文件夹中。
STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\文件夹展开内容见图 CMSIS 文件夹内容。
目录:Libraries\CMSIS\
6.3.1.1 内核相关文件
在 CoreSupport 文件夹中有 core_cm3.c 和 core_cm3.h 两个文件。 Core_cm3.h 头文件里面实现了内核的寄存器映射,对应外设头文件 stm32f10x.h,区别就是一个针对内核的外设,一个针对片上(内核之外)的外设。
core_cm3.c 文件实现了一下操作内核外设寄存器的函数,用的比较少。我们还需要了解的是core_cm3.h 头文件中包含了“stdint.h”这个头文件,这是一个 ANSI C 文件,是独立于处理器之外的,就像我们熟知的 C 语言头文件“stdio.h”文件一样。位于 RVMDK 这个软件的安装目录下,主要作用是提供一些类型定义。
/* fastest minimum-width signed integer types */
typedef signed int int_fast8_t;
typedef signed int int_fast16_t;
typedef signed int int_fast32_t;
typedef signed __INT64 int_fast64_t;
/* fastest minimum-width unsigned integer types */
typedef unsigned int uint_fast8_t;
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;
typedef unsigned __INT64 uint_fast64_t;
这些新类型定义屏蔽了在不同芯片平台时,出现的诸如 int 的大小是 16 位,还是 32位的差异。所以在我们以后的程序中,都将使用新类型如 uint8_t 、 uint16_t 等。在稍旧版的程序中还经常会出现如 u8、 u16、 u32 这样的类型,分别表示的无符号的 8 位、 16 位、32 位整型。初学者碰到这样的旧类型感觉一头雾水,它们定义的位置在 STM32f10x.h 文件中。建议在以后的新程序中尽量使用 uint8_t 、 uint16_t 类型的定义。
6.3.1.2 启动文件
启动文件放在 startup/arm 这个文件夹下面,这里面启动文件有很多个,不同型号的单片机用的启动文件不一样。
开发板中用的 STM32F103VET6 或者 STM32F103ZET6 的 FLASH 都是 512K,属于基本型的大容量产品,启动文件统一选择 startup_stm32f10x_hd.s。
stm32f10x.h
这个头文件实现了片上外设的所以寄存器的映射,是一个非常重要的头文件,在内核中与之想对应的头文件是 core_cm3.h。
system_stm32f10x.c
csystem_stm32f10x.c 文件实现了 STM32 的时钟配置,操作的是片上的 RCC 这个外设。系统在上电之后,首选会执行由汇编编写的启动文件,启动文件中的复位函数中调用的 SystemInit 函数就在这个文件里面定义。调用完之后,系统的时钟就被初始化成 72M。如果后面我们需要重新配置系统时钟,我们就可以参考这个函数重写。为了维持库的完整性,我们不会直接在这个文件里面修改时钟配置函数。
STM32F10x_StdPeriph_Driver 文件夹是针对STM32F10x系列微控制器所提供的标准外设库,是ST公司为了方便开发者使用STM32F10x系列微控制器的外设功能而提供的软件包。
这个文件夹包含了许多的源代码文件和头文件,这些文件涵盖了STM32F10x系列微控制器的各种外设功能,例如GPIO、ADC、USART、SPI、I2C、TIM等。这些源代码文件和头文件提供了丰富的API接口,开发者可以通过调用这些API接口来使用STM32F10x系列微控制器的各种外设功能。
此外,STM32F10x_StdPeriph_Driver 文件夹中还提供了一些示例程序,这些示例程序可以帮助开发者更好地理解如何使用STM32F10x系列微控制器的外设功能,同时也可以作为开发者自己开发应用程序的参考。
总之,STM32F10x_StdPeriph_Driver 文件夹是STM32F10x系列微控制器开发中非常重要的软件包,它提供了丰富的API接口和示例程序,方便开发者更好地使用STM32F10x系列微控制器的外设功能,从而加速开发周期。
进入 libraries 目录下的 STM32F10x_StdPeriph_Driver 文件夹,见图外设驱动。
STM32F10x_StdPeriph_Driver 文件夹下有 inc(include 的缩写)跟 src(source 的简写)这两个文件夹,这里的文件属于 CMSIS 之外的的、芯片片上外设部分。 src 里面是每个设备外设的驱动源程序, inc 则是相对应的外设头文件。 src 及 inc 文件夹是 ST 标准库的主要内容,甚至不少人直接认为 ST 标准库就是指这些文件,可见其重要性。
在 src 和 inc 文件夹里的就是 ST 公司针对每个 STM32 外设而编写的库函数文件,每个外设对应一个.c 和.h 后缀的文件。我们把这类外设文件统称为: stm32f10x_ppp.c 或 stm32f10x_ppp.h 文件,PPP 表示外设名称。如在上一章中我们自建的 stm32f10x_gpio.c 及 stm32f10x_gpio.h 文件,就属于这一类。
如针对模数转换 (ADC) 外设,在 src 文件夹下有一个 stm32f10x_adc.c 源文件,在 inc 文件夹下有一个 stm32f10x_adc.h 头文件,若我们开发的工程中用到了 STM32 内部的 ADC,则至少要把这两个文件包含到工程里。
这两个文件夹中,还有一个很特别的 misc.c 文件,这个文件提供了外设对内核中的 NVIC(中断向量控制器) 的访问函数,在配置中断时,我们必须把这个文件添加到工程中。
6.3.3.1 stm32f10x_it.c文件
这个文件包含了中断处理函数的实现。当一个外部事件(如定时器计数器满、串口接收数据等)触发了一个中断,系统就会执行相应的中断处理函数来响应这个事件。这个文件中包含了这些处理函数的实现,例如 TIMx_IRQHandler、USARTx_IRQHandler等。这些函数中会根据具体的事件类型执行相应的操作,例如清除中断标志位、读取接收数据等等。
6.3.3.2 system_stm32f10x.c文件
这个文件包含了系统初始化函数的实现。在系统启动时,需要进行一些基本的初始化操作,例如配置系统时钟、启用外设时钟、设置中断向量表等等。这些操作会在系统初始化函数中完成。这个文件中的函数主要有SystemInit、SystemCoreClockUpdate等。其中,SystemInit函数会在启动时自动执行,用于进行最基本的系统初始化;SystemCoreClockUpdate函数则用于更新系统时钟频率,以便应对系统时钟频率改变的情况。
6.3.3.3 stm32f10x_conf.h文件
stm32f10x_conf.h:这个文件被包含进 stm32f10x.h 文件。当我们使用固件库编程的时候,如果需要某个外设的驱动库,就需要包含该外设的头文件: stm32f10x_ppp.h,包含一个还好,如果是用了多外设,就需要包含多个头文件,这不仅影响代码美观也不好管理,现我们用一个头文件 stm32f10x_conf.h 把这些外设的头文件都包含在里面,让这个配置头文件统一管理这些外设的头文件,我们在应用程序中只需要包含这个配置头文件即可,我们又知道这个头文件在stm32f10x.h 的最后被包含,所以最终我们只需要包含 stm32f10x.h 这个头文件即可,非常方便。Stm32f10x_conf.h 见代码清单: 标准库-2。默认情况下是所以头文件都被包含,没有被注释掉。我们也可以把不要的都注释掉,只留下需要使用的即可。
/* Includes ------------------------------------------------------------------*/
/* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */
#include "stm32f10x_adc.h"
#include "stm32f10x_bkp.h"
#include "stm32f10x_can.h"
#include "stm32f10x_cec.h"
#include "stm32f10x_crc.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_dbgmcu.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_fsmc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_iwdg.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_sdio.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_wwdg.h"
#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
stm32f10x_conf.h 这个文件还可配置是否使用“断言”编译选项
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function which reports
* the name of the source file and the source line number of the call
* that failed. If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
在 ST 标准库的函数中,一般会包含输入参数检查,即上述代码中的“assert_param”宏,当参数不符合要求时,会调用“assert_failed”函数,这个函数默认是空的。实际开发中使用断言时,先通过定义 USE_FULL_ASSERT 宏来使能断言,然后定义“assert_failed”函数,通常我们会让它调用 printf 函数输出错误说明。使能断言后,程序运行时会检查函数的输入参数,当软件经过测试,可发布时,会取消 USE_FULL_ASSERT 宏来去掉断言功能,使程序全速运行。
前面向大家简单介绍了各个库文件的作用,库文件是直接包含进工程即可,丝毫不用修改,而有的文件就要我们在使用的时候根据具体的需要进行配置。接下来从整体上把握一下各个文件在库工程中的层次或关系,这些文件对应到 CMSIS 标准架构上。
图库各文件关系描述了 STM32 库各文件之间的调用关系,在实际的使用库开发工程的过程中,我们把位于 CMSIS 层的文件包含进工程,除了特殊系统时钟需要修改 system_stm32f10x.c,其它文件丝毫不用修改,也不建议修改。对于位于用户层的几个文件,就是我们在使用库的时候,针对不同的应用对库文件进行增删(用条件编译的方法增删)和改动的文件。
•《STM32F10X-中文参考手册》
这个文件全方位介绍了 STM32 芯片的各种片上外设,它把 STM32 的时钟、存储器架构、及各种外设、寄存器都描述得清清楚楚。当我们对 STM32 的外设感到困惑时,可查阅这个文档。以直接配置寄存器方式开发的话,查阅这个文档寄存器部分的频率会相当高,但这样效率太低了。
•《STM32 规格书》
本文档相当于 STM32 的 datasheet,包含了 STM32 芯片所有的引脚功能说明及存储器架构、芯片外设架构说明。后面我们使用 STM32 其它外设时,常常需要查找这个手册,了解外设对应到 STM32 的哪个 GPIO 引脚。
•《Cortex™-M3 内核编程手册》
本文档由 ST 公司提供,主要讲解 STM32 内核寄存器相关的说明,例如系统定时器、 NVIC 等核外设的寄存器。这部分的内容是《STM32F10X-中文参考手册》没涉及到的内核部分的补充。相对来说,本文档虽然介绍了内核寄存器,但不如以下两个文档详细,要了解内核时,可作为以下两个手册的配合资料使用。
•《Cortex-M3 权威指南》
这个手册是由 ARM 公司提供的,它详细讲解了 Cortex 内核的架构和特性,要深入了解 Cortex-M 内核,这是首选,经典中的经典。这个手册也被翻译成中文,出版成书,我们配套的资料里面有提供中文版的电子版。
•《stm32f10x_stdperiph_lib_um.chm》
这个就是本章提到的库的帮助文档,在使用库函数时,我们最好通过查阅此文件来了解标准库提供了哪些外设、函数原型或库函数的调用的方法。也可以直接阅读源码里面的函数的函数说明。
STM32库函数是针对ST公司的STM32系列微控制器所提供的一套软件库函数,可以用于快速开发STM32芯片的应用程序。STM32库函数包含了一系列的API函数,涵盖了STM32芯片的各个方面,包括GPIO控制、中断处理、定时器、串口、SPI、I2C等常见的外设驱动,以及一些常用的算法和数据结构库函数。
使用STM32库函数可以大大简化开发人员的工作,避免繁琐的寄存器配置,减少开发周期。同时,由于这些库函数都经过了严格的测试和优化,因此可以保证程序的稳定性和可靠性。
STM32库函数的使用需要先进行初始化,在初始化后,可以调用相应的API函数来控制各种外设和进行数据处理。例如,使用库函数控制GPIO输出可以通过如下代码实现:
#include "stm32f10x.h"
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_0);
while (1)
{
}
}
在上述代码中,首先包含了相关的库头文件,然后进行GPIO初始化和设置,最后输出高电平。
需要注意的是,STM32库函数的具体使用方式和API函数的命名规则可能会因不同的STM32系列微控制器而略有不同,因此在使用时需要查看相关的文档和资料。
STM32的公司提供了很多的库函数,我们在使用时只需要去查对应的帮助文档就能了解对应库函数对应的功能。
打开库帮助文档《stm32f10x_stdperiph_lib_um.chm》见图
层层打开文档的目录标签:
标签目录:
Modules\STM32F10x_StdPeriph_Driver\
可看到 STM32F10x _StdPeriph_Driver 标签下有很多外设驱动文件的名字 MISC、ADC、BKP、CAN等标签。我们试着查看 GPIO 的“位设置函数 GPIO_SetBits”看看,
打开标签:
标签目录: Modules\STM32F10x_StdPeriph_Driver\GPIO\Functions\GPIO_SetBits 见图
利用这个文档,我们即使没有去看它的具体源代码,也知道要怎么利用它了。如 GPIO_SetBits,函数的原型为 void GPIO_SetBits(GPIO_TypeDef * GPIOx , uint16_t GPIO_Pin)。它的功能是:输入一个类型为 GPIO_TypeDef 的指针 GPIOx 参数,选定要控制的 GPIO 端口;输入GPIO_Pin_x 宏,其中 x 指端口的引脚号,指定要控制的引脚。
其中输入的参数 GPIOx 为 ST 标准库中定义的自定义数据类型,这两个传入参数均为结构体指针。初学时,我们并不知道如 GPIO_TypeDef 这样的类型是什么意思,可以点击函数原型中带下划线的 GPIO_TypeDef 就可以查看这个类型的声明了。
目录
6.1 初识STM32标准库
6.2 CMSIS标准及库层次关系
6.3 库目录、文件简介
6.3.1 CMSIS文件
6.3.2 STM32F10x_StdPeriph_Driver文件夹
6.3.3 stm32f10x_it.c,system_stm32f10x.c,stm32f10x_conf.h文件
6.4 库各文件间的关系
6.5 学会使用帮助文档
6.6 初识库函数
就这样初步了解了一下库函数,读者就可以发现 STM32 的库是写得很优美的。每个函数和数据类型都符合见名知义的原则,当然,这样的名称写起来特别长,而且对于我们来说要输入这么长的英文,很容易出错,所以在开发软件的时候,在用到库函数的地方,直接把库帮助文档中的函数名称复制粘贴到工程文件就可以了。而且,配合 MDK 软件的代码自动补全功能,可以减少输入量。
谢谢阅读!