【STM32 CubeMX】GPIO_HAL库源码分析

文章目录

  • 前言
  • 一、GPIO_HAL库源码分析
    • 1.1 初始化GPIO
    • 1.2 HAL_GPIO_Init源码分析
      • GPIO_InitTypeDef初始化结构体
      • HAL_GPIO_Init函数
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


一、GPIO_HAL库源码分析

1.1 初始化GPIO

void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);/*Configure GPIO pin : PB5 */GPIO_InitStruct.Pin = GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

上面这个代码是初始化GPIOBpin5引脚
在这里设置哪个引脚:GPIO_InitStruct.Pin = GPIO_PIN_5;
设置模式:GPIO_InitStruct.ModeGPIO_MODE_OUTPUT_PP为推挽输出
除了推挽输出,他还有下面这些:

#define  GPIO_MODE_OUTPUT_PP                    0x00000001u   /*推挽输出               */
#define  GPIO_MODE_OUTPUT_OD                    0x00000011u   /*开漏输出                */

在这里:GPIO_InitStruct.Pull,我们是设置是否有上下拉电阻,他有以下这些值

#define  GPIO_NOPULL        0x00000000u   /*!< No Pull-up or Pull-down activation  */
#define  GPIO_PULLUP        0x00000001u   /*!< Pull-up activation                  */
#define  GPIO_PULLDOWN      0x00000002u   /*!< Pull-down activation                */

其中就是无上下拉电阻,上拉、下拉电阻的设置

在我们主函数的while循环如下:

while (1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);
HAL_Delay(500);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */
}

他就只是对GPIOB pin5输出高低电平点灯

我们主要需要看一下HAL_GPIO_Init函数是如何实现的

1.2 HAL_GPIO_Init源码分析

GPIO_InitTypeDef初始化结构体

GPIO_InitTypeDef这个结构体是用来对于某一个引脚进行初始化存储的结构体
他长下面这样:

typedef struct
{uint32_t Pin;       /*!< Specifies the GPIO pins to be configured.This parameter can be any value of @ref GPIO_pins_define */uint32_t Mode;      /*!< Specifies the operating mode for the selected pins.This parameter can be a value of @ref GPIO_mode_define */uint32_t Pull;      /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.This parameter can be a value of @ref GPIO_pull_define */uint32_t Speed;     /*!< Specifies the speed for the selected pins.This parameter can be a value of @ref GPIO_speed_define */
} GPIO_InitTypeDef;

第一个成员为pin,pin这样表示

#define GPIO_PIN_0                 ((uint16_t)0x0001)  /* Pin 0 selected    */
#define GPIO_PIN_1                 ((uint16_t)0x0002)  /* Pin 1 selected    */
#define GPIO_PIN_2                 ((uint16_t)0x0004)  /* Pin 2 selected    */
#define GPIO_PIN_3                 ((uint16_t)0x0008)  /* Pin 3 selected    */
#define GPIO_PIN_4                 ((uint16_t)0x0010)  /* Pin 4 selected    */
#define GPIO_PIN_5                 ((uint16_t)0x0020)  /* Pin 5 selected    */
#define GPIO_PIN_6                 ((uint16_t)0x0040)  /* Pin 6 selected    */
#define GPIO_PIN_7                 ((uint16_t)0x0080)  /* Pin 7 selected    */
#define GPIO_PIN_8                 ((uint16_t)0x0100)  /* Pin 8 selected    */
#define GPIO_PIN_9                 ((uint16_t)0x0200)  /* Pin 9 selected    */
#define GPIO_PIN_10                ((uint16_t)0x0400)  /* Pin 10 selected   */
#define GPIO_PIN_11                ((uint16_t)0x0800)  /* Pin 11 selected   */
#define GPIO_PIN_12                ((uint16_t)0x1000)  /* Pin 12 selected   */
#define GPIO_PIN_13                ((uint16_t)0x2000)  /* Pin 13 selected   */
#define GPIO_PIN_14                ((uint16_t)0x4000)  /* Pin 14 selected   */
#define GPIO_PIN_15                ((uint16_t)0x8000)  /* Pin 15 selected   */
#define GPIO_PIN_All               ((uint16_t)0xFFFF)  /* All pins selected */

比如GPIO5,他变成二进制如下:在这里插入图片描述
他的bit5为1,是不是和我们上两节课的寄存器联系起来了
如果没有看过的同学可以进入HAL库的本质是操作寄存器来进行学习

接下来看Speed成员:
他可以有以下取值:

