stm32 - GPIO
- GPIO结构图
 - GPIO原理图
 - 输入
 - 上拉/下拉/浮空
 - 施密特触发器
 - 片上外设
 
- 输出
 - 推挽/开漏/关闭输出方式
 
- GPIO88种模式
 - 复用输出
 
- GPIO寄存器
 - 端口配置寄存器_CRL
 - 端口输入数据寄存器_IDR
 - 端口输出数据寄存器_ODR
 - 端口位设置/清除寄存器_BSRR
 - 端口位清除寄存器_BRR
 - 端口配置锁定寄存器
 
- 例子
 - 点灯
 - 流水灯
 - 蜂鸣器
 
GPIO结构图
GPIO全都挂载在APB2总线上的
每个GPIOA 都有16个引脚
寄存器:输入寄存器和输出寄存器,输出寄存器引脚输出电平,输入寄存器从引脚读取当前电平
每个寄存器有32位,但是每个寄存器都只对应16个引脚,所以只使用寄存器中的低16 位
驱动器负责增大信号的驱动能力
GPIO原理图

输入
上拉/下拉/浮空

为了给输入一个默认的输入电平
为了避免引脚悬空导致输入数据的不稳定,需要加上上拉电阻或下拉电阻
上拉电阻:浮空引脚,保证引脚的高电平
下拉电阻:浮空引脚,保证引脚的低电平
上拉输入:高电平输入
下拉输入:低电平输入
施密特触发器
对输入电压进行整形,防止干扰
如果输入电压大于某一阈值,输出就会瞬间升为高电平
如果输入电压小于某一阈值,输出就会瞬间降为低电平

片上外设
- 模拟输入 ADC等
 - 复用输入 数字量
 
输出
- 输出寄存器:写某一位控制某一个引脚(用位设置和位清楚寄存器更好)
 - 片上外设
 
推挽/开漏/关闭输出方式

- 推挽输出
 
高低电平均有强驱动能力
P-MOS和N-MOS均有效
输出数据寄存器为1时,上管导通PMOS导通,下管NMOS断开,输出直接接到VDD,输出高电平
输出数据寄存器为0时,上管导通PMOS断开,下管NMOS导通,输出直接接到VSS,输出低电平
- 开漏输出
 
低电平有强驱动能力,高电平没有驱动能力
P-MOS无效,N-MOS有效
输出数据寄存器为1时,上管导通PMOS无效,下管NMOS断开,输出相当于断开,相当于高阻模式
输出数据寄存器为0时,上管导通PMOS无效,下管NMOS导通,输出直接接到VSS,输出低电平
开漏输出接外部的上拉5V电源
- 关闭输出
 
引脚配置为输入模式的时候
两个MOS管均无效
GPIO88种模式

复用输出
由片上外设进行输出
GPIO寄存器
端口配置寄存器_CRL
GPIOX_CRL
一共32位,每4位对应一个IO的配置,可配置8个引脚
端口输入数据寄存器_IDR
GPIOX_IDR
32位,低16位对应16个引脚
端口输出数据寄存器_ODR
GPIOX_ODR
32位,低16位对应16个引脚
端口位设置/清除寄存器_BSRR
GPIOX_BSRR
32位,高16位用于进行位清除,低16位用于进行位设置
端口位清除寄存器_BRR
32位,低16位用于进行位清除
端口配置锁定寄存器
端口锁定
例子
点灯
main.cpp
#include "stm32f10x.h"
#include "Delay.h"
int main()
{
	// 初始化APB2外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 
	
	// 配置GPIO - ODR/CLR
	GPIO_InitTypeDef GPIO_InitStructure;			// 配置结构体
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; 	// GPIO_Mode_Out_PP 推挽输出
//	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD; 	// GPIO_Mode_Out_OD 开漏输出 	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;			// GPIOA的0号引脚
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; // 50MHZ 
	
	GPIO_Init(GPIOA,&GPIO_InitStructure); // A0推挽输出
	
//	GPIO_SetBits(GPIOA,GPIO_Pin_0); 	// 设置为高电平
//	GPIO_ResetBits(GPIOA,GPIO_Pin_0); 	// 设置为低电平
//	GPIO_Write();
//	GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET); // Bit_RESET 低电平	
//	GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET); // Bit_SET 高电平
	while (1)
	{
//		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET); 	// Bit_RESET 低电平
		GPIO_ResetBits(GPIOA,GPIO_Pin_0);			// version2
		Delay_ms(500);
//		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET); 	// Bit_SET 高电平
		GPIO_SetBits(GPIOA,GPIO_Pin_0);				// version2
		Delay_ms(500);
	}
}
 
