【03】STM32F407 HAL 库框架设计学习

【03】STM32F407 HAL 库框架设计学习

摘要

本文旨在为初学者提供一个关于STM32F407微控制器HAL(Hardware Abstraction Layer)库框架设计的详细学习教程。通过本文,读者将从零开始,逐步掌握STM32F407的基本知识、HAL库的配置步骤、HAL库函数的使用方法,并通过配套的例程和代码注释加深理解。本文内容涵盖基础知识、配置步骤、HAL库函数详解、配套例程和总结,并附有思维导图以帮助读者更好地理解知识结构。


初学者重要提示

在开始学习STM32F407和HAL库之前,请注意以下几点:

  1. 硬件准备
    • 确保你拥有STM32F407开发板,并熟悉其硬件结构。
    • 准备好调试工具,如ST-Link或类似设备。
  2. 软件安装
    • 安装STM32CubeMX和STM32CubeIDE。
    • 安装STM32Cube_FW_F4固件库。
  3. 开发环境配置
    • 确保STM32CubeMX和STM32CubeIDE已正确配置,并能够生成和编译项目。
  4. 学习资源
    • 熟悉STM32F407的数据手册和HAL库参考手册。
    • 参考STM32CubeMX和STM32CubeIDE的用户指南。
  5. 编程基础
    • 熟悉C语言编程基础。
    • 理解基本的嵌入式系统概念,如中断、DMA等。

1. 基础知识

1.1 STM32F407简介

STM32F407是STMicroelectronics公司推出的一款高性能32位微控制器,基于ARM Cortex-M4内核,工作频率高达168MHz。它集成了丰富的外设,如GPIO、UART、SPI、I2C、PWM、ADC、DAC等,适用于多种嵌入式应用。

1.2 HAL库简介

HAL(Hardware Abstraction Layer)库是ST公司为STM32系列微控制器提供的标准软件库,旨在为开发者提供一个统一的接口,简化硬件操作。HAL库将硬件操作抽象为函数调用,使得开发者无需深入了解底层硬件细节,即可完成复杂的硬件操作。

1.3 开发环境搭建

在开始使用STM32F407和HAL库之前,需要先搭建开发环境。以下是搭建开发环境的步骤:

  1. 安装STM32CubeMX:STM32CubeMX是一个图形化配置工具,用于配置STM32微控制器的外设和时钟。
  2. 安装STM32CubeIDE:STM32CubeIDE是基于Eclipse的集成开发环境,用于STM32项目的开发和调试。
  3. 安装STM32Cube_FW_F4:这是STM32F4系列的HAL库和底层固件库,包含HAL库的源代码和头文件。

2. 配置步骤

2.1 使用STM32CubeMX配置STM32F407

  1. 打开STM32CubeMX,选择STM32F407VG芯片。
  2. 配置时钟:在“Clock Configuration”选项卡中,配置系统时钟为168MHz。
  3. 配置GPIO:在“Pinout & Configuration”选项卡中,配置GPIO引脚的功能。例如,配置GPIOA的第5引脚为LED输出。
  4. 配置其他外设:根据需要配置其他外设,如UART、SPI、I2C等。
  5. 生成代码:完成配置后,点击“Generate Code”按钮,选择保存路径,生成初始化代码。

2.2 在STM32CubeIDE中配置项目

  1. 导入生成的代码:在STM32CubeIDE中,选择“File” -> “Import” -> “STM32CubeMX Project” -> “Existing STM32CubeMX Project”,导入生成的代码。
  2. 配置项目:在“Project Explorer”中,右键点击项目,选择“Properties”,配置项目属性,如调试配置、编译选项等。
  3. 构建项目:点击“Build”按钮,构建项目,确保没有错误。

3. HAL库函数详解

3.1 GPIO操作

3.1.1 GPIO初始化
HAL_StatusTypeDef HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
  • 参数

    • GPIOx:GPIO端口,如GPIOA、GPIOB等。
    • GPIO_Init:指向GPIO初始化结构体的指针,包含GPIO模式、速度、上下拉配置等信息。
  • 返回值

    • HAL_OK:初始化成功。
    • HAL_ERROR:初始化失败。
