端口位设置/清除寄存器(GPIOx_BSRR) (x=A..E)
端口位清除寄存器(GPIOx_BRR) (x=A..E)
虽然一开始学板子就点灯了,突然发现不懂这两个寄存器的用法。
用法规则:
一、置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;// 使用规则一和规则二
例如点灯程序中:
void LED_SetState(u8 stateValue)
{
GPIOC->BSRR = (u16)stateValue & 0x00FF;
GPIOC->BRR = ~((u16)stateValue & 0x00FF);
}
使用BRR和BSRR寄存器可以方便地快速地实现对端口某些特定位的操作,而不影响其它位的状态。
比如希望快速地对GPIOA的位7进行翻转,则可以:
GPIOA->BSRR = 0x80; // 置’1’
GPIOA->BRR = 0x80; // 置’0’
如果使用常规’读-改-写’的方法:
GPIOA->ODR = GPIOA->ODR | 0x80; // 置’1’
GPIOA->ODR = GPIOA->ODR & 0xFF7F; // 置’0’
并且BSRR的高16也是常用的:
对GPIOE的位7置’1’,位6置’0’:
GPIOE->BSRR = 0x4080;
如果没有BSRR的高16位,则要分2次操作,结果造成位7和位6的变化不同步!
GPIOE->BSRR = 0x80;
GPIOE->BRR = 0x40;