STM32初识HAL库(下载和使用)

初识HAL库(了解)

ST 为了方便用户开发 STM32芯片开发提供了三种库:

  • 标准外设库 (Standard Peripheral Libraries)
  • HAL库(硬件抽象层):Hardware Abstraction Layer
  • LL库:Low Layer

请添加图片描述

一、获取STM32Cube固件包

方式一:ST官网( 意法半导体-STMicroelectronics )搜索STM32Cube

请添加图片描述

选择你需要的stm32cube的文件包(根据你的硬件型号进行选择,我的型号是stm32F108c)
请添加图片描述

新页面往下滑。选择要下载的版本

请添加图片描述

或者使用git进行代码拉取(这里拉取的是v1.8.0的版本)

git clone http://github.com/STMicroelectronics/STM32CubeF1.git -b v1.8.0 --depth 1

方式二:开发板A盘资料:A 盘→8,STM32 参考资料→1,STM32CubeXX固件包

二、STM32文件结构分布

要想学会stm32hal库首先要了解总体的文件架构,总体架构分为三部分 MCU硬件层CMSIS接口层用户程序层

CMSIS (微控制器软件接口标准):Cortex Microcontroller Software Interface Standard,是由ARM和与其合作的芯片厂商、软件工具厂商,共同制定的标准

以下就是各个文件描述

三、STM32Cube固件库文件简介

请添加图片描述
其中STM32Cube固件库文件中最重要的是Drivers和Middlewares文件夹中的文件和了解project文件夹

Drivers文件夹介绍:

请添加图片描述
在这里插入图片描述

BSP文件夹

存放开发板板级支持包驱动代码,如各种外设驱动
在这里插入图片描述

CMSIS文件夹

在这里插入图片描述
在这里插入图片描述

STM32F1xx_HAL_Driver文件夹

在这里插入图片描述
文件介绍
在这里插入图片描述

HAL库API函数和变量命名规则
文件名stm32f1xx_hal_ppp .(c/h)stm32f1xx_hal_ppp .(c/h)
函数名HAL_PPP_FunctionHAL_PPP_Function
外设句柄PPP_HandleTypeDef
外设工作参数初始化结构体PPP_InitTypeDefPPP_InitTypeDef
配置参数结构体PPP_ YyyyConfTypeDefPPP_ YyyyConfTypeDef

初始化/反初始化函数:HAL_PPP_Init(), HAL_PPP_DeInit()
外设读写函数:HAL_PPP_Read(),HAL_PPP_Write(),HAL_PPP_Transmit(), HAL_PPP_Receive()
控制函数:HAL_PPP_Set (),HAL_PPP_Get ()
状态和错误:HAL_PPP_GetState (), HAL_PPP_GetError ()

HAL库对寄存器位操作的相关宏定义
宏定义结构用途
__HAL_PPP_ENABLE_IT(HANDLE, INTERRUPT)使能外设中断
__HAL_PPP_DISABLE_IT(HANDLE,INTERRUPT)禁用外设中断
__HAL_PPP_GET_IT (HANDLE, __ INTERRUPT __)获取外设某一中断源
__HAL_PPP_CLEAR_IT (HANDLE, __ INTERRUPT __)清除外设中断
__HAL_PPP_GET_FLAG (HANDLE, FLAG)获取外设的状态标记
__HAL_PPP_CLEAR_FLAG (HANDLE, FLAG)清除外设的状态标记
__HAL_PPP_ENABLE(HANDLE)使能某一外设
__HAL_PPP_DISABLE(HANDLE)禁用某一外设
__HAL_PPP_XXXX (HANDLE, PARAM)针对外设的特殊操作
_HAL_PPP_GET IT_SOURCE (HANDLE, __INTERRUPT __)检查外设的中断源
HAL库回调函数
回调函数举例
HAL_PPP_MspInit() / _MspDeInit()举例: HAL_USART_MspInit()会被HAL_PPP_Init() 函数调用,该函数主要用于存放外设使用到的GPIO、CLOCK、NVIC、DMA等初始化代码
HAL_PPP_ProcessCpltCallback举例: HAL_USART_TxCpltCallback由外设中断或DMA中断调用,HAL库中断公共处理函数已经实现对中断标记位读取、判断和清除操作,用户只需要专注于中断逻辑功能的实现即可
HAL_PPP_ErrorCallback举例: HAL_USART_ErrorCallback外设或DMA中断中发生的错误,用于发生错误处理

此类函数通常被_weak修饰(弱函数),允许用户重新定义该函数

Middlewares文件夹介绍

该文件夹下面有 ST 和 Third_Party 2 个子文件夹。
ST 文件夹下面存放的是 STM32 相关的一些文件,包括 STemWin 和 USB 库等。
Third_Party 文件夹是第三方中间件,这些中间件都是非常成熟的开源解决方案。
在这里插入图片描述

Projects 文件夹

