赞
踩
目录
在STM32中,所有的GPIO都是挂载在APB2外设总线上的。
(1)施密特触发器:对输入电压进行整形。其执行逻辑为:如果输入电压大于某一阈值,输出就会瞬间升为高电平
(2)模拟输入:这个是连接到ADC(片上外设)上的,因为ADC需要接收模拟量,所以接到施密特触发器前面。
(3)复用功能输入:这个是连接到其他需要读取端口的外设上的,比如串口的输入引脚等,这根线接收的是数字量,所以接到施密特触发器后面。
(4)输出数据寄存器(ODR):写其的某一位就可以操作对应的某个端口。
(5)位设置/清除寄存器:可用来单独操作输出数据寄存器的某一位,而不是影响其他位。因为输出数据寄存器同时控制16个端口,并且这个寄存器只能整体读写,所以想单独控制其中某一个端口而不影响其他端口的话,就需要一些特殊的方式:
先读出这个寄存器,然后用按位与和按位或的方式更改某一位(&= |=),最后再将更改后的数据写回去。但这种方法效率不高且麻烦,对IO口的操作而言不太合适
通过设置这个位设置/清除寄存器,如果我们要对某一位置1,在位设置寄存器的对应位写1即可,剩下不需要操作的位写0,这样它内部就会有电路自动将位设置寄存器中对应位置1,而剩下写0的位保持不变。保证了只操作其中某一位而不影响其它位,并且这是一步到位的操作。如果想对某一位进行清0的操作,就在位清除寄存器的对应位写1即可,内部电路会把这一位清0.
读写STM32中的“位带”区域,这个位带的作用跟51单片机的位寻址作用差不多。在STM32中,专门分配有一段地址区域,这段地址映射了RAM和外设寄存器所有的位,读取这段地址中的数据,就相当于读写所映射位置的某一位,这就是位带的操作方式。
输出模式 | 控制开关 | 工作方式 | 特点 |
推挽输出 | P-MOS、N-MOS均有效 | 数据寄存器为1时,上管导通,下管断开,输出直接接到VDD,即高电平;反之则是低电平 | 这种模式下,高低电平均有较强的驱动能力,所以推挽输出模式也可以叫强推输出模式(STM32对IO口具有绝对的控制权,高低电平都由STM32说了算) |
开漏输出 | P-MOS无效、N-MOS均有效 | 数据寄存器为1时,下管断开,下管断开,输出相当于断开,即高阻模式。数据寄存器为0时,下管导通,输出直接接到VSS,即输出低电平。这种模式下,只有低电平有驱动能力,高电平没有驱动能力。 | 这个开漏模式可以作为通信协议的驱动方式,比如I2C通信的引脚,就是使用的开漏模式。在多机通信的情况下,这个模式可以避免各个设备的相互干扰。另外开漏模式还可以用于输出5V的电平信号。 |
关闭 | P-MOS、N-MOS均有效 | 当引脚配置为输入模式的时候,输出关闭,端口的电平由外部信号来控制 |
(1)1、2、3模式的电路结构基本一样,区别就是上拉电阻和下拉电阻的连接。
(浮空输入下,端口一定要接上一个连续的驱动源,不能出现悬空的状态)
(2)
(3)
(4)
GPIO_Mode_AIN | Analog In--模拟输入 |
GPIO_Mode_IN_FLOATING | Floating--浮空输入 |
GPIO_Mode_IPD | In Pull Down--下拉输入 |
GPIO_Mode_IPU | In Pull Up--上拉输入 |
GPIO_Mode_OUT_OD | Out Open Drain--开漏输出 |
GPIO_Mode_OUT_PP | Out Push Pull--推挽输出(点灯 ) |
GPIO_Mode_AF_OD | Atl Open Drain--复用开漏 |
GPIO_Mode_AF_PP | Atl Push Pull--复用推挽 |
LED:长正短负,小正大负。
以上图为例,将P1^2引脚接低电平,蜂鸣器响,接高电平,蜂鸣器关闭(低电平触发)。
(1)低电平驱动LED:当PA0输出低电平时,LED两端就会产生电压差,从而形成正向导通的电流,LED点亮。
该GPIO在推挽输出模式下,高低电平均有比较强的驱动能力,故两种接法均可。但在单片机的电路里,一般使用低电平驱动,因为很多单片机或者芯片都使用了“高电平弱驱动,低电平强驱动”的规则。
(2)蜂鸣器电路使用了三极管开关的驱动方案(最简单的驱动电路)(对于功率稍微大一点的电路,直接用IO口驱动会导致STM32负担过重)。三极管左边的是基极,带箭头的是发射极,剩下的是集电极。
PNP三极管:基极给低电平三极管导通, 蜂鸣器有电流,反之没有。
NPN三极管:相反。
(PNP的三极管接在蜂鸣器上面,而NPN的三极管接在蜂鸣器下面,因为三极管的通断需要在发射极和基极直接产生一定的开启电压,若反过来可能导致三极管不能开启)
(3)在PA0口输出高低电平,驱动LED闪烁
(注意因为配置的是GPIO,所以要使用APB2外设总线)
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
-
- int main(void)
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // RCC的APB2外设时钟控制函数(PA0-GPIOA,使能)
-
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //选择0号端口
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
- GPIO_Init(GPIOA, &GPIO_InitStructure); // GPIO初始化(GPOIX, )第二个参数是一个结构体,需要先把结构体类型复制下来,再在前面定义
-
- // GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 设置指定端口为低电平
- // GPIO_SetBits(GPIOA, GPIO_Pin_0); // 设置指定端口为高电平
- // GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); // 设置指定端口为高电平
- // GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); // 设置指定端口为低电平
- // GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0); // 将0强制转换为BitAction的枚举类型,低电平
- // GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1); // 将1强制转换为BitAction的枚举类型,高电平
-
- while(1)
- {
- GPIO_ResetBits(GPIOA, GPIO_Pin_0);
- Delay_ms(500);
- GPIO_SetBits(GPIOA, GPIO_Pin_0);
- Delay_ms(500);
-
- //直接法
- GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
- Delay_ms(500);
- GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
- Delay_ms(500);
-
- //枚举法
- GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);
- Delay_ms(500);
- GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
- Delay_ms(500);
- }
- }
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_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); | 一般可以实现批量或者同时控制多个 GPIO 引脚的输出状态 |
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); | 用来单独设置某一个特定的 GPIO 引脚的输出状态 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。