1,位绑定的概念:
将一个单元(32位)中的某个位通过一个算法映射到地址,对地址进行操作(最低位有效)。
2,位绑定的优点:
直接操作地址,代码执行效率更高,安全性高
3,cortex中绑定区域:
SRAM区:0x2000 0000 ~ 0x200f ffff (1M的绑定区)
片上外设:0x4000 0000 ~ 0x200f ffff (1M的绑定区)
4,通过位绑定实现位的快速操作:
位绑定公式:
SRAM区:
绑定后的新地址 = 0x2200 0000 +((本身地址 - 0x2000 0000)*8 + n)*4
= 0x2200 0000 +(本身地址 - 0x2000 0000)*32 + n*4 //*32是32个位,*4是4个字节,n=0~7是以字节为单位;n=0~31是以字为单位
片上外设:
绑定后的新地址 = 0x4200 0000 +((本身地址 - 0x4000 0000)*8 + n)*4
= 0x4200 0000 +(本身地址 - 0x4000 0000)*32 + n*4
5,示例:
#include"stm32f10x_lib.h"
#include"stdio.h"
#define PA1 GPIOA->BSRR
#define PA0 GPIOA->BRR
#define GPIOA_ODR_A (GPIOA_BASE + 0x0C)
#define GPIOA_IDR_A (GPIOA_BASE + 0x08)
#define BitBand(Addr,BitNum) *((volatile unsigned long *)((Addr&0xF0000000)+0x2000000+((Addr&0xFFFFF)<<5)+(BitNum<<2)))
#define PAout(n) BitBand(GPIOA_ODR_A,n)
#define PAin(n) BitBand(GPIOA_IDR_A,n)
int main(void)
{
// ODR地址 基地址 偏移地址
// u32 *PAO3 = (u32 *)(GPIOA_BASE+0x0C);
// 绑定后的地址 第三位
u32 *PAO3 = (u32 *)(0x42000000+(0x4001080C-0x40000000)*32+3*4);
u32 *PAI11 = (u32 *)(0x42000000+(0x40010808-0x40000000)*32+11*4);
// 或者u32 *PAI11 = (u32 *)(0x42000000+(0x40010809-0x40000000)*32+3*4);
//1,PA0~PA7作为输出:推挽输出50MHZ; PA8~PA15作为输入:浮空输入
GPIOA->CRL = 0x33333333;
GPIOA->CRH = 0x44444444;
//2,输入状态反映到对应引脚的输出
while(1)
{
if((GPIOA->IDR & 0x0100) == 0x0100) /*8*/ PA1 = 0x01; //宏定义方式
else PA0 = 0x01;
if((GPIOA->IDR & 0x0200) == 0x0200) /*9*/ PA1 = 0x02;
else PA0 = 0x02;
if((GPIOA->IDR & 0x0400) == 0x0400) /*10*/ GPIOA->BSRR = 0x04; //位操作方式
else GPIOA->BRR = 0x04;
//A = GPIOA_BASE + ODRÆ«ÒƵØÖ· = GPIOA_BASE+0x0C n = 3
//A = GPIOA_BASE + IDRÆ«ÒƵØÖ· = GPIOA_BASE_0x08 n = 3
if(*PAI11 == 1) /*11*/ *PAO3 = 1; //位绑定方式
else *PAO3 = 0;
if((GPIOA->IDR & 0x1000) == 0x1000) /*12*/ GPIOA->ODR = GPIOA->ODR | 0x10; //计算
else GPIOA->ODR = GPIOA->ODR & (~0x10);
if(PAin(13) == 1) /*13*/ PAout(5) = 1; //位绑定公式方法
else PAout(5) = 0;
if((GPIOA->IDR & 0x4000) == 0x4000) /*14*/ GPIOA->ODR = GPIOA->ODR | 0x40;
else GPIOA->ODR = GPIOA->ODR & (~0x40);
if((GPIOA->IDR & 0x8000) == 0x8000) /*15*/ GPIOA->ODR = GPIOA->ODR | 0x80;
else GPIOA->ODR = GPIOA->ODR & (~0x80);
}
return(1);
}