该文件夹存放的是一些可以直接编译的实例工程。每个文件夹对应一个 ST 官方的 Demo板。比如要查看 STM32L476 相关工程,直接打开子文件夹 STM32L476G-EVAL即可。里面有很多实例,都可以用来参考。

这里注意,每个工程下面都有一个MDK-ARM 子文件夹,该子文件夹内部会有名称为 Project.uvprojx 的工程文件,我们只需要点击它就可以在MDK中打开工程。 例如打 开Projects\STM32L476G-EVAL\Templates\MDK-ARM 文件夹,内容如下图:
在这里插入图片描述

四、使用

CMSIS核心层文件就是将【CMSIS】文件夹中的【Device】和【Include】文件夹中裁剪后剩的11个文件,这11个文件对于新建MDK工程是必须包含的;设备驱动层就是HAL库及LL库的源码,也就是【STM32F1xx_HAL_Driver】文件夹中的源码;用户程序文件,正点原子例程都将main.h、stm32f1xx_hal_msp.c删除掉了,放到了例如初始化UART就将UART的在stm32f1xx_hal_msp.c中的回调函数放到usart.c中,stm32f1xx_it.c和stm32f1xx_it.h里面本身就定义了一些中断,所以选择保留,如果写串口中断,推荐写到usart.c中。。

HAL 库的用户配置文件

如果是F1系列那么就修改stm32f1xx_hal_conf.h。获取此文件可以从STM32官方例程中获取,也可以从HAL库驱动源码中获取,只是名称不同,复制时只需要将template删除即可。
  在这里插入图片描述

裁剪HAL库外设驱动源码(不进行编译)

STM32HAL库裁剪就是将stm32f1xx_hal_conf.h中用不到的宏定义注释掉,因为在HAL库驱动源码中都是用的ifdef判断宏是否被定义。以GPIO为例如下所示:
  在这里插入图片描述
通过对工程中用到什么外设就加什么驱动文件,也是起到裁剪作用。如下所示,是部分HAL库驱动文件:
在这里插入图片描述

stm32f1xx_hal.c 文件
  使用HAL库最关心的就说HAL库初始化函数HAL_Init(),不同系列可能有些小区别,但是核心代码如下:

HAL_StatusTypeDef  HAL_Init(void) 
{ 
	__HAL_FLASH_PREFETCH_BUFFER_ENABLE(); 	                    /* 使能FLASH预取缓冲 */ 

	HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2); /* 配置中断优先级分组 */ 

	/* 使用滴答定时器作为时钟基准,配置 1ms 滴答(重置后默认的时钟源为 HSI) */ 
	HAL_InitTick(TICK_INT_PRIORITY); 

	HAL_MspInit(); 	/* 初始化其它底层硬件(如果必要) */ 

	return HAL_OK; 	/* 返回函数状态 */ 
}
  • 第一段程序作用是使能FLASH预取缓冲,STM32是32位的,每次读取的指令也是32位的,FLASH存在预取缓冲区,预取缓冲区由2个64位组成,CPU每次读取指令,将指令放在预取缓冲区,就可以起到程序加快运行的效果。

  • 第二段程序是设置中断优先级分组,默认情况下设置位为4,正点原子默认设置成2。

  • 第三段是使能系统滴答定时器,并且配置为1ms。正点原子实际配置滴答定时器在delay.c中的delay_Init()函数中。

  • HAL_MspInit()为空函数