3.1.2 GPIO输入输出操作
HAL_StatusTypeDef HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
  • 参数

    • GPIOx:GPIO端口。
    • GPIO_Pin:GPIO引脚,如GPIO_PIN_5。
    • PinState:引脚状态,GPIO_PIN_SET表示高电平,GPIO_PIN_RESET表示低电平。
  • 返回值

    • HAL_OK:操作成功。
    • HAL_ERROR:操作失败。

3.2 UART操作

3.2.1 UART初始化
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart, UART_InitTypeDef *uInit)
  • 参数

    • huart:UART句柄,包含UART配置信息。
    • uInit:指向UART初始化结构体的指针,包含波特率、数据位、停止位、校验位等信息。
  • 返回值

    • HAL_OK:初始化成功。
    • HAL_ERROR:初始化失败。
3.2.2 UART数据发送
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
  • 参数

    • huart:UART句柄。
    • pData:指向发送数据缓冲区的指针。
    • Size:发送数据的长度。
    • Timeout:超时时间。
  • 返回值

    • HAL_OK:发送成功。
    • HAL_ERROR:发送失败。

3.3 PWM操作

3.3.1 PWM初始化
HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim, TIM_InitTypeDef *pInitStruct)
  • 参数

    • htim:TIM句柄,包含PWM配置信息。
    • pInitStruct:指向TIM初始化结构体的指针,包含PWM模式、时钟源、频率等信息。
  • 返回值

    • HAL_OK:初始化成功。
    • HAL_ERROR:初始化失败。
3.3.2 PWM输出
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
  • 参数

    • htim:TIM句柄。
    • Channel:PWM通道,如TIM_CHANNEL_1。
  • 返回值

    • HAL_OK:启动成功。
    • HAL_ERROR:启动失败。

4. 配套例程

4.1 LED闪烁例程

4.1.1 代码实现
#include "main.h"GPIO_InitTypeDef GPIO_InitStructure;void SystemClock_Config(void);
static void MX_GPIO_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();while (1){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);HAL_Delay(500);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);HAL_Delay(500);}
}static void MX_GPIO_Init(void)
{GPIO_InitStructure.Pin = GPIO_PIN_5;GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.Pull = GPIO_NOPULL;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}void Error_Handler(void)
{while (1){}
}
4.1.2 代码说明
  • HAL_Init():初始化HAL库。
  • SystemClock_Config():配置系统时钟。
  • MX_GPIO_Init():配置GPIO引脚。
  • HAL_GPIO_WritePin():控制GPIO引脚输出。
  • HAL_Delay():延时函数。

4.2 UART通信例程

4.2.1 代码实现
#include "main.h"UART_HandleTypeDef huart2;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART2_UART_Init();while (1){char data = 'A';HAL_UART_Transmit(&huart2, (uint8_t *)&data, 1, 100);HAL_Delay(1000);}
}static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_2;GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;GPIO_InitStructure.Pull = GPIO_NOPULL;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
}static void MX_USART2_UART_Init(void)
{huart2.Instance = USART2;huart2.Init.BaudRate = 115200;huart2.Init.WordLength = UART_WORDLENGTH_8B;huart2.Init.StopBits = UART_STOPBITS_1;huart2.Init.Parity = UART_PARITY_NONE;huart2.Init.Mode = UART_MODE_TX_RX;huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart2.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart2) != HAL_OK){Error_Handler();}
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}void Error_Handler(void)
{while (1){}
}
4.2.2 代码注释
  • UART_HandleTypeDef huart2:UART句柄。
  • MX_USART2_UART_Init():配置UART2。
  • HAL_UART_Transmit():发送数据。
  • HAL_Delay():延时函数。

4.3 PWM生成例程

