首页 > 其他分享 >07. 通用GPIO

07. 通用GPIO

时间:2023-10-01 20:34:31浏览次数:35  
标签:selected 通用 07 Pin PIN uint16 GPIO define

一、什么是GPIO

  GPIO 是控制或者采集外部器件的信息的外设,即负责输入输出。它按组分配,每组 16 个 IO 口,组数视芯片而定。STM32F103ZET6 芯片是 144 脚的芯片,具有 GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOF 和 GPIOG 七组 GPIO 口,共有 112 个 IO 口可供我们编程使用。

  STM32F103 的绝大部分 IO 口,都兼容 5V。我们可以参考 STM32F103xE 的数据手册,见表 5 大容量 STM32F103xx 引脚定义,凡是有 FT 标志的,都是兼容 5V 电平的 IO 口,可以直接接 5V 的外设(注意:如果引脚设置的是模拟输入模式,则不能接 5V!)。

二、GPIO基本结构

GPIO基本结构

【1】、保护二极管

  保护二极管共有两个,用于保护引脚外部过高或过低的电压输入。当引脚输入电压高于 VDD 时,上面的二极管导通,当引脚输入电压低于 VSS 时,下面的二极管导通,从而使输入芯片内部的电压处于比较稳定的值。虽然有二极管的保护,但这样的保护却很有限,大电压大电流的接入很容易烧坏芯片。所以在实际的设计中我们要考虑设计引脚的保护电路。

【2】、上拉、下拉电阻

  它们阻值大概在 30~50K 欧之间,可以通过上、下两个对应的开关控制,这两个开关由寄存器控制。当引脚外部的器件没有干扰引脚的电压时,即没有外部的上、下拉电压,引脚的电平由引脚内部上、下拉决定,开启内部上拉电阻工作,引脚电平为高,开启内部下拉电阻工作,则引脚电平为低。同样,如果内部上、下拉电阻都不开启,这种情况就是我们所说的浮空模式。浮空模式下,引脚的电平是不可确定的。引脚的电平可以由外部的上、下拉电平决定。需要注意的是,STM32 的内部上拉是一种“弱上拉”,这样的上拉电流很弱,如果有要求大电流还是得外部上拉。

【3】、施密特触发器

  TTL肖特基触发器其实可以理解为用肖特基管构成的施密特触发器。对于标准施密特触发器,当输入电压高于正向阈值电压,输出为高;当输入电压低于负向阈值电压,输出为低;当输入在正负向阈值电压之间,输出不改变,也就是说输出由高电准位翻转为低电准位,或是由低电准位翻转为高电准位对应的阈值电压是不同的。只有当输入电压发生足够的变化时,输出才会变化,因此将这种元件命名为触发器。这种双阈值动作被称为迟滞现象,表明施密特触发器有记忆性。从本质上来说,施密特触发器是一种双稳态多谐振荡器。

  施密特触发器可作为波形整形电路,能将模拟信号波形整形为数字电路能够处理的方波波形,而且由于施密特触发器具有滞回特性,所以可用于抗干扰,以及在闭回路正回授/负回授配置中用于实现多谐振荡器。

【4】、P-MOS 管和 N-MOS 管

  这个结构控制 GPIO 的开漏输出和推挽输出两种模式。开漏输出:输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行。推挽输出:这两只对称的 MOS 管每次只有一只导通,所以导通损耗小、效率高。输出既可以向负载灌电流,也可以从负载拉电流。推拉式输出既能提高电路的负载能力,又能提高开关速度。

三、GPIO的工作模式

  GPIO 有八种工作模式,分别是:(1)输入浮空;(2)输入上拉;(3)输入下拉;(4)模拟输入;(5)开漏输出;(6)推挽式输出;(7)推挽式复用功能;(8)开漏复用功能

3.1、输入浮空

  上拉/下拉电阻为断开状态,施密特触发器打开,输出被禁止。输入浮空模式下,IO 口的电平完全是由外部电路决定。如果 IO 引脚没有连接其他的设备,那么检测其输入电平是不确定的。该模式可以用于按键检测等场景。