delay.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);
	}
} 
 
流水灯
#include "stm32f10x.h"
#include "Delay.h"
int main()
{
	// 初始化APB2外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 
	
	/* ====== 流水灯 ====== */
	// 配置GPIO - ODR/CLR register
	GPIO_InitTypeDef GPIO_InitStructure;			// 配置结构体
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; 	// GPIO_Mode_Out_PP 推挽输出	
	/*
	 * #define GPIO_Pin_0                 ((uint16_t)0x0001)
	 * #define GPIO_Pin_1                 ((uint16_t)0x0002)
	 * #define GPIO_Pin_2                 ((uint16_t)0x0004)
	 * #define GPIO_Pin_3                 ((uint16_t)0x0008)
	 * #define GPIO_Pin_4                 ((uint16_t)0x0010)
	 * #define GPIO_Pin_5                 ((uint16_t)0x0020)
	 * #define GPIO_Pin_6                 ((uint16_t)0x0040)
	 * #define GPIO_Pin_7                 ((uint16_t)0x0080)
	 * GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7
	 * 等价于 0x0001 | 0x0002 ... 位之间并不冲突
	 */
//	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;			// GPIOA的0号引脚
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; // 50MHZ 
	
	GPIO_Init(GPIOA,&GPIO_InitStructure); // A0推挽输出
	while (1)
	{
		for (int i=0;i<8;i++)
		{
			GPIO_Write(GPIOA,~(0x0001<<i));
//			GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
			Delay_ms(100);
		}
	}
}
 
蜂鸣器
#include "stm32f10x.h"
#include "Delay.h"
int main()
{
	// 初始化APB2外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); 
	
	// 配置GPIO - ODR/CLR
	GPIO_InitTypeDef GPIO_InitStructure;			// 配置结构体
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; 	// GPIO_Mode_Out_PP 推挽输出
//	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD; 	// GPIO_Mode_Out_OD 开漏输出 	
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_12;			// GPIOA的0号引脚
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; // 50MHZ 
	
	GPIO_Init(GPIOB,&GPIO_InitStructure); // A0推挽输出
	
//	GPIO_SetBits(GPIOB,GPIO_Pin_12); 	// 设置为高电平
//	GPIO_ResetBits(GPIOB,GPIO_Pin_12); 	// 设置为低电平
//	GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET); // Bit_RESET 低电平	
//	GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET); // Bit_SET 高电平
	while (1)
	{
//		GPIO_WriteBit(GPIOB,GPIO_Pin_0,Bit_RESET); 	// Bit_RESET 低电平
		GPIO_ResetBits(GPIOB,GPIO_Pin_12);			// version2
		Delay_ms(500);
//		GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET); 	// Bit_SET 高电平
		GPIO_SetBits(GPIOB,GPIO_Pin_12);				// version2
		Delay_ms(500);
	}
	
}
                





![2023年中国智能电视柜产量、需求量、市场规模及行业价格走势[图]](https://img-blog.csdnimg.cn/img_convert/f189ab4f3166845d1771bce82cd76bdf.png)









![web:[RoarCTF 2019]Easy Calc](https://img-blog.csdnimg.cn/ff66f1b7cdac4bfa99a9784d7e716a68.png)



