位带操作
位带操作:将APB1/2和AHB1这些外设的每一位寄存器都映射到一个32位地址中去
将别名区的四位映射为位带区的1个位
存在两个各1M的位带区:分别为0x4000 0000-0x400F 0000 和0x2000 0000 - 0x200F 0000
将一个32位的寄存器映射到8位的位带区中
映射公式: A-需要位带操作寄存器所在地址 n-位号
AliasAddr_外设 = 0x4200 0000 + (A-0x4000 0000) x 8 x 4 + n x 4
AliasAddr_SRAM = 0x2200 0000 + (A-0x4000 0000) x 8 x 4 + n x 4
合并公式:
((addr & 0xF0000000 )+ 0x20000000+((addr &0x00FFFFFF)<<5) + (n<<2))
三种原子操作
//1. 固件库原子操作
// GPIO_SetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN);
// Time();
// GPIO_ResetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN);
// Time();
//2. 寄存器原子操作
// LED_G_GPIO_PORT->BRR = LED_G_GPIO_PIN;
// Time();
// LED_G_GPIO_PORT->BSRR = LED_G_GPIO_PIN;
// Time();
//3. 位带原子操作
// #define GPIO_ODR_Addr ( GPIOB_BASE+ 0x0C)
// #define PBou *( unsigned int*) (0x42000000 + (GPIO_ODR_Addr-0x40000000)*8*4 +1 * 4 )
// PBou = 1;
// Time();
// PBou = 0;
// Time();
按键的位带原子操作
#define GPIO_IDR_Addr ( GPIOA_BASE+ 0x08)
#define PAin(n) *( unsigned int*) (0x42000000 + (GPIO_IDR_Addr-0x40000000)*8*4 + (n * 4) )
if( PAin(0) == Key_ON)
{
while(PAin(0) == Key_ON);//松手检测
LED_G_TOGGLE; //状态反转
}
}