输入浮空

空闲时,IO 状态不确定,由外部的环境决定;

3.2、输入上拉

  上拉电阻导通,施密特触发器打开,输出被禁止。 在需要外部上拉电阻的时候,可以使用内部上拉电阻,这样可以节省一个外部电阻,但是内部上拉电阻的阻值较大,所以只是“弱上拉”,不适合做电流型驱动。

输入上拉

空闲时,IO 呈现高电平;

3.3、输入下拉

  下拉电阻导通,施密特触发器打开,输出被禁止。 在需要外部下拉电阻的时候,可以使用内部下拉电阻,这样可以节省一个外部电阻,但是内部下拉电阻的阻值较大,所以不适合做电流型驱动。

输入下拉

空闲时,IO 呈现低电平;

3.4、模拟输入

  上下拉电阻断开,施密特触发器关闭,双 MOS 管也关闭。其他外设可以通过模拟通道输入输出。 该模式下需要用到芯片内部的模拟电路单元单元,用于 ADC、DAC、MCO 这类操作模拟信号的外设。

模拟输入

专门用于模拟信号输入或输出,如:ADC 和 DAC;

3.5、开漏输出

  STM32 的开漏输出模式是数字电路输出的一种,从结果上看它 只能输出低电平 VSS 或者高阻态,常用于 IIC 通讯(IIC_SDA)或其它需要进行电平转换的场景。

  根据《STM32F10xxx参考手册_V10(中文版).pdf》第 108页 关于“GPIO输出配置”的描述,我们可以知道开漏模式下,IO 是这样工作的:

  • P-MOS 被“输出控制”控制在截止状态,因此 IO 的状态取决于 N-MOS 的导通状况;
  • 只有 N-MOS 还受控制于输出寄存器,“输出控制”对输入信号进行了逻辑非的操作;
  • 施密特触发器是工作的,即可以输入,且上下拉电阻都断开了,可以看成浮空输入;

  根据参考手册的描述:开漏输出模式下 P-MOS 一直在截止状态,即不导通,所以 P-MOS 管的栅极相当于一直接 VDD。

  如果输出数据寄存器的值为 0,那么 IO 引脚的输出状态为低电平。输出数据寄存器的逻辑 0 经过“输出控制”的取反操作后,输出逻辑 1 到 N-MOS 管的栅极,这时 N-MOS 管就会导通,使得 IO 引脚连接到 VSS,即输出低电平。

  如果输出数据寄存器的值为 1,经过“输出控制”的取反操作后,输出逻辑 0 到 N-MOS 管的栅极,这时 N-MOS 管就会截止。又因为 P-MOS 管是一直截止的,使得 IO 引脚呈现高阻态,即不输出低电平,也不输出高电平。因此要 IO 引脚输出高电平就必须接上拉电阻。 又由于 F1 系列的开漏输出模式下,内部的上下拉电阻不可用,所以只能通过接芯片外部上拉电阻的方式,实现开漏输出模式下输出高电平。如果芯片外部不接上拉电阻,那么开漏输出模式下,IO 无法输出高电平。

  在开漏输出模式下,施密特触发器是工作的,所以 IO 口引脚的电平状态会被采集到输入数据寄存器中,如果对输入数据寄存器进行读访问可以得到 IO 口的状态。也就是说开漏输出模式下,我们可以读取 IO 引脚状态。

开漏输出

不能输出高电平,必须由外部(或内部)上拉才能输出高电平;

3.6、开漏复用功能

  一个 IO 口 可以是 通用的 IO 口功能,还可以是 其他外设的特殊功能引脚,这就是 IO 口的复用功能。一个 IO 口可以是多个外设的功能引脚,我们需要选择作为其中一个外设的功能引脚。当选择复用功能时,引脚的状态是由对应的外设控制,而不是输出数据寄存器。除了复用功能外,其他的结构分析请参考开漏输出模式。

  另外 在开漏式复用功能模式下,施密特触发器也是打开的,我们可以读取 IO 口的电平状态,同时外设可以读取 IO 口的信息。

