STM32学习笔记(四)GPIO(General-Purpose I/Os)

输出方式

推挽输出(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寄存器

I/O端口位的基本结构
  • 端口配置低寄存器 --- 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_InitStructGPIO_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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容