4.3.1 代码实现
#include "main.h"TIM_HandleTypeDef htim2;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM2_Init();HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);while (1){HAL_Delay(1000);}
}static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_0;GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;GPIO_InitStructure.Pull = GPIO_NOPULL;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
}static void MX_TIM2_Init(void)
{TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};htim2.Instance = TIM2;htim2.Init.Prescaler = 8399;htim2.Init.CounterMode = TIM_COUNTERMODE_UP;htim2.Init.Period = 999;htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_Init(&htim2) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK){Error_Handler();}
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}void Error_Handler(void)
{while (1){}
}
4.3.2 代码说明
  • TIM_HandleTypeDef htim2:TIM句柄。
  • MX_TIM2_Init():配置TIM2。
  • HAL_TIM_PWM_Start():启动PWM输出。
  • HAL_Delay():延时函数。

5. 总结

通过本文的学习,读者应该能够掌握STM32F407的基本知识、HAL库的配置步骤、HAL库函数的使用方法,并能够通过配套的例程和代码注释加深理解。HAL库的使用大大简化了硬件操作,使得开发者能够更专注于应用逻辑的实现。希望本文能够帮助读者快速上手STM32F407的开发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/26837.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PhotoShop学习01

了解Photoshop 这里省略了Photoshop的软件安装,请自行查找资源下载。 1.打开图片 下图为启动photoshop后出现的界面,我们可以通过创建新文件或打开已有文件来启用photoshop的工作界面。 可以通过左边的按钮进行新文件的创建或打开已有文件。 也可以点…

LabVIEW虚拟弗兰克赫兹实验仪

随着信息技术的飞速发展,虚拟仿真技术已经成为教学和研究中不可或缺的工具。开发了一种基于LabVIEW平台开发的虚拟弗兰克赫兹实验仪,该系统不仅能模拟实验操作,还能实时绘制数据图形,极大地丰富了物理实验的教学内容和方式。 ​ …

【TI毫米波雷达】DCA1000的ADC原始数据C语言解析及FMCW的Python解析2D-FFT图像

【TI毫米波雷达】DCA1000的ADC原始数据C语言解析及FMCW的Python解析2D-FFT图像 文章目录 ADC原始数据C语言解析Python的2D-FFT图像附录:结构框架雷达基本原理叙述雷达天线排列位置芯片框架Demo工程功能CCS工程导入工程叙述Software TasksData PathOutput informati…

【数据结构】堆与二叉树

一、树的概念 1.1 什么是树? 树是一种非线性的数据结构,其由 n 个 ( n > 0 ) 有限节点所组成的一个有层次关系的集合。之所以称其为树,是因为其逻辑结构看起来像是一颗倒挂的树。 在树中,有一个特殊的节点称为根节点&#xf…

从零开始开发纯血鸿蒙应用之语音朗读

从零开始开发纯血鸿蒙应用 〇、前言一、API 选型1、基本情况2、认识TextToSpeechEngine 二、功能集成实践1、改造右上角菜单2、实现语音播报功能2.1、语音引擎的获取和关闭2.2、设置待播报文本2.3、speak 目标文本2.4、设置语音回调 三、总结 〇、前言 中华汉字洋洋洒洒何其多…

8 SpringBoot进阶(上):AOP(面向切面编程技术)、AOP案例之统一操作日志

文章目录 前言1. AOP基础1.1 AOP概述: 什么是AOP?1.2 AOP快速入门1.3 Spring AOP核心中的相关术语(面试)2. AOP进阶2.1 通知类型2.1.1 @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行(通知的代码在业务方法之前和之后都有)2.1.2 @Before:前置通知,此…

人大金仓国产数据库与PostgreSQL

一、简介 在前面项目中,我们使用若依前后端分离整合人大金仓,在后续开发过程中,我们经常因为各种”不适配“问题,但可以感觉得到大部分问题,将人大金仓视为postgreSQL就能去解决大部分问题。据了解,Kingba…

Deepseek 模型蒸馏

赋范课堂: https://www.bilibili.com/video/BV1qUN8enE4c/

经验分享:用一张表解决并发冲突!数据库事务锁的核心实现逻辑

