STM32寄存器结构体定义

因为unit32_t是32位的,也就是四个字节,CRL就从GPIOB_BASE的地址开始占四个字节的位置,CRH存放的地址就自动+4个字节了,正好是偏移量,就免去了每次都用#define去根据基地址去偏移了


//基地址+偏移地址 就能得到寄存器的地址
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)

#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)


#define RCC_BASE      (AHBPERIPH_BASE + 0x1000)


typedef unsigned int    uint32_t;
typedef unsigned short  uint16_t;

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

//强制类型转换 表示在代码中使用GPIOB时,会被替换为指向GPIOB外设的指针。
#define GPIOB ((GPIO_TypeDef*)GPIOB_BASE)
	

这段程序的目的是为了方便地访问特定微控制器的 GPIOB 外设

下面是这段程序的工作原理:

  1. 首先,通过宏定义的方式,确定了 GPIOB 外设寄存器在内存中的基地址。具体的计算方法是通过对应的外设基地址(如 APB2PERIPH_BASE)加上偏移地址(如 0x0C00)来得到 GPIOB 的基地址。

  2. 接下来,定义了一个名为 GPIO_TypeDef 的结构体,其中包含了 GPIO 外设的不同寄存器,如 CRL、CRH、IDR、ODR、BSRR、BRR 和 LCKR。

  3. 最后,通过宏定义 #define GPIOB ((GPIO_TypeDef*)GPIOB_BASE),将 GPIOB 外设基地址强制类型转换为 GPIO_TypeDef* 类型的指针,也就是将其解释为指向 GPIO_TypeDef 结构体的指针。

通过这样的宏定义,以后在代码中使用 GPIOB 时,就可以直接通过指针访问 GPIOB 外设的寄存器,从而方便地对 GPIOB 进行配置和操作。例如:

GPIOB->CRL = 0x00000001; // 对 GPIOB 的 CRL 寄存器进行配置
GPIOB->ODR |= (1 << 5);  // 设置 GPIOB 的第 5 位输出

 

为什么用typedef而不用define?

typedef unsigned int    uint32_t;
typedef unsigned short  uint16_t;

在 C/C++ 中,可以使用 #define 来创建简单的别名,但是使用 typedef 更适合创建类型别名。虽然两者都能达到类似的效果,但 typedef 在某些情况下更灵活且更安全。

使用 #define 创建别名会直接进行文本替换,这可能导致一些潜在的问题。例如:

#define A int
A x, y; // 替换后:int x, y;

这样会将 A完全替换为 int,但是有时候可能意外地影响到其他代码,尤其是在代码规模较大的情况下。

typedef 则会在编译器级别创建类型别名,它更安全且更易于维护。例如:

typedef int A;
A x, y; // 此时 A 是 int 的别名

使用 typedef,编译器会将 A视为 int 的别名,这样做不会引起不必要的替换或潜在错误。

因此,虽然 #define 可以用于创建别名,但建议在 C/C++ 中使用 typedef 来定义类型别名,因为它更安全、更符合语义,而且更容易维护。

 

结构体:

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

这是一个典型的 C typedef 结构体定义,用于表示特定的 GPIO(General Purpose Input/Output)外设寄存器映射。

让我来解释一下这段代码:

  1. typedef: 这是 C中用于定义类型别名的关键字。

  2. struct: 这是 C 中用于定义结构体的关键字。

  3. GPIO_TypeDef: 这是结构体的名称,代表这个结构体类型的别名。

  4. 大括号 {} 中是结构体的成员,每个成员都是一个无符号32位整数(uint32_t)。这些成员代表了 GPIO 外设的不同寄存器,其中包括:

    • CRL:GPIO控制寄存器低位(Control Register Low)
    • CRH:GPIO控制寄存器高位(Control Register High)
    • IDR:GPIO输入数据寄存器(Input Data Register)
    • ODR:GPIO输出数据寄存器(Output Data Register)
    • BSRR:GPIO位设置/复位寄存器(Bit Set/Reset Register)
    • BRR:GPIO位复位寄存器(Bit Reset Register
    • LCKR:GPIO锁定寄存器(Lock Register)

这样的结构体定义可以很方便地访问和控制特定微控制器中的GPIO外设寄存器,使得对GPIO的配置和操作更加简洁和可读。例如,可以通过访问 GPIO_TypeDef 结构体的成员来控制和读取 GPIO 的不同功能和状态。

#define GPIOB((GPIO_TypeDef*)GPIOB_BASE)

((GPIO_TypeDef*)GPIOB_BASE) 这部分代码是一个类型转换(type-casting)的表达式。让我解释一下:

  1. GPIO_TypeDef: 这是一个类型名称,是在特定的微控制器或嵌入式系统中定义的结构体类型,用于表示GPIO外设的寄存器映射。

  2. GPIOB_BASE: 这是一个宏或符号常量,表示GPIOB外设在内存中的基地址。基地址是指外设寄存器的起始地址,通过访问这个地址,可以读写控制外设的寄存器。

  3. (GPIO_TypeDef*): 这是C/C++中的类型转换语法。通过将GPIOB_BASE强制转换为GPIO_TypeDef类型的指针,可以将该地址解释为GPIO外设的寄存器映射结构。

综合来说,((GPIO_TypeDef*)GPIOB_BASE) 这个表达式的作用是将GPIOB外设的基地址转换为指向该外设的结构体指针,使得程序可以通过指针访问该外设的寄存器,并进行相关的控制和配置。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值