STM32寄存器定义分析

了解下库函数寄存器的定义过程,对我们理解底层很有帮助。以后开发其他软件可以效仿此类定义方法。

1. 寄存器定义

这里以STM32F1xx系列的 GPIO)为例,库函数找到的相关代码如下

#define PERIPH_BASE           ((u32)0x40000000)

#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)

#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)

#define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)

首先前3行,不用解释太多,就是数据的宏定义。这个数据最终计算出来GPIOB的基地址

GPIOB_BASE= 0x4001 0C00

对照手册,正确无误。

第四行可能有小伙伴就得思考下了,其实也非常简单,(GPIO_TypeDef *)就是一个强制类型转换。 因为前面编译器就认为GPIOB_BASE就是一个数据。经过强转后,就可以把GPIOB_BASE转换成一个结构体指针。

然后经过宏定义#define GPIOB   ((GPIO_TypeDef *) GPIOB_BASE)

则GPIOB   就代表指向的是 RCC_TypeDef定义的结构体指针了。

GPIO_TypeDef的定义是这样做的:

typedef struct
{
  vu32 CRL;
  vu32 CRH;
  vu32 IDR;
  vu32 ODR;
  vu32 BSRR;
  vu32 BRR;
  vu32 LCKR;
} GPIO_TypeDef;

结构体里面的GPIO的各寄存器需要按顺序定义,因为结构体成员的地址是按首地址连续往下排列的。所以各成员需要根据偏移地址的高低来确定,如果寄存器的偏移地址不连续,结构体要空出相应的位置。参考手册截图如下,方便对应。

2. 应用

结构体指针对成员的引用用“->”符号即可。

比如上面GPIOB的使用

	GPIOB->CRL&=0XFF0FFFFF; 
	GPIOB->CRL|=0X00300000;//PB5 推挽输出   	 
    GPIOB->ODR|=1<<5;      //PB5 输出高
											  

3. 补充(了解即可,有些时候自己用裸机定义一些寄存器可以参考)

上面是STM32官方的定义方式。当然有一些程序员自己开发裸机的时候用下列方式,如上面端口B输出寄存器GPIOB_ODR 如下定义:


#define GPIOB_ODR   (*((volatile uint32_t *)0x40010C0C))

这里0x40010C0C,对应GPIOB的输出寄存器地址(基地址0x4001 0C00+偏移地址0x0C),但是编译器同时不知道是个地址,所以用强制类型转换(volatile uint32_t *)将数据强制转换成一个指针,指针指向0x40010C0C地址的值,然后外面一个取数据的符号,*((volatile uint32_t *)0x40010C0C)代表取GPIOB_ODR里面的值,通过宏定义,改变GPIO的输出只需要修改GPIOB_ODR值即可,如下

GPIOB_ODR=1<<5;      //PB5 输出高

如果采用官方的库的定义,要实现同样功能是这样写:

GPIOB->ODR|=1<<5;      //PB5 输出高

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值