#define  GPIO_SPEED_FREQ_LOW              (GPIO_CRL_MODE0_1) /*!< Low speed */
#define  GPIO_SPEED_FREQ_MEDIUM           (GPIO_CRL_MODE0_0) /*!< Medium speed */
#define  GPIO_SPEED_FREQ_HIGH             (GPIO_CRL_MODE0)   /*!< High speed */

其中有低速,中速和高速
其中低速为2M,中速10M高速50M

HAL_GPIO_Init函数

这个函数有两个参数。一个为组号,另一个为初始化结构体
首先第一个参数,他有如下取值:

#define GPIOA               ((GPIO_TypeDef *)GPIOA_BASE)
#define GPIOB               ((GPIO_TypeDef *)GPIOB_BASE)
#define GPIOC               ((GPIO_TypeDef *)GPIOC_BASE)
#define GPIOD               ((GPIO_TypeDef *)GPIOD_BASE)
#define GPIOE               ((GPIO_TypeDef *)GPIOE_BASE)
#define GPIOF               ((GPIO_TypeDef *)GPIOF_BASE)
#define GPIOG               ((GPIO_TypeDef *)GPIOG_BASE)
//。。。。。。

GPIOx_Base如下:

#define GPIOA_BASE            (APB2PERIPH_BASE + 0x00000800UL)
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x00000C00UL)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x00001000UL)
#define GPIOD_BASE            (APB2PERIPH_BASE + 0x00001400UL)

这些就一起定义了一个组的基地址是什么

接下来我们看HAL_GPIO_Init源码:

void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{uint32_t position = 0x00u;uint32_t ioposition;uint32_t iocurrent;uint32_t temp;uint32_t config = 0x00u;__IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */uint32_t registeroffset;       /* offset used during computation of CNF and MODE bits placement inside CRL or CRH register *//* Check the parameters */assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Init->Pin));assert_param(IS_GPIO_MODE(GPIO_Init->Mode));/* Configure the port pins */while (((GPIO_Init->Pin) >> position) != 0x00u){/* Get the IO position */ioposition = (0x01uL << position);/* Get the current IO position */iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;if (iocurrent == ioposition){/* Check the Alternate function parameters */assert_param(IS_GPIO_AF_INSTANCE(GPIOx));/* Based on the required mode, filling config variable with MODEy[1:0] and CNFy[3:2] corresponding bits */switch (GPIO_Init->Mode){/* If we are configuring the pin in OUTPUT push-pull mode */case GPIO_MODE_OUTPUT_PP:/* Check the GPIO speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_PP;break;/* If we are configuring the pin in OUTPUT open-drain mode */case GPIO_MODE_OUTPUT_OD:/* Check the GPIO speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_OD;break;/* If we are configuring the pin in ALTERNATE FUNCTION push-pull mode */case GPIO_MODE_AF_PP:/* Check the GPIO speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_PP;break;/* If we are configuring the pin in ALTERNATE FUNCTION open-drain mode */case GPIO_MODE_AF_OD:/* Check the GPIO speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_OD;break;/* If we are configuring the pin in INPUT (also applicable to EVENT and IT mode) */case GPIO_MODE_INPUT:case GPIO_MODE_IT_RISING:case GPIO_MODE_IT_FALLING:case GPIO_MODE_IT_RISING_FALLING:case GPIO_MODE_EVT_RISING:case GPIO_MODE_EVT_FALLING:case GPIO_MODE_EVT_RISING_FALLING:/* Check the GPIO pull parameter */assert_param(IS_GPIO_PULL(GPIO_Init->Pull));if (GPIO_Init->Pull == GPIO_NOPULL){config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_FLOATING;}else if (GPIO_Init->Pull == GPIO_PULLUP){config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD;/* Set the corresponding ODR bit */GPIOx->BSRR = ioposition;}else /* GPIO_PULLDOWN */{config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD;/* Reset the corresponding ODR bit */GPIOx->BRR = ioposition;}break;/* If we are configuring the pin in INPUT analog mode */case GPIO_MODE_ANALOG:config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_ANALOG;break;/* Parameters are checked with assert_param */default:break;}//code..................
}

这些功能太复杂,我们只分析怎么把传入的参数变成输出引脚
他根据mode,来进行具体的设置:
在这里插入图片描述
然后他把数据存储到了config变量中
在这里插入图片描述
接下来我们看MODIFY_REG,修改寄存器,他需要修改指定寄存器,并且其他寄存器不被破坏

#define MODIFY_REG(REG, CLEARMASK, SETMASK)  WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))

在这里WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))他要写寄存器REG
他写什么呢,首先把寄存器的值读出来,& (~(CLEARMASK))清除掉某些位 | (SETMASK)设置某些位,这样就达到了修改寄存器且不破坏其他位

