本代码在正点原子ministm32 实现,闪亮PD2:
总体来说分两种:
1 通过控制三个寄存器实现,ODR,BRR,BSRR
2 位带地址写0/1实现
操作方式 | 寄存器 | 封装函数 | |
寄存器 | ODR | GPIO_WriteBit | |
BRR | GPIO_ResetBits | ||
BSRR | GPIO_SetBits | ||
位带地址 | 如(*((u32*)0x42228188))=0 |
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BSRR = GPIO_Pin;
}
void GPIO_ResetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin)
{
GPIOx->BRR |= GPIO_Pin;
}
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BSRR = GPIO_Pin;
}
void GPIO_ResetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin){
GPIOx->BRR |= GPIO_Pin;
}
char x=5;
while(1)
{
switch (x) {
case 1:
GPIOD-> ODR =0x0;
delay_ms(0xFF);
GPIOD ->ODR =0xffff;
delay_ms(0x10FF);
break;
case 2:
GPIOD->BRR |= 0x0004; // PD2 ¶ÔÓ¦µÄÊǵÚ3λ£¡²»ÊǵÚ2λ 43210
delay_ms(0xFF);
GPIOD->BSRR |=0x0004;
delay_ms(0xFF);
break;
case 3:
GPIOD->BSRR =0x00040000;
delay_ms(0xFF);
GPIOD->BSRR |=0x0004;
delay_ms(0xFF);
break;
case 4:
GPIO_WriteBit(GPIOD, GPIO_Pin_2,0);
delay_ms(0xFF);
GPIO_WriteBit(GPIOD, GPIO_Pin_2, 1);
delay_ms(0xFF);
break;
case 5:
GPIO_ResetBits(GPIOD, 4);
delay_ms(0xFF);
GPIO_SetBits(GPIOD, 4);
delay_ms(0xFF);
break;
case 6:
(*((u32*)0x42228188))=0; //0x42228180+2*4
delay_ms(0xFF);
(*((u32*)0x42228188))=1;
delay_ms(0x10FF);
break;
default:
}
位绑定地址计算公式为:
结合“豆包” ,prompt: stm32 gpioA PA0的位绑定地址 计算:
AliasAddr = 0x42000000 + ((A - 0x40000000) * 32 + n * 4),其中A为要绑定的寄存器地址,n表示寄存器中的位序号(0~7)。()
PA0的位绑定地址 ,也称位带地址(C是 ODR的偏移地址)
= 0x42000000 + (0x1080C × 32) = 0x42000000 + 0x210180 = 0x42210180
PD2的位绑定地址 ,也称位带地址(C是 ODR的偏移地址)
= 0x42000000 + (0x1140C × 32) + 2 × 4 =0x42228188
注:× 32等于16进制的 x20 ,很方便手算。
教材的算法:
// 把“位带地址+位序号”转换成别名地址的宏
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))
/*
*addr & 0xF0000000,取地址的高4位,看看是2还是4,用于区分SRAM和外设地址,
*如果是2,+0x02000000则=0X2200 0000,即是SRAM,如果是4,+0x02000000则=0X4200 0000,即是外设
*
*addr & 0x000FFFFFF,屏蔽掉高两位,相当于-0X2000 0000或者-0X4000 0000,结果表示偏移位带区多少个字节
*<<5 等于*8*4,因为位带区一个地址表示一个字节,一个字节有8个bit,一个bit可以膨胀成一个字,即4个字节
*<<2 等于*4,因为一个位可以膨胀成一个字,即4个字节
*
*分解成两条公式应该就是这样:
*SRAM位带别名地址
*AliasAddr= 0x2200 0000+((A-0x2000 0000)*8+n)*4 =0x22000000+ (A-0x20000000)*8*4 +n*4
*外设位带别名地址(野火原始把这里弄错了!)
*AliasAddr= 0x4200 0000+((A-0x2000 0000)*8+n)*4 =0x2200 0000+ (A-0x2000 0000)*8*4 +n*4
= 0x4200 0000 +(0x4001 140C - 0x2000 0000)*32*2+2*4 //带入PD2端口数据
= 0x4200 0000 + 0x2001 140C *32*2+8 // *32左移一个16进制的0
= 0x4200 0000+0x2001 140C0*2+8
= 0x 4200 0000
+ 0x 0022 8180
+ 8
= 0x 4222 8188
*/
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001 140C