GPIO之IDR、ODR及BSRR寄存器详解

IDR (Input Data Register, 输入数据寄存器)

        每个GPIO端口对应一个IDR寄存器(如GPIOA一个IDR寄存器,GPIOB又一个寄存器),而每一个GPIO引脚(如GPIO_PIN_0)对应IDR寄存器的一位,IDR寄存器的位值对应该引脚的电平【0-0(逻辑低),1-1(逻辑高)】

        例如STM32为32位的处理器,其数据总线宽度、寄存器宽度和指令集都是32位的,故其IDR寄存器也是32位的。如果 GPIO 端口支持 16 个引脚(例如 GPIOA),IDR 的低 16 位(位 0 ~ 15)对应 GPIOA 的引脚 0 到引脚 15。剩余的高 16 位(位 16 ~ 31)是未使用的,在这种情况下,这些位通常是固定的 0。如下图所示则表示GPIO_PIN_15和GPIO_PIN_9为高电平,其余为低电平.

IDR寄存器
位数 31 30 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
位值 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0

实际应用示例:

补充:GPIO_PIN_13是位掩码,对应0x2000 = 0010 0000 0000 0000

#define    DATA_READ_GPIO          GPIOD                   
#define    DATA_READ_PIN           GPIO_PIN_13 

uint8_t Data=0;
//高位先行
for(int i=7;i--;i>=0)
{
    if(DATA_READ_GPIO->IDR&GPIO_PIN_13==1)Data|=1<<i;    
    else Data|=0<<i;
}


ODR 寄存器Output Data Register,输出数据寄存器)

        同IDR寄存器,每一个GPIO引脚(如GPIO_PIN_0)对应IDR寄存器的一位,IDR寄存器的位值对应该引脚的电平【0-0(逻辑低),1-1(逻辑高)】,也是32位。高16位为0,低16位一一对应,只不过ODR是输出,IDR是输入。

实际应用示例:

//精准控制
GPIOA->ODR|=GPIO_PIN_13;    //GPIOA的第13号引脚输出高电平
GPIOA->ODR|=~GPIO_PIN_13;   //GPIOA的第14号引脚输出低电平

//LED闪烁
GPIOA->ODR ^= GPIO_PIN_13;  // 翻转 LED 状态

BSRR 寄存器Bit Set/Reset Register,位设置/复位寄存器)

BSRR位结构
位数 功能 描述
0-15 Set位 写入 1 设置对应引脚为高电平(0-15号引脚)
16-31 Reset位 写入 1 设置对应引脚为低电平(0-15号引脚)

 

相对ODR寄存器的优点是:

通过一次写入寄存器的方式,可以同时设置多个引脚为高电平或低电平,避免因中断或任务切换导致的不一致问题。例如:可以同时设置 GPIO 引脚 13 为高电平,同时将 GPIO 引脚 14 拉低。

实际应用示例:

GPIOC->BSRR = GPIO_PIN_13;          // 写入 BSRR 的第 13 位(0~15),引脚 13 被置位
GPIOC->BSRR = GPIO_PIN_13 << 16;    // 写入 BSRR 的第 29 位(16~31),引脚 13 被复位

GPIOC->BSRR = GPIO_PIN_13 | (GPIO_PIN_14 << 16);  //将引脚13拉高,同时将引脚14拉低

如果BSRR 第0位和第16位同时置1。最终,GPIO_PIN_0设置复位操作会覆盖置位操作,GPIO_PIN_0 引脚的状态为 低电平.

【使用BSRR相对ODR的优点是能够避免竞态问题】

作者:大只L

物联沃分享整理
物联沃-IOTWORD物联网 » GPIO之IDR、ODR及BSRR寄存器详解

发表回复