一、GPIO口初始化步骤
启动GPIO时钟外设总共三步1.启动RCC时钟,2.利用GPIO_Init初始化IO口3.开启关闭IO口
1.RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
该函数用于启动STM32外设时钟,通过跳转选择相应IO口时钟。
2.GPIO_Init(GPIOA,&GPIO_InitStructure);//选择配置GPIOC输出口,并且吧上述定义的结构提初始指针给GPIO_Init
3.GPIO_InitTypeDef GPIO_InitStructure ; //创建一个结构体,下面三行为结构体三个参数
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//配置结构体的参数,GPIO模式, //outpp表示推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;//选择具体哪个引脚,这里是13引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//选择时钟频率吧
二、GPIO口工作模式
1.GPIO_Mode_AIN = 0x0,模拟输入模式
STM32微控制器的模拟输入模式(GPIO_Mode_AIN
)是GPIO的一种配置方式,主要用于ADC(Analog-to-Digital Converter,模数转换器)的模拟信号输入。当配置为模拟输入模式时,GPIO引脚可以接收模拟信号,例如来自传感器的电压信号,并将这些信号转换为数字值供微控制器处理 。
在模拟输入模式下,信号不经过肖特基触发器触发,因为肖特基触发器的信号只有0或1两种状态,而模拟信号是连续的。这种模式适用于处理如温湿度传感器、光敏传感器、烟雾传感器等设备的数据采集 。此外,模拟输入模式还可以用于低功耗应用,因为它允许微控制器在低功耗状态下从外部模拟信号源获取数据 。当配置GPIO为模拟输入模式时,信号是直接被ADC模块读取,而不经过任何内部的上拉或下拉电阻,这样可以减少电阻对信号的影响,提高测量的准确性 。
总结来说,STM32的模拟输入模式是专为ADC设计的,用于读取连续变化的模拟电压信号,常见于各种传感器的数据采集应用。
2.GPIO_Mode_IN_FLOATING = 0x04,浮空输入
在STM32微控制器中,浮空输入(Floating Input)是一种GPIO(通用输入输出)引脚的配置模式。当一个GPIO引脚被配置为浮空输入模式时,它没有内部上拉或下拉电阻,因此引脚的电平状态将由外部连接的电路决定。以下是浮空输入模式的一些关键特点:
-
高阻态:浮空输入模式下,GPIO引脚呈现高阻抗状态,这意味着它不向外部电路提供电流,也不从外部电路吸收电流。
-
外部决定电平:由于没有内部电阻,引脚的电平(高或低)完全取决于外部电路。如果引脚未连接任何电路,它可能会因为内部或外部的噪声而随机地处于不确定的电平状态。
-
敏感性:浮空输入模式下的引脚对外部噪声较为敏感,因此在使用时可能需要特别注意电路的布线和屏蔽,以减少噪声干扰。
-
应用场景:浮空输入通常用于需要检测外部电路状态的情况,例如按键输入、触摸传感器等。在这些应用中,外部设备(如按键)可以连接到GPIO引脚和地之间,当按键未按下时,引脚由于内部结构原因可能呈现高电平状态;按下按键时,引脚连接到地,变为低电平。
-
配置方法:在STM32中,将GPIO配置为浮空输入通常涉及到设置GPIO的模式寄存器,选择相应的浮空输入模式选项,例如
GPIO_Mode_IN_FLOATING
。 -
注意事项:由于浮空输入的不确定性,在读取引脚状态时可能需要通过软件进行去抖动处理,以确保读取的稳定性和准确性。
浮空输入是一种灵活的GPIO配置方式,但在设计电路时需要考虑到其对噪声的敏感性以及可能的不确定性。正确使用浮空输入可以为某些特定的应用场景提供便利。
3.GPIO_Mode_IPD = 0x28,下拉输入
在STM32微控制器中,下拉输入(Pull-Down Input)是一种GPIO(通用输入输出)引脚的配置模式,它通过内部的下拉电阻将GPIO引脚拉低至地(GND)电平。以下是下拉输入模式的一些关键特点:
-
内部电阻:在下拉输入模式下,GPIO引脚内部连接有一个下拉电阻,通常这个电阻的阻值是固定的,并且由微控制器的制造商决定。
-
稳定电平:由于内部下拉电阻的存在,即使引脚未连接任何外部电路,GPIO引脚也会稳定在一个低电平状态。
-
减少噪声:下拉输入模式可以帮助减少由于外部电路的噪声或干扰导致的不确定电平状态,提高信号的稳定性。
-
应用场景:下拉输入通常用于需要确保引脚在未连接或浮空状态下保持低电平的应用,例如某些类型的按键输入,或者在通信协议中确保数据线在无信号时保持低电平状态。
-
配置方法:在STM32中,将GPIO配置为下拉输入通常涉及到设置GPIO的模式寄存器,选择相应的下拉输入模式选项,例如
GPIO_Mode_IPD
。 -
与其他模式的比较:
- 与浮空输入(
GPIO_Mode_IN_FLOATING
)相比,下拉输入提供了一个确定的低电平状态。 - 与上拉输入(
GPIO_Mode_IPU
)相比,下拉输入将引脚拉至低电平而不是高电平。
- 与浮空输入(
-
注意事项:在使用下拉输入时,需要确保外部电路的设计不会与内部下拉电阻产生冲突,例如,不应在已经配置为下拉输入的引脚上再连接外部上拉电阻。
下拉输入是一种常见的GPIO配置方式,适用于需要确保引脚保持低电平状态的场合。通过内部下拉电阻,它提供了一种简单有效的方法来避免引脚的不确定状态。
4.GPIO_Mode_IPU = 0x48,上拉输入
在STM32微控制器中,上拉输入(Pull-Up Input)是一种GPIO(通用输入输出)引脚的配置模式,它通过内部的上拉电阻将GPIO引脚拉高至正电源(VDD)电平。以下是上拉输入模式的一些关键特点:
-
内部电阻:在上拉输入模式下,GPIO引脚内部连接有一个上拉电阻,这个电阻的阻值通常是固定的,由微控制器的制造商决定。
-
稳定电平:由于内部上拉电阻的存在,即使引脚未连接任何外部电路,GPIO引脚也会稳定在一个高电平状态。
-
减少噪声:上拉输入模式可以帮助减少由于外部电路的噪声或干扰导致的不确定电平状态,提高信号的稳定性。
-
应用场景:上拉输入通常用于需要确保引脚在未连接或浮空状态下保持高电平的应用。例如,某些类型的按键输入,或者在通信协议中确保数据线在无信号时保持高电平状态。
-
配置方法:在STM32中,将GPIO配置为上拉输入通常涉及到设置GPIO的模式寄存器,选择相应的上拉输入模式选项,例如
GPIO_Mode_IPU
。 -
与其他模式的比较:
- 与浮空输入(
GPIO_Mode_IN_FLOATING
)相比,上拉输入提供了一个确定的高电平状态。 - 与下拉输入(
GPIO_Mode_IPD
)相比,上拉输入将引脚拉至高电平而不是低电平。
- 与浮空输入(
-
注意事项:在使用上拉输入时,需要确保外部电路的设计不会与内部上拉电阻产生冲突,例如,不应在已经配置为上拉输入的引脚上再连接外部下拉电阻。
-
功耗考虑:由于上拉电阻会持续从VDD吸取电流,因此在低功耗应用中需要考虑这种配置对功耗的影响。
上拉输入是一种常见的GPIO配置方式,适用于需要确保引脚保持高电平状态的场合。通过内部上拉电阻,它提供了一种简单有效的方法来避免引脚的不确定状态,同时在设计电路时需要考虑到功耗和外部电路的兼容性。
5.GPIO_Mode_Out_OD = 0x14,开漏输出
开漏输出模式(Open-Drain Output)是一种特殊的输出配置,在这种模式下,输出引脚可以被配置为只输出低电平或者高阻态(高阻态可以理解为不输出任何电平,即不驱动负载)。在开漏输出模式下,引脚的输出能力有限,它不能直接驱动负载,但可以通过外部上拉电阻来实现高电平的输出。
在嵌入式系统和微控制器编程中,开漏输出模式常用于:
-
多设备共享数据线:在I2C等通信协议中,多个设备可以共享数据线(SDA),每个设备的数据输出引脚都配置为开漏模式,通过外部上拉电阻来实现高电平。当某个设备输出低电平时,它会覆盖其他设备的高电平,从而实现数据的传输。
-
灵活的电平控制:由于开漏引脚可以输出低电平或高阻态,它允许通过外部电路(如上拉电阻)来控制电平,这在某些需要灵活电平控制的应用中非常有用。
-
减少电源消耗:在某些应用中,通过使用开漏输出和外部上拉电阻,可以减少微控制器的电源消耗,因为微控制器不需要在高电平时提供电流。
6.GPIO_Mode_Out_PP = 0x10,推挽输出
STM32微控制器中的推挽输出(Push-Pull Output)是一种GPIO(通用输入输出)引脚的配置模式,用于驱动外部电路。以下是推挽输出模式的一些关键特点:
-
双向驱动能力:推挽输出模式允许GPIO引脚既可以向外部电路提供电流(sink current),也可以从外部电路吸收电流(source current),即可以输出高电平也可以输出低电平。
-
强电流驱动:与开漏输出(Open-Drain Output)相比,推挽输出可以提供更强的电流驱动能力,适合驱动LED、继电器、蜂鸣器等负载。
-
配置方法:在STM32中,将GPIO配置为推挽输出通常涉及到设置GPIO的模式寄存器,选择推挽输出模式选项,例如
GPIO_Mode_Out_PP
。 -
应用场景:推挽输出模式适用于需要直接控制数字设备(如LED、继电器等)的开关状态的场景。
-
内部结构:推挽输出通常由两个互补的晶体管构成,一个负责输出高电平,另一个负责输出低电平。当一个晶体管导通时,另一个晶体管截止。
-
注意事项:
- 在设计电路时,需要注意推挽输出的电流能力,避免超过GPIO引脚的最大电流承受能力。
- 如果需要驱动较高电流的负载,可能需要在GPIO和负载之间添加适当的驱动器或晶体管。
-
与开漏输出的区别:开漏输出模式下,GPIO引脚只能输出低电平或高阻态,需要外部上拉电阻来实现高电平输出。而推挽输出模式则可以直接输出高电平。
-
功耗考虑:由于推挽输出可以提供较强的电流驱动能力,因此在设计时也需要考虑功耗和散热问题。
推挽输出是一种常用的GPIO配置方式,适用于需要直接控制外部数字负载的场景。它提供了一种简单有效的方法来实现GPIO引脚的数字输出功能。
7.GPIO_Mode_AF_OD = 0x1C,复用开漏输出
在STM32微控制器中,复用开漏输出(Alternate Function Open-Drain Output)是一种特殊的GPIO配置模式,它结合了复用功能和开漏输出的特性。以下是复用开漏输出模式的一些关键特点:
-
复用功能:在STM32微控制器中,GPIO引脚通常具有多种复用功能,例如可以作为通用I/O使用,也可以配置为特定的外设功能,如USART的TX/RX、I2C的SCL/SDA等。
-
开漏输出特性:开漏输出模式意味着GPIO引脚可以输出低电平或高阻态。在高阻态时,引脚不驱动任何电流,需要外部上拉电阻来实现高电平输出。
-
配置方法:要配置为复用开漏输出,需要先使能相应的复用功能,然后设置GPIO的模式寄存器为开漏输出模式,例如使用
GPIO_Mode_AF_OD
。 -
应用场景:
- 多设备共享数据线:在像I2C这样的总线通信协议中,多个设备可以共享数据线,每个设备的数据线(SDA)引脚都配置为开漏输出,通过外部上拉电阻实现高电平。
- 灵活的电平控制:由于开漏引脚可以输出低电平或高阻态,它允许通过外部电路来控制电平,这在需要灵活电平控制的应用中非常有用。
-
与推挽复用输出的区别:复用推挽输出(Alternate Function Push-Pull Output)可以直接输出确定的高电平或低电平,而复用开漏输出则需要外部上拉电阻来实现高电平。
-
注意事项:
- 在设计电路时,需要确保外部上拉电阻的阻值适当,以确保在开漏输出模式下能够获得正确的高电平。
- 由于开漏输出的驱动能力较弱,它通常不适用于驱动高电流负载。
-
功耗考虑:由于开漏输出在高阻态时不消耗电流,因此在某些低功耗应用中可能是一个合适的选择。
复用开漏输出模式在STM32微控制器中非常有用,特别是在需要多设备共享数据线或需要灵活电平控制的场景中。通过适当的外部电路设计,可以实现高效的通信和信号处理。
8. GPIO_Mode_AF_PP = 0x18,复用推挽输出
STM32的复用推挽输出(Alternate Function Push-Pull Output)是一种GPIO(通用输入输出)引脚的配置模式,它结合了复用功能和推挽输出的特性。以下是复用推挽输出模式的一些关键特点:
-
复用功能:STM32微控制器的GPIO引脚可以配置为多种复用功能,这些功能通常与微控制器的外设相关,如USART、SPI、I2C等。
-
推挽输出特性:推挽输出模式允许GPIO引脚输出确定的高电平或低电平,具有双向驱动能力,可以向外部电路提供或吸收电流。
-
配置方法:要配置为复用推挽输出,首先需要使能相应的复用功能,然后设置GPIO的模式寄存器为推挽输出模式,例如使用
GPIO_Mode_AF_PP
。 -
应用场景:
- 外设通信:复用推挽输出通常用于微控制器与外部设备之间的通信,如I2C的SCL/SDA、SPI的SCK/MOSI/MISO等。
- 数字信号控制:在需要提供确定电平的数字信号控制场合,复用推挽输出可以直接驱动外部数字电路。
-
与开漏复用输出的区别:与复用开漏输出(Alternate Function Open-Drain Output)相比,复用推挽输出可以直接输出高电平而不需要外部上拉电阻。
-
注意事项:
- 在设计电路时,需要确保GPIO引脚的复用功能与所需的外设功能相匹配。
- 由于推挽输出可以提供较强的电流驱动能力,需要考虑GPIO引脚的最大电流承受能力,避免超负荷。
-
功耗考虑:虽然推挽输出在高电平时不消耗电流,但在设计时仍需考虑整体系统的功耗,特别是在使用多个推挽输出引脚时。
-
信号完整性:由于推挽输出具有一定的驱动能力,它可以减少信号线上的噪声和干扰,提高信号的完整性。
复用推挽输出模式在STM32微控制器中非常有用,特别是在需要与外部设备进行数字通信或控制的场景中。通过适当的配置,可以实现高效的外设通信和信号控制。
三、GPIO口定义
#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口速度,一般选择50MHz
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
五、GPIO输入函数
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);根据第三个参 数来设定指定的端口,第三个参数可以是BitAction中枚举,如Bit_Reset表示低电平
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);对16个端口进行写入操作,如GPIO_Write(GPIOA,~GPIO_Pin_0);表示给A0口置为低电平
六、初始化多个端口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;表示同时初始化A0~A4口,GPIO_Pin_ALL表示初始化所有端口。
同时时钟的初始化也可以用RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB来实现,该段代码表示同时初始化A和B两个端口。
七、函数引用
要写函数,必须同时包括.c和.h类型文件,其中.c文件里面是对函数的具体定义;.h文件是对.c文件中函数的声明,同时要在main.c中引用,则必须用头文件形式包含.h文件。
例子:.h文件
#ifndef __DELAY_H
#define __DELAY_H
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);
#endif
.c文件
#include "stm32f10x.h"
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--)
{
Delay_ms(1000);
}
}