位带简介
位操作就是可以单独的对一个比特位读和写, 51 单片机中通过关键字 sbit 来实现位定义, STM32 没有这样的关键字,而是通过访问位带别名区来实现。
在 STM32 中,有两个地方实现了位带,一个是 SRAM 区的最低 1MB 空间,令一个是外设区最低 1MB 空间。这两个 1MB 的空间除了可以像正常的 RAM 一样操作外,他们还有自己的位带别名区,位带别名区把这 1MB 的空间的每一个位膨胀成一个 32 位的字,当访问位带别名区的这些字时,就可以达到访问位带区某个比特位的目的
位带地址转换
位带区的一个位,对应位带别名区的四个字节。一个字节对应一个地址。
8表示一个地址对应一个字节,一个字节有8个位,4表示1位对应4个别名区的字节(地址)
使用位带方式访问寄存器
main.c
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_key.h"
#define GPIOB_ODR_Addr (GPIOB_BASE+ 0x0C)
#define PBout(n) *(unsigned int*)((GPIOB_ODR_Addr & 0xF0000000)+0x02000000+((GPIOB_ODR_Addr & 0x00FFFFF)<<5)+(n<<2))
#define GPIOA_IDR_Addr (GPIOA_BASE+ 0x08)
#define PAin(n) *(unsigned int*)((GPIOA_IDR_Addr & 0xF0000000)+0x02000000+((GPIOA_IDR_Addr & 0x00FFFFF)<<5)+(n<<2))
#define GPIOC_IDR_Addr (GPIOC_BASE+ 0x08)
#define PCin(n) *(unsigned int*)((GPIOC_IDR_Addr & 0xF0000000)+0x02000000+((GPIOC_IDR_Addr & 0x00FFFFF)<<5)+(n<<2))
void Delay( uint32_t count)
{
for(;count != 0;count--);
}
//void GreenLed(uint32_t t)
//{
// LED_G(ON);
// LED_B(OFF);
// LED_R(OFF);
// Delay(t);
//}
//void BlueLed(uint32_t t)
//{
// LED_G(OFF);
// LED_B(ON);
// LED_R(OFF);
// Delay(t);
//}
//void RedLed(uint32_t t)
//{
// LED_G(OFF);
// LED_B(OFF);
// LED_R(ON);
// Delay(t);
//}
int main(void)
{
LED_G_GPIO_Config();
LED_B_GPIO_Config();
KEY1_GPIO_Config();
KEY2_GPIO_Config();
#if 0
while(1)
{
PBout(0) = 1;
PBout(1) = 1;
Delay(0xFFFFF);
PBout(0) = 0;
Delay(0xFFFFF);
PBout(0) = 1;
Delay(0xFFFFF);
PBout(1) = 0;
Delay(0xFFFFF);
PBout(1) = 1;
Delay(0xFFFFF);
PBout(0) = 0;
PBout(1) = 0;
Delay(0xFFFFF);
}
#else
while(1)
{
// if(Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_Pin) == KEY_ON)
// {
// LED_G_TOGGLE;
//
// }
//
// if(Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_Pin) == KEY_ON)
// {
// LED_B_TOGGLE;
//
// }
if(PAin(0) == KEY_ON)
{
while(PAin(0) == KEY_ON);
LED_G_TOGGLE;
}
if(PCin(13) == KEY_ON)
{
while(PCin(13) == KEY_ON);
LED_B_TOGGLE;
}
}
#endif
}