开漏复用功能

不能输出高电平,必须由外部(或内部)上拉才能输出高电平,由其它外设控制输出;

3.7、推挽式输出

  STM32 的推挽输出模式,从结果上看它会 输出低电平 VSS 或者高电平 VDD。推挽输出跟开漏输出不同的是,推挽输出模式 P-MOS 管和 N-MOS 管都用上。

  如果输出数据寄存器的值为 0,经过“输出控制”取反操作后,输出逻辑 1 到 P-MOS 管的栅极,这时 P-MOS 管就会截止,同时也会输出逻辑 1 到 N-MOS 管的栅极,这时 N-MOS 管就会导通,使得 IO 引脚接到 VSS,即输出低电平。

  如果输出数据寄存器的值为 1 ,经过“输出控制”取反操作后,输出逻辑 0 到 N-MOS 管的栅极,这时 N-MOS 管就会截止,同时也会输出逻辑 0 到 P-MOS 管的栅极,这时 P-MOS 管就会导通,使得 IO 引脚接到 VDD,即输出高电平。

  推挽输出模式下,P-MOS 管和 N-MOS 管同一时间只能有一个管是导通的。 当 IO 引脚在做高低电平切换时,两个管子轮流导通,一个负责灌电流,一个负责拉电流,使其负载能力和开关速度都有较大的提高。

  另外 在推挽输出模式下,施密特触发器也是打开的,我们可以读取 IO 口的电平状态。

  由于推挽输出模式下输出高电平时,是直接连接 VDD,所以驱动能力较强,可以做电流型驱动,驱动电流最大可达 25mA,但是芯片的总电流有限,所以并不建议这样用,最好还是使用芯片外部的电源。

推挽式输出

可输出高低电平,驱动能力强;

3.8、推挽式复用功能

  一个 IO 口 可以是 通用的 IO 口功能,还可以是 其他外设的特殊功能引脚,这就是 IO 口的复用功能。一个 IO 口可以是多个外设的功能引脚,我们需要选择作为其中一个外设的功能引脚。当选择复用功能时,引脚的状态是由对应的外设控制,而不是输出数据寄存器。除了复用功能外,其他的结构分析请参考推挽式输出模式。

  另外 在推挽式复用功能模式下,施密特触发器也是打开的,我们可以读取 IO 口的电平状态,同时外设可以读取 IO 口的信息。

推挽式复用功能

可输出高低电平,驱动能力强,由其它外设控制输出;

四、复用功能

  使用默认复用功能前必须对端口位配置寄存器编程。

  • 对于 复用的输入功能,端口必须配置成 输入模式(浮空、上拉 或 下拉)且 输入引脚必须由外部驱动
    • 也可以通过软件来模拟复用功能输入引脚,这种模拟可以通过对 GPIO 控制器编程来实现。此时,端口应当被设置为复用功能输出模式。显然,这时相应的引脚不再由外部驱动,而是通过GPIO控制器由软件来驱动。
  • 对于 复用输出功能,端口必须配置成 复用功能输出模式(推挽 或 开漏)
  • 对于 双向复用功能,端口位必须配置 复用功能输出模式(推挽 或 开漏)。这时,输入驱动器 被配置成 浮空输入模式

  如果把端口配置成复用输出功能,则引脚和输出寄存器断开,并和片上外设的输出信号连接。如果软件把一个 GPIO引脚 配置成 复用输出功能,但是外设没有被激活,它的输出将不确定。

  当 I/O 端口被配置为复用功能时:

  • 开漏或推挽式配置中,输出缓冲器被打开
  • 内置外设的信号驱动输出缓冲器(复用功能输出)
  • 施密特触发输入被激活
  • 弱上拉 和 下拉电阻 被禁止
  • 在每个 APB2 时钟周期,出现在 I/O 引脚上的数据被采样到输入数据寄存器
  • 开漏模式时,读输入数据寄存器时可得到 I/O 口状态
  • 在推挽模式时,读输出数据寄存器时可得到最后一次写的值

