深入解析STM32 GPIO的输入和输出函数

系列文章目录

STM32单片机系列专栏

C语言术语和结构总结专栏

文章目录

1. GPIO模式

2. GPIO输出

2.1 RCC

2.2 GPIO

3. 代码示例

3.1 RCC时钟

3.2 GPIO初始化

3.3 GPIO输出函数

3.4 推挽输出和开漏输出

4. GPIO输入

4.1 输入模式

4.2 数据读取函数

5. C语言语法


1. GPIO模式

GPIO是微控制器中最基本也是最灵活的功能之一,其可以被配置为输入或输出模式,以及许多其他特殊功能模式。通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式:

模式名称 类型 描述
浮空输入 浮空输入 引脚没有内部或外部上拉或下拉,其电平未定义,通常不建议使用
上拉输入 上拉输入 引脚内部上拉至VDD,外部信号低于VDD时,检测到低电平
下拉输入 下拉输入 引脚内部下拉至VSS,外部信号高于VSS时,检测到高电平
模拟输入 模拟输入 GPIO未锁定,引脚直接连接到内部ADC
开漏输出 开漏输出 引脚以开漏模式工作,高电平时为高阻态,低电平时连接到VSS
推挽输出 推挽输出 引脚以推挽模式工作,高电平时连接到VDD,低电平时连接到VSS
复用开漏输出 复用开漏输出 用于复用功能的开漏输出,高电平时为高阻态,低电平时连接到VSS
复用推挽输出 复用推挽输出 用于复用功能的推挽输出,高电平时连接到VDD,低电平时连接到VSS

