今天介HAL库操作普通IO口,就是输入/输出。

  如果用CubeMX配置io工程,打开以后可以看到如下代码:

    GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE(); // 根据名字,这是使能B端口 GPIO_Initure.Pin=GPIO_PIN_0;       // 0口
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; // 上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; // 高速
HAL_GPIO_Init(GPIOB,&GPIO_Initure); // 调用初始化函数 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET); // 初始化电平

看到代码的时候,如果想深入了解一定要深入的仔细分析,看看到底是怎么调用的,操作了那些寄存器(不需要自己操作,但是要了解),用一个词来概括,抽丝剥茧。首先定义了一个 GPIO_InitTypeDef 类型的结构体,从名字可以看出是IO口初始化的类型配置,然后使能B端口,再然后配置刚才定义的结构体,把各种功能赋给各个成员变量。我们可以看一下这个结构体怎么定义的,,代码如下:

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 */ uint32_t Alternate; /*!< Peripheral to be connected to the selected pins.
This parameter can be a value of @ref GPIO_Alternate_function_selection */
}GPIO_InitTypeDef;

这个结构体里面每一个元素都要仔细的看一下,Pin:指定配置那个脚,那参数怎么看呢?看英文注释,他说:这个参数是GPIO_pins_define的任何一个,这个又是什么呢?进去看看?会发现这不是变量,找不到他,那没办法,既注释中有他,那么我们肯定是可以找到的,那就整个工程搜索一下,还真的搜到了,如下:

/** @defgroup GPIO_pins_define GPIO pins define
* @{
*/
#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 */ #define GPIO_PIN_MASK ((uint32_t)0x0000FFFF) /* PIN mask for assert test */

其实意思就是,结构体中的Pin变量可以是这些宏定义中的任何一个,从命名来说也就是0-15哪些脚。继续看,Mode:指定那个脚的模式,这个参数可以是 GPIO_mode_define 中的任何一个,找到他看看,如下:

/** @defgroup GPIO_mode_define GPIO mode define
* @brief GPIO Configuration Mode
* Elements values convention: 0xX0yz00YZ
* - X : GPIO mode or EXTI Mode
* - y : External IT or Event trigger detection
* - z : IO configuration on External IT or Event
* - Y : Output type (Push Pull or Open Drain)
* - Z : IO Direction mode (Input, Output, Alternate or Analog)
* @{
*/
#define GPIO_MODE_INPUT ((uint32_t)0x00000000) /*!< Input Floating Mode */
#define GPIO_MODE_OUTPUT_PP ((uint32_t)0x00000001) /*!< Output Push Pull Mode */
#define GPIO_MODE_OUTPUT_OD ((uint32_t)0x00000011) /*!< Output Open Drain Mode */
#define GPIO_MODE_AF_PP ((uint32_t)0x00000002) /*!< Alternate Function Push Pull Mode */
#define GPIO_MODE_AF_OD ((uint32_t)0x00000012) /*!< Alternate Function Open Drain Mode */ #define GPIO_MODE_ANALOG ((uint32_t)0x00000003) /*!< Analog Mode */ #define GPIO_MODE_IT_RISING ((uint32_t)0x10110000) /*!< External Interrupt Mode with Rising edge trigger detection */
#define GPIO_MODE_IT_FALLING ((uint32_t)0x10210000) /*!< External Interrupt Mode with Falling edge trigger detection */
#define GPIO_MODE_IT_RISING_FALLING ((uint32_t)0x10310000) /*!< External Interrupt Mode with Rising/Falling edge trigger detection */ #define GPIO_MODE_EVT_RISING ((uint32_t)0x10120000) /*!< External Event Mode with Rising edge trigger detection */
#define GPIO_MODE_EVT_FALLING ((uint32_t)0x10220000) /*!< External Event Mode with Falling edge trigger detection */
#define GPIO_MODE_EVT_RISING_FALLING ((uint32_t)0x10320000) /*!< External Event Mode with Rising/Falling edge trigger detection */

上面就是IO口的各种功能配置,依次是:输入、推挽输出、开漏输出等等。同理,可以可以找到Pull、Speed等可以赋什么值。到此这个结构体就“充满”了,配置好了,我们的告诉系统啊,好接下来调用 HAL_GPIO_Init(GPIOB,&GPIO_Initure); 就是把刚才配制好的结构体扔到这个叫做IO口初始化的函数中。这个函数有两个参数,第一个是B就是那个端口,第二个是我们配置的结构体,其实就是:B端口的0号脚,这样的功能。这个函数太长了,说关键的部分,该函数会把我们的引脚的功能逐个抽离出来,然后配置相应的寄存器,就实现了这个脚的配置,代码如下:

