输出方式
推挽输出(Push-Pull)
- 若 INT 输入为 0,则 PMOS 截止,NMOS 导通,产生灌电流,输出 OUT 为 0;
- 若 INT 输入为 1,则 NMOS 导通,PMOS 截止,产生拉电流,输出 OUT 为 1;
推挽输出特点
- 同时具有高低电压的驱动能力,即高低电平切换所需时间短,反应快;
- 无法实现线与功能(即禁止输出之间短接);
- 结型场效应管的特性(G与D、S近乎绝缘)使得电功率极小;
- 高低电平均由内部 IC 电平决定,通常为一定值;
开漏输出(Open-Drain)
即 漏极(Drain) 一端什么都不接,直接连接 输出端口
- 若 INT 输入为 0,则 NMOS 导通,输出 OUT 为 0;
- 若 INT 输入为 1,则 NMOS 截止,通过上拉电阻使输出 OUT 为 1;
开漏输出特点
- 若无上拉电阻则 INT 输入为 1 时输出 OUT 仍为 0;
- 可以多个 I/O 口共用一个上拉电阻(输出之间短接),形成线与功能(任一条线上输出为0,则所有线均输出为0);
- 上拉电阻取值要合理,电阻过小则电阻上功耗大,电阻过大则使低电平切换至高电平所需的时间过长;
- 开漏输出的高电平取决于上拉电阻接的电压,可实现输出高电平电压的灵活变动;
输入方式
上拉/下拉输入(Pull-up/Pull-down)
- 上拉输入 引脚 初始值为高电平(即通过 BSRR 将 ODR 置位),判定低电平为输入;
- 下拉输入 引脚 初始值为低电平(即通过 BRR 将 ODR 复位),判定高电平为输入;
浮空输入(Floating)
- 初始情况下 引脚 不接高电平也不接低电平,端口呈高阻态;
- 引脚 的电平完全由外部输入决定;
GPIO寄存器
-
端口配置低寄存器 --- CRL(Configuration Register Low):配置低8位脚的输入/输出方式;
- 复位值:0x4444 4444
-
端口配置高寄存器 --- CRH(Configuration Register High):配置高8位脚的输入/输出方式;
- 复位值:0x4444 4444
-
端口输入数据寄存器 --- IDR(Input Data Register):读取端口输入数据,低16位有效(高16位保留);
- 复位值:0x0000 xxxx
- 注意:若为输出模式,则该寄存器的值等于 ODR 寄存器的值;
-
端口输出数据寄存器 --- ODR(Output Data Register):写入端口输出数据,低16位有效(高16位保留);
- 复位值:0x0000 0000
-
位设置/清除寄存器 --- BSRR(Bit Set/Reset Register):一般只用低16位对ODR寄存器进行置位操作(高16位为复位操作);
- 复位值:0x0000 0000
-
端口位清除寄存器 --- BRR(Bit Reset Register):对ODR寄存器进行复位操作,低16位有效(高16位保留);
- 复位值:0x0000 0000
-
端口配置锁定寄存器 --- LCKR(Configuration Lock Register):置1锁定CR寄存器的值,低16位有效;第17位LCKK进行{写1、写0、写1、读0、读1}序列操作更改,LCKK==0时低16位寄存器有效;
- 复位值:0x0000 0000
常用GPIO固件库函数 (stm32f01x_gpio.h)
需要先打开对应GPIOx的时钟才可正常使用GPIO
GPIO初始化函数 --- GPIO_Init
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
- GPIOx:对应的 GPIOx 端口,x可以为 (A~G);
-
GPIO_InitStruct:GPIO_InitTypeDef 结构体
- GPIO_Pin_x:需要配置的对应的脚,x可以为 (0~15);
- GPIO_Speed:输出模式则需配置,可选为 2MHz、10MHz、50MHz;
- GPIO_Mode:AIN——模拟输入、IN_FLOATING——浮空输入、IPD——下拉输入、IPU——上拉输入,Out_OD——开漏输出、Out_PP——推挽输出、AF_OD——复用开漏输出、AF_PP——复用推挽输出;
- 示例:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //选择 Pin0 脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //选择最大速率为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); // GPIOA 的 Pin0 初始化
输出端口引脚置位函数 --- GPIO_SetBits
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- GPIOx:对应的 GPIOx 端口,x可以为 (A~G);
- GPIO_Pin_x:需要置位的对应的脚,x可以为 (0~15);
- 示例:
GPIO_SetBits(GPIOA, GPIO_Pin_0); // GPIOA 的 Pin0 输出高电平
输出端口引脚复位函数 --- GPIO_ResetBits
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- GPIOx:对应的 GPIOx 端口,x可以为 (A~G);
- GPIO_Pin_x:需要置位的对应的脚,x可以为 (0~15);
- 示例:
GPIO_ResetBits(GPIOA, GPIO_Pin_0); // GPIOA 的 Pin0 输出低电平
读输入端口引脚数据函数 --- GPIO_ReadInputDataBit
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- GPIOx:对应的 GPIOx 端口,x可以为 (A~G);
- GPIO_Pin_x:需要读取数据的对应的脚,x可以为 (0~15);
- 返回值:输入高电平为 1,输入低电平为 0;
- 示例:
#define ON 1
if( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == ON )
{
//若 GPIOA 的 Pin0 脚为 ON ,执行下列指令
}
位带操作
即将 一个bit的的数据用 取 32位地址的内容 的方式进行操作。
/********位带操作********/
//把“位带地址+位序号”转换为 位带别名区地址
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
//把地址转换成一个指针
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
//把位带别名区地址转换成指针
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//对 GPIOA 的 Pin0 置为高电平
#define GPIOA_ODR_ADDR (GPIOA_BASE + 0x0C)
BIT_ADDR(GPIOA_ODR_ADDR, 0)