五、GPIO寄存器介绍

  每个 GPIO 端口有两个 32 位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个 32 位数据寄存器(GPIOx_IDR 和 GPIOx_ODR),一个 32 位置位/复位寄存器(GPIOx_BSRR),一个 16 位复位寄存器(GPIOx_BRR)和 一个 32 位锁定寄存器(GPIOx_LCKR)。

  每个 I/O 端口位可以自由编程,然而 I/O 端口寄存器必须按 32 位字被访问(不允许半字或字节访问)。GPIOx_BSRR 和 GPIOx_BRR 寄存器允许对任何 GPIO 寄存器的读/更改的独立访问;这样,在读和更改访问之间产生 IRQ 时不会发生危险。

5.1、端口配置寄存器(GPIOx_CRL、GPIOx_CRH)(x=A..E)

端口配置低寄存器(GPIOx_CRL) (x=A..E)

端口配置高寄存器(GPIOx_CRH) (x=A..E)

  这两个寄存器都是 GPIO 口配置寄存器,不过 CRL 控制端口的低八位,CRH 控制端口的高八位。寄存器的作用是控制 GPIO 口的工作模式和工作速度。每组 GPIO 下有 16 个 IO 口,一个寄存器共 32 位,每 4 个位控制 1 个 IO,所以才需要两个寄存器完成。

  上面这 2 个配置寄存器就是用来配置 GPIO 的相关工作模式和工作速度,它们通过不同的配置组合方法,就决定我们所说的 8 种工作模式。

  端口配置表:

配置模式 CNF1 CNF0 MODE1 MODE2 PxODR寄存器
通用输出 推挽(Push-Pull) 0 0 01
10
11
见下表输出模式位
0 或 1
开漏(Open-Drain) 1 0 或 1
复用功能输出 推挽(Push-Pull) 1 0 不使用
开漏(Open-Drain) 1 不使用
输入 模拟输入 0 0 00 不使用
浮空输入 1 不使用
下拉输入 1 0 0
上拉输入 1

  输出模式位:

MODE[1:0] 意义
00 保留
01 最大输出速度为 10MHz
10 最大输出速度为 2MHz
11 最大输出速度为 50MHz

这两个寄存器都是 GPIO 口配置寄存器,不过 CRL 控制端口的低八位,CRH 控制端口的高八位。

每组 GPIO 下有 16 个 IO 口,一个寄存器共 32 位,每 4 个位控制 1 个 IO,所以才需要两个寄存器完成。

5.2、端口输入数据寄存器(GPIOx_IDR)(x=A..E)

端口输入数据寄存器(GPIOx_IDR) (x=A..E)

  该寄存器用于存储 GPIOx 的输入状态,它连接到施密特触发器上,IO 口外部的电平信号经过触发器后,模拟信号就被转化成 0 和 1 这样的数字信号,并存储到该寄存器中。

  该寄存器低 16 位有效,分别对应每一组 GPIO 的 16 个引脚。当 CPU 访问该寄存器,如果对应的某位为 0(IDRy = 0),则说明该 IO口 输入的是 低电平,如果是 1(IDRy = 1),则表示输入的是高电平,y = 0~15。

5.3、端口输出数据寄存器(GPIOx_ODR)(x=A..E)

端口输出数据寄存器(GPIOx_ODR) (x=A..E)

  该寄存器用于控制 GPIOx 的输出高电平或者低电平。该寄存器低 16 位有效,分别对应每一组 GPIO 的 16 个引脚。当 CPU 写访问该寄存器,如果对应的某位写 0 (ODRy = 0),则表示设置该 IO 口输出的是低电平,如果写 1(ODRy = 1),则表示设置该 IO 口输出的是高电平,y = 0~15。