背景 对于一些内部使用的管理系统来说,可能没有引入Redis,又想基于现有的基础设施处理并发问题,而数据库是每个应用都避不开的基础设施之一,因此分享个我曾经维护过的一个系统中,使用数据库表来实现事务锁的方式。 之…

【前端基础】1、HTML概述(HTML基本结构)

一、网页组成 HTML:网页的内容CSS:网页的样式JavaScript:网页的功能 二、HTML概述 HTML:全称为超文本标记语言,是一种标记语言。 超文本:文本、声音、图片、视频、表格、链接标记:由许许多多…

MongoDB—(一主、一从、一仲裁)副本集搭建

MongoDB集群介绍: MongoDB 副本集是由多个MongoDB实例组成的集群,其中包含一个主节点(Primary)和多个从节点(Secondary),用于提供数据冗余和高可用性。以下是搭建 MongoDB 副本集的详细步骤&am…

Hive-06之函数 聚合Cube、Rollup、窗口函数

1、Hive函数介绍以及内置函数查看 内容较多,见《Hive官方文档》 https://cwiki.apache.org/confluence/display/Hive/LanguageManualUDF 1)查看系统自带的函数 hive> show functions; 2)显示自带的函数的用法 hive> desc function…

CSS定位详解

1. 相对定位 1.1 如何设置相对定位? 给元素设置 position:relative 即可实现相对定位。 可以使用 left 、 right 、 top 、 bottom 四个属性调整位置。 1.2 相对定位的参考点在哪里? 相对自己原来的位置 1.3 相对定位的特点&#xff1…

[Lc滑动窗口_1] 长度最小的数组 | 无重复字符的最长子串 | 最大连续1的个数 III | 将 x 减到 0 的最小操作数

目录 1. 长度最小的字数组 题解 代码 ⭕2.无重复字符的最长子串 题解 代码 3.最大连续1的个数 III 题解 代码 4.将 x 减到 0 的最小操作数 题解 代码 1. 长度最小的字数组 题目链接:209.长度最小的字数组 题目分析: 给定一个含有 n 个 正整数 的数组…

MySQL 事务笔记

MySQL 事务笔记 目录 事务简介事务操作事务四大特性并发事务问题事务隔离级别总结 事务简介 事务(Transaction)是数据库操作的逻辑单元,由一组不可分割的SQL操作组成。主要用于保证: 多个操作的原子性(要么全部成功…

数据结构秘籍(四) 堆 (详细包含用途、分类、存储、操作等)

1 引言 什么是堆? 堆是一种满足以下条件的树:(树这一篇可以参考我的文章数据结构秘籍(三)树 (含二叉树的分类、存储和定义)-CSDN博客) 堆中的每一个结点值都大于等于&#xff08…

【网络安全 | 渗透测试】GraphQL精讲一:基础知识

未经许可,不得转载, 文章目录 GraphQL 定义GraphQL 工作原理GraphQL 模式GraphQL 查询GraphQL 变更(Mutations)查询(Queries)和变更(Mutations)的组成部分字段(Fields)参数(Arguments)变量别名(Aliases)片段(Fragments)订阅(Subscriptions)自省(Introspecti…

EMQX中不同端口对应的接入协议

使用tcp接入时应使用mqtt://IP:1883 使用ws接入时应使用ws://IP:8083

2020年蓝桥杯Java B组第二场题目+部分个人解析

#A&#xff1a;门牌制作 624 解一&#xff1a; public static void main(String[] args) {int count0;for(int i1;i<2020;i) {int ni;while(n>0) {if(n%102) {count;}n/10;}}System.out.println(count);} 解二&#xff1a; public static void main(String[] args) {…

数据结构:反射 和 枚举

目录 一、反射 1、定义 2、反射相关的类 3、Class类 &#xff08;2&#xff09;常用获得类中属性相关的方法&#xff1a; &#xff08;3&#xff09;获得类中注解相关的方法&#xff1a; &#xff08;4&#xff09;获得类中构造器相关的方法&#xff1a; &#xff08;…