如何理解STM32中的RCC宏定义和RCC_TypeDef数据类型?

如何理解stm32中的#define RCC ((RCC_TypeDef *) RCC_BASE)

#define RCC ((RCC_TypeDef *) RCC_BASE)

在stm32寄存器开发中,经常看到下面的写法:
stm32截图
#define RCC ((RCC_TypeDef *) RCC_BASE),笔者第一次看到颇感困惑,最终也算搞懂了一点。
其中,RCC_TypeDef是一个定义的结构体,具体代码如下:

typedef struct
{
  __IO uint32_t CR;
  __IO uint32_t CFGR;
  __IO uint32_t CIR;
  __IO uint32_t APB2RSTR;
  __IO uint32_t APB1RSTR;
  __IO uint32_t AHBENR;
  __IO uint32_t APB2ENR;
  __IO uint32_t APB1ENR;
  __IO uint32_t BDCR;
  __IO uint32_t CSR;

#ifdef STM32F10X_CL  
  __IO uint32_t AHBRSTR;
  __IO uint32_t CFGR2;
#endif /* STM32F10X_CL */ 

#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)   
  uint32_t RESERVED0;
  __IO uint32_t CFGR2;
#endif /* STM32F10X_LD_VL || STM32F10X_MD_VL || STM32F10X_HD_VL */ 
} RCC_TypeDef;

其次是RCC_BASE来源:

#define RCC_BASE              (AHBPERIPH_BASE + 0x1000)
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)
#define PERIPH_BASE           ((uint32_t)0x40000000)
typedef unsigned int uint32_t;

可以看到,RCC_BASE实际上是一个字节长度为4的无符号整形变量,经过各种宏定义,相加,最终RCC_BASE的值为 0x40000000+0x20000+0x1000=0x40021000

下面详细分析 #define RCC ((RCC_TypeDef *) RCC_BASE)

我们知道了RCC_BASE是一个无符号整型变量,为了将变量与地址0x40021000所指向的存储单元对应起来,我们通过( *)RCC_BASE强制类型转换,使得RCC_BASE变成我们所需要的地址,也就是寄存器的基地址。

而(RCC_TypeDef *) 的意思是类型长度为RCC_TypeDef,也就是该地址指向的存储单元占据多少个字节,通常我们采用(int *)RCC_BASE来说明,但是使用RCC_Typede可以方便知道此组寄存器需要多少字节。

(RCC_TypeDef *) RCC_BASE,也就是在RCC_BASE基地址申请了一个结构体,结构体RCC_TypeDef包含10个4字节成员,他们在基地址上开辟了连续的10个32变量的存储空间,

最后再由宏定义,将((RCC_TypeDef *) RCC_BASE)由RCC代替,这样可以直接通过RCC访问结构体的成员地址。

硬件联系

那么此写法是如何与寄存器建立联系的,通过查阅stm32官方参考手册,不难发现,RCC_BASE的值刚好代表RCC寄存器组起始地址。

通过查看RCC寄存器组的地址偏移,发现一个寄存器偏移4个字节,刚好对应结构体中uint32_t 。

下面做一个简单的实验,为了方便,直接把RCC_BASE赋值为0x10000000:

#include <stdio.h>

typedef unsigned int uint32_t;

typedef struct {
    volatile uint32_t CR;
    volatile uint32_t CFGR;
    volatile uint32_t CIR;
    volatile uint32_t CSR;
}RCC_Typedef;
#define  RCC  ((RCC_Typedef *)0x10000000)

int main() {
    printf("%x\n",&(RCC->CR));
    printf("%x\n",&(RCC->CFGR));
    printf("%x\n",&(RCC->CIR));
    printf("%x\n",&(RCC->CSR));
    printf("%d\n",sizeof (RCC_Typedef));
    }
    return 0;
}

输出结果为:

由此可见,RCC_TypeDef的长度为4*4=16。RCC->CR的地址为10000000。因为uint32_t字节长度为4,所以结构体内的成员变量地址4字节的累加。

参考来源:
[1]:https://www.cnblogs.com/caolinsummer/p/5643942.html
[2]:https://blog.csdn.net/childbor/article/details/86770360#:~:text=%23define%20RCC%20%28%28RCC_TypeDef%20%2A%29%20RCC_BASE%29%20RCC_TypeDef%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E7%BB%93%E6%9E%84%E4%BD%93,RCC_BASE%E6%98%AF%E4%B8%80%E4%B8%AAunsigned%20long%EF%BC%8832%E4%BD%8D%E6%95%B0%E5%80%BC%EF%BC%89%20%E7%AE%80%E5%8C%96%E5%90%8E%E6%98%AF%EF%BC%9A%20%28int%20%2A%29%200xb8000000.

作者:茶多多z

物联沃分享整理
物联沃-IOTWORD物联网 » 如何理解STM32中的RCC宏定义和RCC_TypeDef数据类型?

发表评论