GPIO的寄存器BSRR和BRR使用摘抄汇总

GPIO的寄存器BSRR和BRR

以写数据为例,提供的函数有 
GPIO_SetBits  
GPIO_ResetBits 
GPIO_WriteBit  
GPIO_Write 
比如我在PD口的高八位接了个并行的数据线,低八位为控制,有输入有输出。怎么实现对高八位写任意数而第八位不受影响呢。 
前两个函数肯定都不可以。 
第三个也不行,是对一个或多个IO口置位或复位。 
第四个是写整个口,势必影响到第八位的控制信号啊。 


GPIO的寄存器BSRR和BRR 

端口位设置/复位寄存器BSRR: 注:如果同时设置了BSy和BRy的对应位,BSy位起作用。 

 位31:16  BRy: 清除端口x的位y (y = 0…15)  
    这些位只能写入并只能以字(16位)的形式操作。  
    0:对对应的ODRy位不产生影响  
    1:清除对应的ODRy位为0  

位15:0 BSy: 设置端口x的位y (y = 0…15)  
    这些位只能写入并只能以字(16位)的形式操作。 
    0:对对应的ODRy位不产生影响 
    1:设置对应的ODRy位为1 


端口位复位寄存器BRR: 
位31:16  保留。  
位15:0 BRy: 清除端口x的位y (y = 0…15)  
     这些位只能写入并只能以字(16位)的形式操作。  
     0:对对应的ODRy位不产生影响  
     1:清除对应的ODRy位为0  


使用方法: 

1.混合改变 
需要置1的端口对应的位,在低16位里置1 
需要置0的端口对应的位,在高16位里置1, 
不改变的,都置0. 
然后写寄存器BSRR 

2.改变引脚为低 
需要置0的端口对应的位,在低16位里置1, 
然后写寄存器BRR 

3.改变引脚为高 
需要置1的端口对应的位,在低16位里置1 
高16为全0 
然后写寄存器BSRR 


另外就是,STM32的库,GPIO_SetBits,GPIO_ResetBits,可以对多个引脚操作的,就是把需要操作的引脚用“|”(或运算)。 

最方便的还是自己直接写寄存器(方法1)。

规则: 
一、置GPIOD->BSRR低16位的某位为'1',则对应的I/O端口置'1';而置GPIOD->BSRR低16位的某位为'0',则对应的I/O端口不变。 
二、置GPIOD->BSRR高16位的某位为'1',则对应的I/O端口置'0';而置GPIOD->BSRR高16位的某位为'0',则对应的I/O端口不变。 
三、置GPIOD->BRR低16位的某位为'1',则对应的I/O端口置'0';而置GPIOD->BRR低16位的某位为'0',则对应的I/O端口不变。 

例如: 
1)要设置D0、D5、D10、D11为高,而保持其它I/O口不变,只需一行语句: 
  GPIOD->BSRR = 0x0C21;// 使用规则一 

2)要设置D1、D3、D14、D15为低,而保持其它I/O口不变,只需一行语句: 
  GPIOD->BRR = 0xC00A;// 使用规则三 

3)要同时设置D0、D5、D10、D11为高,设置D1、D3、D14、D15为低,而保持其它I/O口不变,也只需一行语句: 
  GPIOD->BSRR = 0xC00A0C21;// 使用规则一和规则二 

--------------------------------------------------------------------------------


举个例子说明如何使用这两个寄存器和所体现的优势。例如GPIOE的16个IO都被设置成输出,而每次操作仅需要改变低8位的数据而保持高8位不变,假设新的8位数据在变量Newdata中,

这个要求可以通过操作这两个寄存器实现,STM32的固件库中有两个函数GPIO_SetBits()和GPIO_ResetBits()使用了这两个寄存器操作端口。

上述要求可以这样实现:

GPIO_SetBits(GPIOE, Newdata & 0xff);
GPIO_ResetBits(GPIOE, (~Newdata & 0xff));

也可以直接操作这两个寄存器:

GPIOE->BSRR = Newdata & 0xff;
GPIOE->BRR = ~Newdata & 0xff;

当然还可以一次完成对8位的操作:

GPIOE->BSRR = (Newdata & 0xff) | (~Newdata & 0xff)<<16;

从最后这个操作可以看出使用BSRR寄存器,可以实现8个端口位的同时修改操作。

--------------------------------------------------------------------------------

如果不是用BRR和BSRR寄存器,则上述要求就需要这样实现:

GPIOE->ODR = GPIOE->ODR & 0xff00 | Newdata;

--------------------------------------------------------------------------------


使用BRR和BSRR寄存器可以方便地快速地实现对端口某些特定位的操作,而不影响其它位的状态。

比如希望快速地对GPIOE的位7进行翻转,则可以:

GPIOE->BSRR = 0x80; // 置'1'
GPIOE->BRR = 0x80; // 置'0'

如果使用常规'读-改-写'的方法:

GPIOE->ODR = GPIOE->ODR | 0x80; // 置'1'
GPIOE->ODR = GPIOE->ODR & 0xFF7F; // 置'0'

--------------------------------------------------------------------------------


有人问是否BSRR的高16位是多余的,请看下面这个例子:

假如你想在一个操作中对GPIOE的位7置'1',位6置'0',则使用BSRR非常方便: 
  GPIOE->BSRR = 0x400080; 

如果没有BSRR的高16位,则要分2次操作,结果造成位7和位6的变化不同步! 
  GPIOE->BSRR = 0x80; 
  GPIOE->BRR = 0x40;

猜你喜欢

转载自blog.csdn.net/flyme2010/article/details/81161523
今日推荐