void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
uint32_t position;
uint32_t ioposition = 0x00;
uint32_t iocurrent = 0x00;
uint32_t temp = 0x00; /* 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));
assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); /* Configure the port pins */
for(position = ; position < GPIO_NUMBER; position++)
{
/* Get the IO position */
ioposition = ((uint32_t)0x01) << position;
/* Get the current IO position */
iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition; if(iocurrent == ioposition)
{
/*--------------------- GPIO Mode Configuration ------------------------*/
/* In case of Alternate function mode selection */
if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
{
/* Check the Alternate function parameter */
assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
/* Configure Alternate function mapped with the current IO */
temp = GPIOx->AFR[position >> ];
temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * )) ;
temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * ));
GPIOx->AFR[position >> ] = temp;
} /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
temp = GPIOx->MODER;
temp &= ~(GPIO_MODER_MODER0 << (position * ));
temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * ));
GPIOx->MODER = temp; /* In case of Output or Alternate function mode selection */
if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
(GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
{
/* Check the Speed parameter */
assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
/* Configure the IO Speed */
temp = GPIOx->OSPEEDR;
temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * ));
temp |= (GPIO_Init->Speed << (position * ));
GPIOx->OSPEEDR = temp; /* Configure the IO Output Type */
temp = GPIOx->OTYPER;
temp &= ~(GPIO_OTYPER_OT_0 << position) ;
temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> ) << position);
GPIOx->OTYPER = temp;
} /* Activate the Pull-up or Pull down resistor for the current IO */
temp = GPIOx->PUPDR;
temp &= ~(GPIO_PUPDR_PUPDR0 << (position * ));
temp |= ((GPIO_Init->Pull) << (position * ));
GPIOx->PUPDR = temp; /*--------------------- EXTI Mode Configuration ------------------------*/
/* Configure the External Interrupt or event for the current IO */
if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
{
/* Enable SYSCFG Clock */
__HAL_RCC_SYSCFG_CLK_ENABLE(); temp = SYSCFG->EXTICR[position >> ];
temp &= ~(((uint32_t)0x0F) << ( * (position & 0x03)));
temp |= ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << ( * (position & 0x03)));
SYSCFG->EXTICR[position >> ] = temp; /* Clear EXTI line configuration */
temp = EXTI->IMR;
temp &= ~((uint32_t)iocurrent);
if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
{
temp |= iocurrent;
}
EXTI->IMR = temp; temp = EXTI->EMR;
temp &= ~((uint32_t)iocurrent);
if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
{
temp |= iocurrent;
}
EXTI->EMR = temp; /* Clear Rising Falling edge configuration */
temp = EXTI->RTSR;
temp &= ~((uint32_t)iocurrent);
if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
{
temp |= iocurrent;
}
EXTI->RTSR = temp; temp = EXTI->FTSR;
temp &= ~((uint32_t)iocurrent);
if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
{
temp |= iocurrent;
}
EXTI->FTSR = temp;
}
}
}
}

回过头来,再看一下开启GPIOB时钟,__HAL_RCC_GPIOB_CLK_ENABLE(); 他是一个很大的宏,把和这个宏有关的都贴上一起分析:

#define __HAL_RCC_GPIOB_CLK_ENABLE()    do { \
__IO uint32_t tmpreg = 0x00; \
SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN);\
/* Delay after an RCC peripheral clock enabling */ \
tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN);\
UNUSED(tmpreg); \
} while() #define SET_BIT(REG, BIT) ((REG) |= (BIT)) #define RCC_AHB1ENR_GPIOBEN ((uint32_t)0x00000002) #define READ_BIT(REG, BIT) ((REG) & (BIT)) #define UNUSED(x) ((void)(x)) // 避免警告——百度

这个宏,简单一点看,把当作一个函数看一下,执行一次do里面的,把寄存器 AHB1ENR 1位置1,就是使能GPIOB。

  总结一下IO是使用,想配置一个脚作为普通口用,就要定义一个配置结构体,初始化这个脚所在的口的时钟,然后“填满”它,在把他扔到初始化函数中,到此,就配置好了一个普通的IO口作为输入输出。

  