5.4、端口位设置/清除寄存器(GPIOx_BSRR)(x=A..E)

端口位设置清除寄存器(GPIOx_BSRR) (x=A..E)

  该寄存器也用于控制 GPIOx 的输出高电平或者低电平。

  为什么有了 GPIOx_ODR 寄存器,还要这个 GPIOx_BSRR 寄存器呢?

  GPIOx_BSRR 是只写权限,而 GPIOx_ODR 是可读可写权限。GPIOx_BSRR 寄存器 32 位有效,对于低 16 位(0-15),我们往相应的位写 1(BSy = 1),那么对应的 IO 口会输出高电平,往相应的位写 0(BSy = 0),对 IO 口没有任何影响,高 16 位(16-31)作用刚好相反,对相应的位写 1(BRy = 1)会输出低电平,写 0(BRy = 0)没有任何影响,y = 0~15。

  也就是说,对于 GPIOx_BSRR 寄存器,你写 0 的话,对 IO 口电平是没有任何影响的。我们要设置某个 IO 口电平,只需要相关位设置为 1 即可。而 GPIOx_ODR 寄存器,我们要设置某个 IO 口电平,我们首先需要读出来 GPIOx_ODR 寄存器的值,然后对整个 GPIOx_ODR 寄存器重新赋值来达到设置某个或者某些 IO 口的目的,而 GPIOx_BSRR 寄存器直接设置即可,这在多任务实时操作系统中作用很大。

  GPIOX_BSRR 寄存器还有一个好处,就是 GPIOx_BSRR 寄存器改变引脚状态的时候,不会被中断打断,而 GPIOx_ODR 寄存器有被中断打断的风险。

5.5、端口位清除寄存器(GPIOx_BRR) (x=A..E)

端口位清除寄存器(GPIOx_BRR) (x=A..E)

5.6、端口配置锁定寄存器(GPIOx_LCKR) (x=A..E)

端口配置锁定寄存器(GPIOx_LCKR) (x=A..E)

六、GPIO配置步骤

  HAL 库中关于 GPIO 的驱动程序在 stm32f1xx_hal_gpio.c 文件以及其对应的头文件 stm32f1xx_hal_gpio.h 中。

6.1、使能对应GPIO时钟

  STM32 在使用任何外设之前,我们都要先使能其时钟。有关片上外设使能的头文件放在 stm32f1xx_hal_rcc.h 和 stm32f1xx_hal_rcc_ex.h 头文件中。

/** @defgroup RCC_APB2_Clock_Enable_Disable APB2 Clock Enable Disable
  * @brief  Enable or disable the High Speed APB (APB2) peripheral clock.
  * @note   After reset, the peripheral clock (used for registers read/write access)
  *         is disabled and the application software has to enable this clock before
  *         using it.
  * @{
  */
#define __HAL_RCC_GPIOA_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);\
                                        /* Delay after an RCC peripheral clock enabling */\
                                        tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);\
                                        UNUSED(tmpreg); \
                                      } while(0U)

#define __HAL_RCC_GPIOB_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN);\
                                        /* Delay after an RCC peripheral clock enabling */\
                                        tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN);\
                                        UNUSED(tmpreg); \
                                      } while(0U)

#define __HAL_RCC_GPIOC_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPCEN);\
                                        /* Delay after an RCC peripheral clock enabling */\
                                        tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPCEN);\
                                        UNUSED(tmpreg); \
                                      } while(0U)

#define __HAL_RCC_GPIOD_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPDEN);\
                                        /* Delay after an RCC peripheral clock enabling */\
                                        tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPDEN);\
                                        UNUSED(tmpreg); \
                                      } while(0U)
/** @defgroup RCCEx_APB2_Clock_Enable_Disable APB2 Clock Enable Disable
  * @brief  Enable or disable the High Speed APB (APB2) peripheral clock.
  * @note   After reset, the peripheral clock (used for registers read/write access)
  *         is disabled and the application software has to enable this clock before
  *         using it.
  * @{
  */