针对于stm32f4xx芯片开发使用hal版本 /** ****************************************************************************** * @file stm32f4xx_hal.h * @author MCD Application Team * @version V1.4.2 * @date 10-November-2015 * @brief This file contains all the functions prototypes for the HAL * module driver. ****************************************************************************** * @attention * * © COPYRIGHT(c) 2015 STMicroelectronics * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */
<think>好的,我现在需要帮助用户了解C语言中占位符的使用方法,特别是在printfscanf中的格式化字符串应用。首先,我应该回顾一下自己关于C语言格式化输出的知识,确保信息的准确性。 用户提到了几个引用资料,我需要仔细看看这些引用内容,确保回答符合他们提供的资料。引用[1]提到除了printfscanf,其他函数如sprintfsnprintf也使用占位符,这我的记忆一致。引用[2][3]详细说明了不同占位符的类型修饰符,比如%hd表示短整型,%lf用于双精度浮点数,还有关于长度修饰符的内容,比如lh。 接下来,我需要组织回答的结构。用户要求结构清晰,逐步解决问题,所以分点说明比较合适。首先介绍基本概念,然后分类讨论不同的占位符类型,比如整数、浮点数、字符字符串等。每个类别下给出示例代码,这样用户更容易理解。 需要注意的是,用户要求所有行内数学表达式用$...$格式,但这里的内容主要是代码占位符,可能涉及较少数学表达式。不过如果有的话,比如提到变量或参数说明,可能需要使用。例如,在说明字段宽度小数精度时,可能会用到变量,如$%5d$,这里应该用行内格式。 然后,关于常见问题,用户可能对scanf的安全问题或占位符错误使用导致的bug感兴趣。比如,忘记使用&符号取地址,或者缓冲区溢出,这些都需要提醒。此外,用户可能想知道不同函数的区别,如printfscanf在占位符上的差异,比如%lf在printf中不需要,但在scanf中必须使用。 还需要检查是否有遗漏的占位符类型,比如%p用于指针,%n用于记录已输出的字符数,这些虽然不常用,但完整提及能帮助用户全面了解。同时,引用资料中提到的修饰符如h、l、L等,要正确解释它们的用途,比如%ld表示长整型,%hd表示短整型,%Lf用于长双精度。 在代码示例部分,需要确保语法正确,比如在scanf中使用%lf读取双精度浮点数,而在printf中使用%f。同时,提醒用户在使用字符串占位符%s时要注意缓冲区大小,避免溢出,这可以引用资料中的内容。 最后,生成相关问题时要围绕占位符的用法、常见错误、不同函数的差异以及安全性等方面。确保问题有针对性,帮助用户深入理解。 总结步骤: 1. 定义基本语法,说明占位符的作用。 2. 分类列出常用占位符,每种类型给出示例代码。 3. 解释修饰符格式控制,如字段宽度、精度、对齐等。 4. 强调scanf的特殊注意事项,如地址符&、缓冲区处理。 5. 常见错误安全性问题,引用资料中的例子。 6. 生成相关问题,覆盖使用场景、错误案例、函数比较等。 现在需要检查是否有遗漏的信息点,比如引用[3]中提到输出字符个数数字的小数位数,这需要在格式控制部分详细说明。同时,确保所有引用都正确标注,比如在讨论scanf的%lf时引用[2],在说明精度时引用[3]。 确认所有占位符的示例正确,比如%o%x的输出形式,%e的科学计数法,%%的转义等。可能需要测试代码示例是否正确,但至少在理论部分要准确。 最后,确保语言简洁明了,符合中文表达习惯,不使用复杂句式,让用户容易理解。</think>### C语言占位符使用方法详解 #### 一、基本概念 占位符(Format Specifier)用于在格式化输入/输出函数(如$printf$、$scanf$、$sprintf$等)中指定数据类型格式[^1]。其语法为: `%[标志][宽度][.精度][长度修饰符]类型字符` #### 二、常用占位符类型 1. **整数类型** - `%d`:有符号十进制整数 - `%u`:无符号十进制整数 - `%x`/`%X`:十六进制整数(小写/大写) - `%o`:八进制整数 ```c int num = 255; printf("十进制:%d,十六进制:%x,八进制:%o", num, num, num); // 输出:255, ff, 377 ``` 2. **浮点数类型** - `%f`:单精度浮点数 - `%lf`:双精度浮点数(仅在$scanf$中需要)[^2] - `%e`/`%E`:科学计数法表示 ```c double pi = 3.1415926; printf("默认精度:%.2f,科学计数:%e", pi, pi); // 输出:3.14,3.141593e+00 ``` 3. **字符与字符串** - `%c`:单个字符 - `%s`:字符串 ```c char name[] = "Alice"; printf("姓名:%s,首字母:%c", name, name[0]); // 输出:Alice,A ``` #### 三、格式控制修饰符 1. **字段宽度与对齐** - `%5d`:右对齐输出至少5位宽度的整数 - `%-5d`:左对齐输出 ```c printf("|%5d|%-5d|", 12, 12); // 输出:| 12|12 | ``` 2. **精度控制** - `%.3f`:保留3位小数 - `%.5s`:输出字符串前5个字符[^3] ```c printf("圆周率:%.3f,截断字符串:%.5s", 3.1415926, "HelloWorld"); // 输出:3.142,Hello ``` 3. **长度修饰符** - `%hd`:短整型(short) - `%ld`:长整型(long) - `%Lf`:长双精度(long double) ```c short age = 18; long population = 7800000000L; printf("年龄:%hd,人口:%ld", age, population); ``` #### 四、$scanf$的特殊注意事项 1. **地址符&** ```c int num; scanf("%d", &num); // 必须使用&取地址 ``` 2. **缓冲区处理** ```c char str[10]; scanf("%9s", str); // 限制输入长度防止溢出 ``` 3. **占位符差异** - $printf$中`%f`可输出单/双精度,但$scanf$中必须用`%lf`读取双精度[^2] #### 五、常见错误案例 1. **类型不匹配** ```c double value; scanf("%f", &value); // 错误!应使用%lf ``` 2. **缺少&符号** ```c int num; scanf("%d", num); // 错误!应改为&num ``` 3. **格式字符串漏洞** ```c char buffer[10]; scanf("%s", buffer); // 危险!未限制输入长度 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值