文章目录
- 一、GPIO是什么?
- 二、外设框图
-
- 保护二极管
- 2.上下拉电阻
- 输入数据寄存器
- 4、模拟输入
- 5用功能输入
- 6.输出数据寄存器
- 7.位置设置/清除寄存器
- 8.复用功能输出
- 9、双MOS管结构
-
- (1)推拉输出
- (2)泄漏输出
- 10.端口配置寄存器(不在框图中)
- 三、编程
- 四、答疑
-
- 1、GPIO引脚驱动能力?
- 2.我怎么知道为什么每个外设都应该配置相应的引脚?
- 参考资料
一、GPIO是什么?
GPIO全称general-purpose input/output ,即通用输入输出端口。
二、外设框图
**输入通道整体输入逻辑:**通过外部信号IO进入单片机后,首先通过保护二极管检查是否有破坏性。检查通过后,通过上下拉电路。该电路设置默认电平。从这里开始,信号要么直接输入,即模拟输入,要么通过触发器转换为数字信号,然后分叉,要么保存在输入数据寄存器中,用户读取,要么重上外设读取。
保护二极管
采用二极管达到阈值电压单向导通的特点,防止从引脚输入过大或过小的电压。
当输入电压超过时VDD 0.7V(如果是硅管),则上述二极管导通。 当输入电压小于Vss-0.7V,下面的二极管导通。
因此,真正输入芯片的电压钳位于Vss-0.7V至VDD 0.7V之间。
2.上下拉电阻
有三种情况可以控制内部是否接入上下拉电阻: ①只打开上拉电阻,引脚默认输出高电平 ②只打开下拉电阻,引脚默认输出低电平 ③上拉下拉电阻不打开,此时引脚处于
在浮动模式下,引脚的电压不确定,可能是1,也可能是0,来回摆动。
根据拉电阻的电阻大小,可分为或。
拉电阻小时为强拉,能抵抗外界噪声,成本是相应的功耗。
STM32内部的拉电阻为弱拉。通过查阅数据手册,拉电阻值为40K左右,如果你想输出一个大电流,通过这个拉电阻输出的电流很小。然后需要外部电阻值较小的拉电阻,实际上是为了增加导线的输出电流。
输入数据寄存器
通过上下拉电阻的信号有三个方向,一是通过触发器转换为0/1进入输入数据寄存器。
4、模拟输入
其次,如果信号不通过触发器,外部模拟信号可以直接输入内部ADC。
5用功能输入
第三个方向是将信号转换为0/1,然后交给外设。
**输出通道的整体逻辑:**有一个输出数据源。首先,我可以控制位置设置/清除寄存器IO我也可以将多个二进制数据写入数据输出寄存器IO口依次输出,我也可以把控制权交给电影内外设备,让它控制IO输出它想要输出的信号。是用户控制还是外设控制由输出控制左侧的梯形结构切换,输出信号通过双MOS 结构可调整为推拉模式或开漏模式IO口输出。
6.输出数据寄存器
将要输出的数据放入寄存器
7.位置设置/清除寄存器
将IO口置0或置1。
高16人负责reset,低16位负责set。
除了GPIOx_BSRR,还有一个类似的寄存器叫做GPIOx_BRR,它相当于GPIOx_BSRR的高16位 这个多余寄存器只是为了方便IO口清0,不像BSRR要清零,必须在写入之前将数据左移16位。
8、复用功能输出
将GPIO输出控制权交给内外设,输出外设想要输出的信号。
9、双MOS管结构
这种结构是可以实现的与。
(1)推拉输出
两个推挽输出MOS管都工作。
当输入为1时,通过反相器获得0PMOS导通,NMOS截止日期,电流从VDD推输出端,最后输出1;
当输入为0时,通过反相器获得1PMOS截止,NMOS导通,电流从输出端拉回,拉回也就是拉回,最后输出0;
(2)泄漏输出
只使用开漏输出NMOS。
当输入为1时,通过反相器获得0NMOS截止日期,引脚相当于内部断开,既不输出1也不输出0,对输出有很高的阻力;
当输入为0时,通过反相器获得1NMOS导通,对外输出0;
要输出高电平,需要增加拉电阻: 这种结构的一个重要特点是特点是,当多个设置为泄漏输出模式的引脚连接在一起时,只要一个引脚输出为0,整个线路为0,只有所有引脚输出为高阻力,线路电平为1。
泄漏输出的应用: ①I2C通信,通信协议通过线和解决多主机同时发送数据的优先判断,详见【STM32】I2C ②电平转换,如果需要3.3V单片机控制5V外设可采用开漏输出模式和连接5V的上拉电阻
10.端口配置寄存器(不在框图中)
有两个端口配置寄存器,其中GPIOx_CRL控制低8位,GPIOx_CRH控制高8位。 这两个32位寄存器分别控制16个IO口,每个IO口都有专属的MODE[1:0]和CNF控制。
其中,MODE控制是输入还是输出,输出有详细的速度配置,支持率越高,功耗越大。
CNF控制在输入和输出模式下具体的工作模式配置。
GPIO共有8种工作模式: ①例如,模拟输入ADC采集 ②上拉输入 ③下拉输入 ④浮空输入,如按钮检测
⑤推挽输入,如点亮LED ⑥泄漏输出,如I2C,电平转换 ⑦复用推挽输出,即由外设控制输出 ⑧复用开漏输出由外设控制
三、编程
首先初始化GPIO
void LED_GPIO_Config(void) {
/*定义一个GPIO_InitTypeDef结构类型*/ GPIO_InitTypeDef GPIO_InitStructure; /*开启LED相关的GPIO外设时钟*/ RCC_APB2PeriphClockCmd( LED1_GPIO_CLK, ENABLE); /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIO*/
GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
/* 关闭所有led灯 */
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
}
然后就可以库函数了
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);//填充GPIO_InitStruct内的元素为复位值
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//读指定IO引脚输入数据
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);//置1指定的端口引脚
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//清0指定的端口引脚
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);//设置或清除选择的数据端口引脚
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);//写指定数据到GPIOx端口寄存器
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);//选择GPIO引脚作为事件输出
void GPIO_EventOutputCmd(FunctionalState NewState);//允许或禁止事件输出
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);//选择IO口作为事件线
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);
四、答疑
1、GPIO引脚驱动能力?
25mA,可以驱动一般的发光二极管。
2、我怎么知道每个外设相应的引脚应该配置为什么模式?
参考手册中有明确规定
参考资料
1、《STM32库开发实战指南》 2、https://zhuanlan.zhihu.com/p/362467204
待补充内容:GPIO中断