访问寄存器是基地址加偏移
用ADC1—>DR
访问DR寄存器,&ADC1—>DR
访问DR寄存器地址
#define ADC1 ((ADC_TypeDef *) ADC1_BASE)
//把ADC1_BASE(ADC1的基地址)强转为ADC_TypeDef型的指针
#define ADC1_BASE (APB2PERIPH_BASE + 0x2400)
//等于APB2外设基地址加0x2400
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
//等于外设基地址加0x10000
#define PERIPH_BASE ((uint32_t)0x40000000)
//外设基地址等于0x40000000(4*8=32位)
/*补充:
#define FLASH_BASE ((uint32_t)0x08000000)
#define SRAM_BASE ((uint32_t)0x20000000)
*/
此时ADC1基地址有了,等于40012400,再加一个偏移就能得到DR寄存器的地址,库函数巧妙地使用结构体实现偏移。
跳转到ADC_TypeDef
结构体定义
typedef struct
{
__IO uint32_t SR;
__IO uint32_t CR1;
__IO uint32_t CR2;
__IO uint32_t SMPR1;
__IO uint32_t SMPR2;
__IO uint32_t JOFR1;
__IO uint32_t JOFR2;
__IO uint32_t JOFR3;
__IO uint32_t JOFR4;
__IO uint32_t HTR;
__IO uint32_t LTR;
__IO uint32_t SQR1;
__IO uint32_t SQR2;
__IO uint32_t SQR3;
__IO uint32_t JSQR;
__IO uint32_t JDR1;
__IO uint32_t JDR2;
__IO uint32_t JDR3;
__IO uint32_t JDR4;
__IO uint32_t DR;
} ADC_TypeDef;
在结构体里,寄存器个数以及排列顺序与实际的硬件上完全一致。结构体成员正好映射对应寄存器。
把ADC1的基地址ADC1_BASE
强转为ADC_TypeDef
结构体类型的指针,ADC1
此时是ADC_TypeDef
结构体的首地址,使用ADC1—>DR
就能访问该寄存器。
结构体可以类比到数组,数组名array
就是指针,array[0
]就能访问array
数组的第一个元素
结构体名在这里ADC1
就是结构体名(经过强制类型转换)也是结构体首地址也是ADC1外设基地址,ADC1—>DR
就能访问该寄存器。
&ADC1—>DR
得到DR寄存器地址,等于4001244c
实际上上面的套娃等价于:
#define ADC1_DR (uint_32 *)0x4001244c
//把0x4001244c强转为32位的int型指针也就是地址
*ADC1_DR
访问寄存器
&*ADC1_DR
得到DR寄存器地址