stm32 HAL库笔记(一)——普通IO口的更多相关文章

  1. stm32 HAL库笔记(零)

    最近在设计四旋翼飞行器,用stm32f407,有三种开发方式可以选择:一.寄存器开发.二:库函数开发.三:HAL库开发,考虑了一下,选择了HAL库,原因如下: 1. 寄存器开发相对较慢,寄存器很多,配 ...

  2. stm32 HAL库笔记(一)——串口的操作

    昨天分析了普通io口的使用,和初始化代码流程,回顾一下,首先定义一个配置io口功能的结构体,然后开启时钟,再去配置这个结构体里面的各个成员变量,每个成员变量都有很多种选择,可以看各个成员变量 后面的注 ...

  3. 【有趣的全彩LED | 编程】用STM32 HAL库让WS2812B为你所动

    一.效果展示 观看演示效果:https://www.bilibili.com/video/BV1dv411Y7x3 使用STM32 HAL库编程 PWM+DMA控制输出,CubeMX生成初始工程 实现 ...

  4. 【情人节选帽子】TCS34725颜色传感器和Python图形界面编程(STM32 HAL库)

    截图 描述: l  STM32 HAL库编程 l  使用模拟IIC通信,方便程序移植 l  Python界面编写,蘑菇头的帽子是什么颜色 l  STM32 HAL库串口通信 l  Python界面使用 ...

  5. STM32 HAL库详解 及 手动移植

    源: STM32 HAL库详解 及 手动移植

  6. 【书籍连载】《STM32 HAL 库开发实战指南—基于F7》-第一章

    从今天起,每天开始连载一章<STM32 HAL 库开发实战指南—基于F7>.欢迎各位阅读.点评.学习. 第1章  如何使用本书 1.1  本书的参考资料 本书参考资料为:<STM32 ...

  7. 【春节歌曲回味 | STM32小音乐盒 】PWM+定时器驱动无源蜂鸣器(STM32 HAL库)

    l  STM32通过PWM与定时器方式控制无源蜂鸣器鸣响 l  STM32小音乐盒,歌曲进度条图形显示与百分比显示,歌曲切换 l  编程使用STM32 HAL库 l  IIC OLED界面编程,动画实 ...

  8. STM32 HAL库 UART 串口读写功能笔记

    https://www.cnblogs.com/Mysterious/p/4804188.html STM32L0 HAL库 UART 串口读写功能 串口发送功能: uint8_t TxData[10 ...

  9. STM32 HAL库与标准库的区别_浅谈句柄、MSP函数、Callback函数

    最近笔者开始学习STM32的HAL库,由于以前一直用标准库进行开发,于是发现了HAL库几点好玩的地方,在此分享. 1.句柄在STM32的标准库中,假设我们要初始化一个外设(这里以USART为例)我们首 ...

随机推荐

  1. JAVA集合接口及类

    各接口及类关系图 Iterable 所有集合的初始接口,实现该接口可进行foreach操作,只有一个iterator()方法,并返回iterator类型: Iterable在java.lang下,It ...

  2. 异常处理:try - except 和 try finally。

    异常处理:try-except语句 1)      此处:as reason为可选参数,reason是一个变量. 2)      使用try—except语句时,检测范围内出现错误,不会有红色的报错提 ...

  3. php优秀框架codeigniter学习系列——CI_Security类学习

    这篇文章主要介绍CI核心框架工具类CI_Security. 安全类包含了一些方法,用于安全的处理输入数据,帮助你创建一个安全的应用.以下选取类中的重点方法进行说明. __construct() 在构造 ...

  4. es6学习日记1

    1.let和const ES6新增了let命令,用来声明变量,用法类似于var ,但是声明的变量只在let命令所在代码块内有效. 例如: { let a = 10; var b = 1; } a // ...

  5. XXS level6

    (1输入框输入与第五关 相同的payload 查看页面源代码,发现“href"变成了”hr_ef“ (2)查看PHP源代码 <?php ini_set("display_er ...

  6. Python之小练习

    1.1 2 3 4 5 6 7 8能组成多少个不同的两位数? count = 0for i in range(1,9): for V in range(1,9): if i != V: count+= ...

  7. Flume架构以及应用介绍

    在具体介绍本文内容之前,先给大家看一下Hadoop业务的整体开发流程:  从Hadoop的业务开发流程图中可以看出,在大数据的业务处理过程中,对于数据的采集是十分重要的一步,也是不可避免的一步,从而引 ...

  8. python select解析 socket高效通信服务器 自己写的socketserver

    import select import socket import queue server = socket.socket()#创建服务器端 server.bind(('localhost',99 ...

  9. LiquiBase 学习

    preconditions mysql database is installed maven has been setted up properly add depedenceies apply p ...

  10. mongodb集群配置分片集群

    测试环境 操作系统:CentOS 7.2 最小化安装 主服务器IP地址:192.168.197.21 mongo01 从服务器IP地址:192.168.197.22 mongo02 从服务器IP地址: ...