#if defined(STM32F100xE) || defined(STM32F101xB) || defined(STM32F101xE)\
 || defined(STM32F101xG) || defined(STM32F100xB) || defined(STM32F103xB)\
 || defined(STM32F103xE) || defined(STM32F103xG) || defined(STM32F105xC)\
 || defined(STM32F107xC)
#define __HAL_RCC_GPIOE_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPEEN);\
                                        /* Delay after an RCC peripheral clock enabling */ \
                                        tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPEEN);\
                                        UNUSED(tmpreg); \
                                      } while(0U)

#endif /* STM32F101x6 || STM32F101xB || STM32F101xE || (...) || STM32F105xC || STM32F107xC */
#if defined(STM32F101xE) || defined(STM32F103xE) || defined(STM32F101xG)\
 || defined(STM32F103xG)
#define __HAL_RCC_GPIOF_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPFEN);\
                                        /* Delay after an RCC peripheral clock enabling */ \
                                        tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPFEN);\
                                        UNUSED(tmpreg); \
                                      } while(0U)

#define __HAL_RCC_GPIOG_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPGEN);\
                                        /* Delay after an RCC peripheral clock enabling */ \
                                        tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPGEN);\
                                        UNUSED(tmpreg); \
                                      } while(0U)

#endif /* STM32F101xE || STM32F103xE || STM32F101xG || STM32F103xG*/

6.2、设置工作模式

【1】、HAL_GPIO_Init() 函数

  HAL_GPIO_Init() 函数是外设 GPIO 初始化函数,用来配置 GPIO 功能模式。外设 GPIO 的初始化函数声明如下:

/**
  * @brief  Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init.
  * @param  GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
  * @param  GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
  *         the configuration information for the specified GPIO peripheral.
  * @retval None
  */
void  HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init);
  • 函数形参

  GPIOx 是 端口号,其中 x 可以是 A-G:

/** @addtogroup Peripheral_declaration
  * @{
  */  
#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)

  GPIO_Init 是 GPIO_InitTypeDef 类型的结构体变量,其定义如下:

/**
  * @brief GPIO Init structure definition
  */
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 表示 引脚号,范围:GPIO_PIN_0 到 GPIO_PIN_15,另外还有 GPIO_PIN_Al l 可选。

/** @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 */

  成员 Mode 是 GPIO 的 模式选择,有以下选择项:

/** @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                        0x00000000u   		/*!< Input Floating Mode                   */
#define  GPIO_MODE_OUTPUT_PP                    0x00000001u   		/*!< Output Push Pull Mode                 */
#define  GPIO_MODE_OUTPUT_OD                    0x00000011u   		/*!< Output Open Drain Mode                */
#define  GPIO_MODE_AF_PP                        0x00000002u   		/*!< Alternate Function Push Pull Mode     */
#define  GPIO_MODE_AF_OD                        0x00000012u   		/*!< Alternate Function Open Drain Mode    */
#define  GPIO_MODE_AF_INPUT                     GPIO_MODE_INPUT         /*!< Alternate Function Input Mode         */
#define  GPIO_MODE_ANALOG                       0x00000003u		/*!< Analog Mode  */

  成员 Pull 用于 配置上下拉电阻,有以下选择项:

/** @defgroup GPIO_pull_define GPIO pull define
  * @brief GPIO Pull-Up or Pull-Down Activation
  * @{
  */
#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                */

  成员 Speed 用于 配置 GPIO 的速度,有以下选择项:

/** @defgroup GPIO_speed_define  GPIO speed define
  * @brief GPIO Output Maximum frequency
  * @{
  */
#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 */
  • 函数返回值

  无;

6.3、设置输出状态

【1】、HAL_GPIO_WritePin() 函数

  HAL_GPIO_WritePin() 函数是 GPIO 口的写引脚函数,用于设置引脚输出高电平或者低电平,通过 GPIOx_BSRR 寄存器复位或者置位操作。其声明如下:

