通过位绑定来快速实现位操作。
这些区域可以进行位绑定
SRAM区:0x2000 0000 ~ 0x200f ffff 1M
公式:A的范围(0x2000 0000 ~ 0x200f ffff) n的范围(0~7),表示第几位 ,AliasAddr表示位绑定的地址
AliasAddr = 0x22000000 + ((A-0x20000000)*8 + n)*4
= 0x22000000 + (A-0x20000000)32 + n4
片上外设:0x4000 0000 ~ 0x400f ffff 1M
公式:A的范围(0x4000 0000 ~ 0x400f ffff) n的范围(0~7),表示第几位,AliasAddr表示位绑定的地址
AliasAddr = 0x42000000 + ((A-0x40000000)*8 + n)*4
= 0x42000000 + (A-0x40000000)32 + n4
拿如下一小段代码举例:
if((GPIOA->IDR & 0x0800) == 0x0800) GPIOA->ODR = GPIOA->ODR | 0x08;
else GPIOA->ODR = GPIOA->ODR & (~0x08);
首先看GPIOA->ODR的地址是多少
GPIOA_ODR:
A = GPIO_ODR的地址= GPIOA_BASE+ODR偏移地址 = GPIOA_BASE+0x0C (0Ch中的h表示16进制)
n = 3 (0x08表示操作的是第三位)
GPIOA_IDR:(地址查询方法同ODR)
A = GPIO_ODR的地址= GPIOA_BASE+ODR偏移地址 = GPIOA_BASE+0x09 (0Ch中的h表示16进制)
n = 3 (0x0800表示操作的同样是第三位,范围0-7)
int main(void)
{
//ODR 和 IDR 这里属于片内外设
//ODR的地址:即A=(0x4000000 + 0x10000 + 0x0800 + 0x0c)= 0x4001080c n=3
u32 *PAO3 = (u32*)(0x42000000 + (0x4001080c - 0x40000000)*32 + 3*4) //PAO3表示GPIOA输出第3位
//IDR的地址:即A=(0x4000000 + 0x10000 + 0x0800 + 0x09)= 0x40010809 n=3
u32 *PAI11 = (u32*)(0x42000000 + (0x40010809 - 0x40000000)*32 + 3*4) //PAI11表示GPIOA输入第11位
//或者:u32 *PAI11 = (u32*)(0x42000000 + (0x40010808 - 0x40000000)*32 + 11*4)
// 1、PA.0 ~ PA.7 输出、50Mhz PA.8 ~ PA.15 输入(PA.0用到CRL, PA.8用到CRH)
GPIOA->CRL = 0x33333333; //PA.0 ~ PA.7 输出、50Mhz
GPIOA->CRL = 0x44444444; //PA.8 ~ PA.15 输入(选择浮空输入,因为模拟输入与复用输入不经过输入数据寄存器)
// 2、PA.8 ~ PA.15 引脚输入状态影响PA.0 ~ PA.7 引脚输出状态
while(1)
{
//if((GPIOA->IDR & 0x0800) == 0x0800) GPIOA->ODR = GPIOA->ODR | 0x08;
//else GPIOA->ODR = GPIOA->ODR & (~0x08);
//简化为:
if(*PAI11 == 1) *PAO3 = 1; //写1直接置1
else *PAO3 = 0; //清零直接置0
}
return(1);
}
继续简化:
1.定义地址
2.定义公式
#define GPIOA_ODR_A (GPIOA_BASE+0x0C)
#define GPIOA_IDR_A (GPIOA_BASE+0x08)
#define GPIOA_ODR_B (GPIOB_BASE+0x0C)
#define GPIOA_IDR_B (GPIOB_BASE+0x08)
#define GPIOA_ODR_C (GPIOC_BASE+0x0C)
#define GPIOA_IDR_C (GPIOC_BASE+0x08)
#define GPIOA_ODR_D (GPIOD_BASE+0x0C)
#define GPIOA_IDR_D (GPIOD_BASE+0x08)
#define GPIOA_ODR_E (GPIOE_BASE+0x0C)
#define GPIOA_IDR_E (GPIOE_BASE+0x08)
//0x22000000 + (A-0x20000000)*32 + n*4
//0x42000000 + (A-0x40000000)*32 + n*4
//合并为 ((A&0xF0000000) +0x2000000+ ((A&0xfffff)*32) + n*4)
#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)
{
// 1、PA.0 ~ PA.7 输出、50Mhz PA.8 ~ PA.15 输入(PA.0用到CRL, PA.8用到CRH)
GPIOA->CRL = 0x33333333; //PA.0 ~ PA.7 输出、50Mhz
GPIOA->CRL = 0x44444444; //PA.8 ~ PA.15 输入(选择浮空输入,因为模拟输入与复用输入不经过输入数据寄存器)
// 2、PA.8 ~ PA.15 引脚输入状态影响PA.0 ~ PA.7 引脚输出状态
while(1)
{
//if((GPIOA->IDR & 0x0800) == 0x0800) GPIOA->ODR = GPIOA->ODR | 0x08;
//else GPIOA->ODR = GPIOA->ODR & (~0x08);
//简化为:
//if(*PAI11 == 1) *PAO3 = 1; //写1直接置1
//else *PAO3 = 0; //清零直接置0
//再简化为:
if(PAin(11) == 1) PAout(3) = 1; //写1直接置1
else PAout(3) = 0; //清零直接置0
}
return(1);
}
上一篇:STM32-(05):GPIO原理与操作
下一篇:STM32-(07):串行通信基础(164芯片)
推荐阅读最新更新时间:2024-11-02 08:08