模式分类:

  • 输入模式(Input):引脚被配置为输入,用来读取外部信号的状态。
  • 输出模式(Output):引脚被配置为输出,可以驱动外部设备或显示设备状态。
  • 类型分类:

  • 推挽输出(Push-pull):可以在两种状态之间切换,要么连接到VDD(高电平),要么连接到VSS(低电平)。
  • 开漏输出(Open-drain):只能连接到VSS(低电平),而高电平状态需要外部拉高。
  • GPIO配置说明

  • 浮空输入(Floating input):引脚没有内部或外部的上拉或下拉电阻,状态由外部电路决定。
  • 上拉输入(Pull-up input):引脚内部连接有上拉电阻,如果外部电路没有连接,它将读取为高电平。
  • 下拉输入(Pull-down input):引脚内部连接有下拉电阻,如果外部电路没有连接,它将读取为低电平。
  • 模拟输入(Analog input):GPIO以模拟方式工作,可以直接连接到内部ADC(模拟到数字转换器)。
  • 开漏输出(Open-drain output):引脚在激活时连接到VSS,非激活时不连接(悬空)。常用于需要外部拉高的应用场合。
  • 推挽输出(Push-pull output):引脚可以输出高电平(连接到VDD)或低电平(连接到VSS)。
  • 复用开漏输出(Alternate function open-drain output):开漏输出,但是引脚被配置为特殊功能,例如I2C通信。
  • 复用推挽输出(Alternate function push-pull output):推挽输出,但是引脚被配置为特殊功能,例如PWM输出。
  • 2. GPIO输出

    操作STM32的GPIO一共有三个步骤:

    1. 使用RCC开启GPIO的时钟
    2. 使用GPIO_Init函数初始化GPIO
    3. 使用输出或者输入函数控制GPIO

    2.1 RCC

    首先打开一个新建好的工程文件,如果不知道怎么建立工程文件,可以看下面这篇文章:

    使用Keil MDK创建STM32标准库工程

    之后在Library中找到rcc.h文件(这里全程使用vscode去操作,如果不知道怎么实现Keil和VSCode协同开发STM32程序,可以查看下面这篇教程:

    Keil和VSCode协同开发STM32程序

    在rcc.h文件中拖到最下面,这里一般都是所有库函数的声明,这里最常用的就是这三个函数:

    void RCC_AHBPeriphClockCmd:外设时钟控制

    接着选择函数名,右键并选择转到定义(这里需要先进行一次编译,否则可能无法跳转) ,之后会来到.c文件的函数定义,下面解释一下这个函数:

    // 函数定义:控制特定AHB外设的时钟。
    // RCC_AHBPeriph:要配置的AHB外设。
    // NewState:指定外设时钟的新状态,ENABLE(使能) 或 DISABLE(失能)。
    void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState)
    {
      // 确保输入参数RCC_AHBPeriph是预定义的有效外设。
      assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph));
      
      // 确保输入的NewState是有效的功能状态(ENABLE 或 DISABLE)。
      assert_param(IS_FUNCTIONAL_STATE(NewState));
    
      // 如果NewState不是DISABLE(即是ENABLE),执行以下代码。
      if (NewState != DISABLE)
      {
        // 通过逻辑或运算将对应的位设置为1,来使能(开启)外设的时钟。
        RCC->AHBENR |= RCC_AHBPeriph;
      }
      // 如果NewState是DISABLE,执行以下代码。
      else
      {
        // 通过逻辑与运算与对应位的否定值运算,将对应的位设置为0,来禁能(关闭)外设的时钟。
        RCC->AHBENR &= ~RCC_AHBPeriph;
      }
    }
    

    2.2 GPIO

    下面看一下GPIO.h的文件,在Library中找到GPIO.h文件,也是拖到最后,这里可以看到常用的函数。

    void GPIO_DeInit(GPIO_TypeDef* GPIOx);
    void GPIO_AFIODeInit(void);
    void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
    void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
    uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
    uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
    void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
    void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

    void GPIO_DeInit(GPIO_TypeDef* GPIOx);
    功能:将指定GPIO端口的所有配置重置为默认值。
    参数:GPIOx:要重置的GPIO端口,例如GPIOA、GPIOB等。
    说明:这个函数通常用于在重新配置(复位)GPIO端口之前清除端口的当前配置。

    void GPIO_AFIODeInit(void);
    功能:将AFIO(Alternate Function IO)模块的所有配置重置(复位)为默认值。
    说明:这个函数通常用于清除所有GPIO端口的复用功能配置。

    void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
    功能:用结构体的参数初始化指定GPIO端口的引脚。
    参数:

  • GPIOx:要初始化的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_InitStruct:包含了初始化配置的结构体指针,如引脚模式、输出类型、输出速度等。
  • 说明:这个函数用于配置GPIO引脚的各种属性,例如输入/输出模式、输出类型、输出速度等。

    void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
    功能:将给定的GPIO_InitTypeDef结构体初始化为默认值。
    参数:GPIO_InitStruct:要初始化的GPIO_InitTypeDef结构体指针。
    说明:这个函数用于在配置GPIO引脚之前,将相关的结构体初始化为默认值。

    uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
    uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

    功能:读取指定GPIO端口指定引脚的输入状态。
    参数:

  • GPIOx:要读取的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_Pin:要读取的引脚,可以是单个引脚或多个引脚的按位或组合。
  • 返回值:引脚的输入状态,0/1。或者GPIO端口的输入状态,每个引脚的状态对应一个位。

    void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    功能:将指定GPIO端口指定引脚的输出状态设置为高电平。
    参数:

  • GPIOx:要设置的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_Pin:要设置的引脚,可以是单个引脚或多个引脚的按位或组合。
  • void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    功能:将指定GPIO端口指定引脚的输出状态设置为低电平。
    参数:

  • GPIOx:要重置的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_Pin:要重置的引脚,可以是单个引脚或多个引脚的按位或组合。
  • void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
    功能:将指定GPIO端口指定引脚的输出状态设置为指定的电平。
    参数:

  • GPIOx:要写入的GPIO端口,例如GPIOA、GPIOB等。
  • GPIO_Pin:要写入的引脚,可以是单个引脚或多个引脚的按位或组合。
  • BitVal:要设置的电平,可以是Bit_RESET(低电平)或Bit_SET(高电平)。
  • void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
    功能:设置指定GPIO端口的输出状态。
    参数:

  • GPIOx:要写入的GPIO端口,例如GPIOA、GPIOB等。
  • PortVal:要设置的输出值,每个引脚的状态对应一个位,0表示低电平,1表示高电平。
  • 3. 代码示例

    这里使用最基础的led灯来解释代码功能

    3.1 RCC时钟

    main.c文件中,首先调用RCC中的APB2外设时钟控制函数,首先和刚才一样,在RCC.h找到函数名, RCC_APB2PeriphClockCmd, 复制到main中,接着右键函数转到定义,根据注释中的提示,因为点亮的是PA0的LED,所以选择 RCC_APB2Periph_GPIOA,将其放到第一个参数,第二个参数选择ENABLE, 这样时钟就开启了。

     

    3.2 GPIO初始化

    接着调用GPIO的初始化函数,在GPIO.h中找到 GPIO_Init 函数,跳转到定义,和rcc类似根据注释中的提示,第一个参数选择GPIOA, 第二个参数是一个结构体

    先把结构体复制到GPIO_Init上面,起名为:GPIO_InitStructure, 这个结构体相当于一个局部变量,然后将结构体的成员都列出来,如下所示:

    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Pin = ;
    	GPIO_InitStructure.GPIO_Mode = ;
    	GPIO_InitStructure.GPIO_Speed = ;
    	GPIO_Init()

    接下来就是如何根据标准库文件来配置函数,以GPIO_Mode为例, 接下来会详细到每一个操作,之后这些操作会省略。

  • 首先右键 GPIO_Mode转到定义
  • 根据提示,我们选择GPIOMode_TypeDef,接着按ctrl+f 搜索,在下面找到定义方式,这里有GPIO的八种工作模式。
  • GPIO_Mode_AIN (0x0):模拟输入模式(Analog Input Mode)
  • GPIO_Mode_IN_FLOATING (0x04):浮空输入模式(Floating Input Mode)
  • GPIO_Mode_IPD (0x28):输入下拉模式(Input Pull-Down Mode)
  • GPIO_Mode_IPU (0x48):输入上拉模式(Input Pull-Up Mode)
  • GPIO_Mode_Out_OD (0x14):开漏输出模式(Open-Drain Output Mode)
  • GPIO_Mode_Out_PP (0x10):推挽输出模式(Push-Pull Output Mode)
  • GPIO_Mode_AF_OD (0x1C):复用开漏输出模式(Alternate Function Open-Drain Mode)
  • GPIO_Mode_AF_PP (0x18):复用推挽
  • 因为这里是为了实现LED功能,所以使用GPIO_Mode_Out_PP,将其复制到GPIO_Mode后面。

    接着是GPIO_Pin,同样的操作,转到定义,这里很简单,选择GPIO_Pin_0即可。

  • 如果要使用多个A引脚,例如多个led灯,直接在后面加上即可,每个定义之间用 | 隔开。
  • 最后是GPIO_Speed,转到定义以后,按ctrl+f 搜索,如图所示下一个就是函数说明,这里选择GPIO_Speed_50MHz,将其复制到GPIO_Speed后面。

    最后,将完成配置的结构体的变量名:GPIO_InitStructure,复制到GPIO_Init中即可完成GPIO的初始化配置。

    此时,main.c中的代码如下:

    #include "stm32f10x.h"                  // Device header
    
    int main(void)
    {
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    	
    	while (1)
    	{
    		
    	}
    }

    3.3 GPIO输出函数

    完成GPIO的初始化之后,就可以使用GPIO的输出函数了,四个输出函数为(前面已经解释):

    void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    //将指定GPIO端口指定引脚的输出状态设置为高电平。
    void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    //将指定GPIO端口指定引脚的输出状态设置为低电平。
    void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
    //将指定GPIO端口指定引脚的输出状态设置为指定的电平。
    void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
    //设置指定GPIO端口的输出状态。

    GPIO_ResetBits

    我们选择低电平输出,所以使用 GPIO_ResetBits,和前面的操作一样,可以转到定义查看注释说明,因为led灯使用A0引脚,所以代码为:

    	GPIO_ResetBits(GPIOA, GPIO_Pin_0);

    此时下载程序到单片机中就可以看到LED灯已经被点亮。(注意这里采用的时led长脚连接负极,短接连接引脚,代表低电平点亮)

    GPIO_SetBits

    如果换成 GPIO_SetBits,可以发现LED熄灭,因为此时输出为高电平。

    GPIO_WriteBit

    第三种输出函数:GPIO_WriteBit,这个函数是指定输出类型,比如前面的配置不同改变,多了一个BitAction参数,转到定义,可以发现注释教程中说明了两个方式Bit_RESETBit_SET

    Bit_RESET: 清除端口值(置低电平)

    Bit_SET: 设置端口值(置高电平)

    GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); 此时led点亮。。GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); 此时led熄灭。

    目前main.c中的代码如下:

    #include "stm32f10x.h"                  // Device header
    
    int main(void)
    {
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
    
    	while (1)
    	{
    		
    	}
    }
    

    这里的GPIO_WriteBit用于LED点亮时,可能会发现一个问题,Bit_SET可以置为高电平,此时LED熄灭,那如果想用基本的0和1来代表高低电平,直接将Bit_SET改为1会出现警告,所以还需要加上强制类型转换,把1和0类型转为BitAction的枚举类型:

    GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);

    这就是GPIO输出函数的配置,之后就是你想实现的功能,这些功能就是在后面的while中去实现,并且根据不同的模块和功能添加不同的库,例如实现led连续闪烁,除了修改main.c中的主程序,还需要在工程文件在加入delay.c 和 delay.h 文件。但操作都类似,在.h文件中找到需要使用的标准库函数,转到定义在.c文件中找到函数定义和注释说明。

    GPIO_WriteBit

    这个函数可以设置指定GPIO端口的输出状态。例如对于多个led的控制。

    首先还是转到定义,从注释中可以看到,第一个参数依然是GPIOA, 第二个参数是指定写到输出数据寄存器的值,下面可以看到第二个参数是直接写道GPIO和ODR寄存器里的。

    所以可以直接写0x001(十六进制),对应二进制为0000 0000 0000 0001。这16个二进制分别对应PA0 – PA15 一共16个端口,最低位(右边)对应PA0。

    此时如果加入延迟函数,就可以实现最基本的led灯流水线

    #include "stm32f10x.h"                  // Device header
    
    int main(void)
    {
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;	
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    	while (1)
    	{
    		GPIO_Write(GPIOA, 0x0001); // Set PA0
    		Delay_ms(1000);
    		GPIO_Write(GPIOA, 0x0002); // Set PA1	
    		Delay_ms(1000);
    		GPIO_Write(GPIOA, 0x0004); // Set PA2
    		Delay_ms(1000);
    	}
    }

    如果设置为低电平触发,可以在参数前加上 ~ ,意思是取反。

    3.4 推挽输出和开漏输出

    对于推挽输出和开漏输出的驱动问题,还是用刚才led的例子,目前我们使用的是GPIO_Mode_Out_PP (0x10):推挽输出模式。此时将led短脚连接负极,长接连接引脚,代表高电平点亮,这时可以发现程序依然可用,说明在推挽模式下,高低电平都有驱动能力。

    如果把端口的模式改为 GPIO_Mode_Out_OD (0x14):开漏输出模式

    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

    此时led还是保持高电平点亮,但程序不起作用,只有当led引脚切换以后,改为低电平点亮时,程序才可以正常运行,这说明开漏输出模式的高电平不具有驱动能力。

    所以,推挽输出高低电平都有驱动能力,开漏输出高电平相当于高阻态,没有驱动能力,只有低电平有驱动能力。

    4. GPIO输入

    4.1 输入模式

    GPIO输入的配置和GPIO输出类似,不同的数结构体中 GPIO_InitStructure.GPIO_Mode 不同,这里要使用下面的四种输入模式,例如按键输入使用上拉输入模式(GPIO_Mode_IPU)

    GPIO_Mode_AIN (0x0):模拟输入模式(Analog Input Mode)

  • 在这种模式下,GPIO引脚被配置为读取模拟信号,意味着它可以直接与微控制器内部的模拟-数字转换器(ADC)相连。
  • GPIO引脚不会被数字输入缓冲器干扰,这样可以保证模拟信号的准确性和质量。
  • 通常用于传感器信号读取,如温度、压力或湿度传感器。
  • GPIO_Mode_IN_FLOATING (0x04):浮空输入模式(Floating Input Mode)

  • GPIO引脚配置为数字输入,没有激活内部上拉或下拉电阻,其电平状态取决于外部电路。
  • 如果外部没有提供确定的电平,引脚的状态是未定义的,可能会浮动,因此称为“浮空”。
  • 这种模式适合于外部电路总是会驱动GPIO到一个确定状态,或者外部已经提供了必要的上拉或下拉设置。
  • GPIO_Mode_IPD (0x28):输入下拉模式(Input Pull-Down Mode)

  • PIO引脚配置为数字输入,并且内部激活了下拉电阻,这会将引脚默认拉至低电平(接地)。
  • 如果外部没有提供信号,引脚将读取为低电平状态;如果外部提供了高电平信号,则会被检测到。
  • 这种模式适用于按钮或开关,其中未激活状态需要确保为低电平。
  • GPIO_Mode_IPU (0x48):输入上拉模式(Input Pull-Up Mode)

  • GPIO引脚配置为数字输入,并且内部激活了上拉电阻,这会将引脚默认拉至高电平(接VDD或正电源)。
  • 如果外部没有提供信号,引脚将读取为高电平状态;如果外部提供了低电平信号,则会被检测到。
  • 这同样适用于按钮或开关,但在这种情况下,未激活状态需要确保为高电平。
  • 4.2 数据读取函数

    还有GPIO数据读取的函数:例如读取按键输入就要用到 GPIO_ReadInputDataBit

    uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

  • 功能:此函数用于读取STM32的GPIO端口上的单个输入引脚的状态。这对于检测如按钮按下、限位开关触发等简单的二进制输入非常有用。
  • 参数
  • GPIOx:指向你想要读取的GPIO端口的指针。STM32微控制器有多个GPIO端口,例如GPIOA、GPIOB等,每个都对应不同的物理引脚组。
  • GPIO_Pin:具体的GPIO引脚编号,它是一个16位的值,每一位代表一个特定的引脚。例如,如果你想读取第0位,就会使用GPIO_Pin_0
  • 返回值:返回值是一个8位的无符号整数。如果指定的引脚处于高电平状态,则返回非零值;如果处于低电平,则返回零。
  • uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

  • 功能:这个函数读取整个GPIO端口的当前输入数据。这在你需要同时检查一个端口上的多个引脚状态时非常有用。
  • 参数
  • GPIOx:与GPIO_ReadInputDataBit函数中的GPIOx相同,指向要读取的GPIO端口的指针。
  • 返回值:返回值是一个16位的无符号整数。每个比特位代表该端口上对应引脚的输入状态,位值为1表示该引脚处于高电平,位值为0表示处于低电平。
  • uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

  • 功能:此函数用于读取STM32的GPIO端口上的单个输出引脚的状态。这在你需要确认引脚的当前输出状态,例如,确保一个LED是否被程序正确控制时非常有用。
  • 参数
  • GPIOx:与GPIO_ReadInputDataBit函数中的GPIOx相同,指向你想要读取的GPIO端口的指针。
  • GPIO_Pin:与GPIO_ReadInputDataBit函数中的GPIO_Pin相同,表示特定的GPIO引脚编号。
  • 返回值:返回值是一个8位的无符号整数。如果指定的引脚正在输出高电平,则返回非零值;如果正在输出低电平,则返回零。
  • uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

  • 功能:这个函数读取整个GPIO端口的当前输出数据。当你需要审核或调试一个端口上多个引脚的输出配置时,这个函数非常有用。
  • 参数
  • GPIOx:与GPIO_ReadInputData函数中的GPIOx相同,指向要读取的GPIO端口的指针。
  • 返回值:返回值是一个16位的无符号整数。与GPIO_ReadInputData类似,每个比特位代表该端口上对应引脚的输出状态,位值为1表示该引脚正在输出高电平,位值为0表示正在输出低电平。
  • 5. C语言语法

    STM32基于C语言开发,对于这部分,需要有一些C语言的基础知识,例如下面的数据类型,如果对这方面不太了解,可以看下面的C语言系列讲解。

    C语言语法和结构总结系列专栏

    数据类型 位数 表示范围 stdint定义 ST定义
    char 8 -128 ~ 127 int8_t s8
    unsigned char 8 0 ~ 255 uint8_t u8
    short 16 -32768 ~ 32767 int16_t s16
    unsigned short 16 0 ~ 65535 uint16_t u16
    int 32 -2147483648 ~ 2147483647 int32_t s32
    unsigned int 32 0 ~ 4294967295 uint32_t u32
    long 32 -2147483648 ~ 2147483647 int32_t s32
    unsigned long 32 0 ~ 4294967295 uint32_t u32
    long long 64 -(2^64)/2 ~ (2^64)/2-1 int64_t
    unsigned long long 64 0 ~ (2^64)-1 uint64_t
    float 32 -3.4e38 ~ 3.4e38
    double 64 -1.7e308 ~ 1.7e308

    接下来对几个关键的语法进行简单说明:

    宏定义  #define

    用途:用一个字符串代替一个数字,便于理解,防止出错;提取程序中经常出现的参数,便于快速修改。

    定义宏定义:

      #define test 123

    引用宏定义:

      int a = test;  //等效于int a = 123;

    typedef 

    用途:将一个比较长的变量类型名换个名字,便于使用,只能用于变量名。
    定义typedef:

     typedef unsigned char uint8_t;

    引用typedef:

    uint8_t a;    //等效于unsigned char a;

    结构体  struct
    用途:数据打包,不同类型变量的集合
    定义结构体变量:因为结构体变量类型较长,所以通常用typedef更改变量类型名

    struct{char x; int y; float z;} StructName;

    引用结构体成员:

    StructName.x = 'T';
    StructName.y = 123;
    StructName.z = 55.55;
    //或者
    pStructName->x = 'T'; //pStructName为结构体的地址    
    pStructName->y = 123;
    pStructName->z = 55.55;

    枚举 enum

    用途:定义一个取值受限制的整型变量,用于限制变量取值范围;宏定义的集合.
    定义枚举变量:因为枚举变量类型较长,所以通常用typedef更改变量类型名

    enum{FALSE = 0, TRUE = 1} EnumName;

    引用枚举成员:

    EnumName = FALSE;
    EnumName = TRUE;

    这里知识简单说明,如果想要深入学习,可以看下面的C语言系列讲解。

    C语言语法和结构总结系列专栏
     

    作者:TENET-

    物联沃分享整理
    物联沃-IOTWORD物联网 » 深入解析STM32 GPIO的输入和输出函数

    发表评论