/**
  * @brief  Sets or clears the selected data port bit.
  *
  * @note   This function uses GPIOx_BSRR register to allow atomic read/modify
  *         accesses. In this way, there is no risk of an IRQ occurring between
  *         the read and the modify access.
  *
  * @param  GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
  * @param  GPIO_Pin: specifies the port bit to be written.
  *          This parameter can be one of GPIO_PIN_x where x can be (0..15).
  * @param  PinState: specifies the value to be written to the selected bit.
  *          This parameter can be one of the GPIO_PinState enum values:
  *            @arg GPIO_PIN_RESET: to clear the port pin
  *            @arg GPIO_PIN_SET: to set the port pin
  * @retval None
  */
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
  • 函数参数

  GPIOx 是 端口号,其中 x 可以是 A-G:

/** @addtogroup Peripheral_declaration
  * @{
  */  
#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)

  GPIO_Pin 是引脚号,可以选择范围:GPIO_PIN_0 到 GPIO_PIN_15

/** @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 */

  PinState 是要设置输出的状态,是枚举型有两个选择:GPIO_PIN_SET 表示 高电平GPIO_PIN_RESET 表示 低电平

/**
  * @brief  GPIO Bit SET and Bit RESET enumeration
  */
typedef enum
{
  GPIO_PIN_RESET = 0u,
  GPIO_PIN_SET
} GPIO_PinState;
  • 函数返回值

  无;

【2】、HAL_GPIO_TogglePin() 函数

  HAL_GPIO_TogglePin() 函数是 GPIO 口的电平翻转函数也是通过 GPIOx_BSRR 寄存器复位或者置位操作。其声明如下:

/**
  * @brief  Toggles the specified GPIO pin
  * @param  GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
  * @param  GPIO_Pin: Specifies the pins to be toggled.
  * @retval None
  */
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
  • 函数参数

  GPIOx 是 端口号,其中 x 可以是 A-G:

/** @addtogroup Peripheral_declaration
  * @{
  */  
#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)

  GPIO_Pin 是引脚号,可以选择范围:GPIO_PIN_0 到 GPIO_PIN_15

/** @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 */
  • 函数返回值

  无;

6.4、读取输入状态

【1】、HAL_GPIO_ReadPin() 函数

  HAL_GPIO_ReadPin() 函数是 GPIO 口的读引脚函数,通过 GPIOx_IDR 寄存器读取。其声明如下:

/**
  * @brief  Reads the specified input port pin.
  * @param  GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
  * @param  GPIO_Pin: specifies the port bit to read.
  *         This parameter can be GPIO_PIN_x where x can be (0..15).
  * @retval The input port pin value.
  */
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
  • 函数参数

  GPIOx 是 端口号,其中 x 可以是 A-G:

/** @addtogroup Peripheral_declaration
  * @{
  */  
#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)

  GPIO_Pin 是引脚号,可以选择范围:GPIO_PIN_0 到 GPIO_PIN_15

/** @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 */
  • 函数返回值

  GPIO_PinState 枚举类型的值,有 2 个,分别是:GPIO_PIN_RESET 表示 低电平GPIO_PIN_SET 表示 高电平

/**
  * @brief  GPIO Bit SET and Bit RESET enumeration
  */
typedef enum
{
  GPIO_PIN_RESET = 0u,
  GPIO_PIN_SET
} GPIO_PinState;

标签:selected,通用,07,Pin,PIN,uint16,GPIO,define
From: https://www.cnblogs.com/kurome/p/17739225.html