在这里:configregister = (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL : &GPIOx->CRH;他会去确定某个寄存器


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

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

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

相关文章

MockServer 服务框架设计

大部分现有的 mock 工具只能满足 HTTP 协议下简单业务场景的使用。但是面对一些复杂的业务场景就显得捉襟见肘&#xff0c;比如对 socket 协议的应用进行 mock&#xff0c;或者对于支付接口的失败重试的定制化 mock 场景。 为解决上述问题&#xff0c;霍格沃兹测试学院设计并研…

Day 44 | 动态规划 完全背包、518. 零钱兑换 II 、 377. 组合总和 Ⅳ

完全背包 题目 文章讲解 视频讲解 完全背包和0-1背包的区别在于&#xff1a;物品是否可以重复使用 思路&#xff1a;对于完全背包问题&#xff0c;内层循环的遍历方式应该是从weight[i]开始一直遍历到V&#xff0c;而不是从V到weight[i]。这样可以确保每种物品可以被选择多次…

【机器学习】数据清洗之处理异常点

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步…

比特币突破5万美元,2年来首次

作者&#xff1a;秦晋 2月13日凌晨&#xff0c;时隔两年&#xff0c;比特币首次突破50000美元关口。最高触及50363美元、24小时涨幅3.53%。创下2021年12月以来的新高。 据《财富》报道&#xff0c;本次上涨得益于三方面&#xff0c;首先是比特币ETF资金流入&#xff0c;比特币E…

Vue3.0(六):VueX 4.x详解

Vuex4状态管理 什么是状态管理 在开发中&#xff0c;我们的应用程序需要处理各种各样的数据&#xff0c;这些数据需要保存在应用程序的某一个位置&#xff0c;对于这些数据的管理&#xff0c;就是 状态管理目前前端项目越来越复杂&#xff0c;多组件共享同一数据的状态很常见…

Microsoft Excel 加载数据分析工具

Microsoft Excel 加载数据分析工具 1. 打开 Excel&#xff0c;文件 -> 选项2. 加载项 -> 转到…3. 分析工具库、分析工具库 - VBA4. 打开 Excel&#xff0c;数据 -> 数据分析References 1. 打开 Excel&#xff0c;文件 -> 选项 2. 加载项 -> 转到… ​​​ 3…

机器学习:卷积介绍及代码实现卷积操作

传统卷积运算是将卷积核以滑动窗口的方式在输入图上滑动&#xff0c;当前窗口内对应元素相乘然后求和得到结果&#xff0c;一个窗口一个结果。相乘然后求和恰好也是向量内积的计算方式&#xff0c;所以可以将每个窗口内的元素拉成向量&#xff0c;通过向量内积进行运算&#xf…

【王道数据结构】【chapter5树与二叉树】【P158t3】

编写后序遍历二叉树的非递归算法 #include <iostream> #include <stack> typedef struct treenode{char data;struct treenode *left;struct treenode *right; }treenode,*ptreenode;ptreenode buytreenode(char x) {ptreenode n(ptreenode) malloc(sizeof (treeno…

基于LLM的业务流程自动化

在当今竞争激烈的商业环境中&#xff0c;业务流程&#xff08;尤其是文档处理工作流程&#xff09;的自动化对于寻求提高效率和减少人工错误的公司来说变得至关重要。 传统方法往往难以跟上任务的数量和复杂性&#xff0c;而人工主导的流程速度缓慢、容易出错&#xff0c;并且可…

C++ //练习 6.30 编译第200页的str_subrange函数,看看你的编译器是如何处理函数中的错误的。

C Primer&#xff08;第5版&#xff09; 练习 6.30 练习 6.30 编译第200页的str_subrange函数&#xff0c;看看你的编译器是如何处理函数中的错误的。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /***********************…

线性代数的本质 2 线性组合、张成的空间、基

基于3Blue1Brown视频的笔记 一种新的看待方式 对于一个向量&#xff0c;比如说&#xff0c;如何看待其中的3和-2&#xff1f; 一开始&#xff0c;我们往往将其看作长度&#xff08;从向量的首走到尾部&#xff0c;分别在x和y上走的长度&#xff09;。 在有了数乘后&#xff0…

C++ 音视频原理

本篇文章我们来描述一下音视频原理 音视频录制原理: 下面是对这张思维导图的介绍 摄像头部分: 麦克风采集声音 摄像头采集画面 摄像头采集回来的数据可以用RGB也可以用YUV来表示 图像帧帧率 一秒能处理多少张图像 图像处理 &#xff1a;调亮度 图像帧队列 :意思是将数据取…