相关文章

  • ARM+Codesys标准通用型控制器
    整机工业级设计,通讯外设经过隔离保护 电源宽电压设计(9~36VDC)丰富的通讯接口,满足多种场合控制和通讯需求 四核工业级处理器,高性能,低功耗,高可靠性    机身无风扇设计,外壳小巧搭载内核100%自主化大型实时操作系统SylixOS,支持   POSIX 接口规范;拥有完全自主可控的知识......
  • 操作STM32的GPIO的步骤
    1.使用RCC开启GPIO的时钟2.使用GPIO_Init函数初始化GPIO3.使用输入/输出控制GPIO口RCC在library组中的 stm32f10x_rcc.h中找:(第一个参数是选择哪个外设,第二个参数是EABLE或者DISABLE)voidRCC_AHBPeriphClockCmd(uint32_tRCC_AHBPeriph,FunctionalStateNewStat......
  • 开源.NetCore通用工具库Xmtool使用连载 - 扩展动态对象篇
    【Github源码】《上一篇》介绍了Xmtool工具库中的图形验证码类库,今天我们继续为大家介绍其中的扩展动态对象类库。<br>扩展动态对象是整个工具库中最重要的一个设计。在软件开发过程中,我们经常需要定义各种各样的数据对象;例如:用于参数传递的数据实体类、用于接口返回结果的Json......
  • P2216 [HAOI2007] 理想的正方形 题解
    Description给定\(n\timesm\)的矩阵,找大小为\(k\timesk\)的子矩阵\(a\),使得子矩阵\(\max\{a\}-\min\{a\}\)最小。SolutionSolution1枚举所有\(k\timesk\)的子矩阵,然后枚举最大值和最小值,时间复杂度\(O(n^4)\),期望得分\(20\)分。Solution2求最大值和最小......
  • 20230712 NOIP模拟(1)
    20230712NOIP模拟(1)[TOC]总结暑期第一次模拟赛预估得分:40分实际得分:40分(有大佬AK力Orz)T1前缀和(pre)题意给定一个字符串,求所有长度为偶数的前缀在整个字符串中出现的次数和。\(|S|\le200000\)。分析由于KMP的\(p[i]\)表示子串\(\left[1\cdotsp[i]\right]......
  • P1075 [NOIP2012 普及组] 质因数分解
    因为n是两个质数的乘积,所以直接暴力枚举,只要能被整除,直接输出因为是要求大的那个,所以从小到大枚举,输出商即可点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineLLlonglongintmain(){ LLn; cin>>n; for(inti=2;1LL*i*i<=n;i++){ if......
  • 洛谷 P7075[CSP-S2020] 儒略日
    [CSP-S2020]儒略日题目描述为了简便计算,天文学家们使用儒略日(Julianday)来表达时间。所谓儒略日,其定义为从公元前4713年1月1日正午12点到此后某一时刻间所经过的天数,不满一天者用小数表达。若利用这一天文学历法,则每一个时刻都将被均匀的映射到数轴上,从而得以很方便的......
  • 洛谷 P7075 [CSP-S2020] 儒略日
    P7075[CSP-S2020]儒略日1.题目描述为了简便计算,天文学家们使用儒略日(Julianday)来表达时间。所谓儒略日,其定义为从公元前4713年1月1日正午12点到此后某一时刻间所经过的天数,不满一天者用小数表达。若利用这一天文学历法,则每一个时刻都将被均匀的映射到数轴上,从而得以......
  • CentOS7通用部署
    #CentOS7#设置静态IPONBOOT=on替换为ONBOOT=yesBOOTPROTO=dhcp替换BOOTPROTO=staticsed-i"s|ONBOOT=on|ONBOOT=yes|"/etc/sysconfig/network-scripts/ifcfg-ens160sed-i"s|BOOTPROTO=dhcp|BOOTPROTO=static|"/etc/sysconfig/network-scripts/ifcfg-ens16......
  • 系统通用部署手册v02
    目录一、centos71.挂载本地ISO镜像2.下载默认插件3.关闭防火墙3.配置zabbix监控4.修改主机名5.JDK安装与环境设置:6.Tomcat安装7.安装redis8.Memcached安装一、centos71.挂载本地ISO镜像 mkdir-p/etc/yum.repos.d/bakmv/etc/yum.repos.d/CentOS*/etc/yum.repos.d/bakcat>......