嵌入式开发中经常会对寄存器操作,所以为了提高代码可读性会对寄存器进行封装
typedef struct {
vu32 ACR; // offset 0x000
vu32 KEYR; // offset 0x004
vu32 OPTKEYR; // offset 0x008
vu32 SR; // offset 0x00C
vu32 CR; // offset 0x010
vu32 AR; // offset 0x014
} FLASH_TypeDef;
这里对FLASH 寄存器定义了一个结构体;
然后对寄存器基地址进行定义 #define FLASH_BASE 0x1FFFFF80
#define FLASH ((FLASH_TypeDef*) FLASH_BASE) 就实现了定义一个名为 FLASH(存放在内存地址为0x1FFFF80)的结构体指针 通过访问 成员变量 FLASH->ACR = value 来实现赋值;
怎么理解呢 首先结构体定义比较好理解,只是 ((FLASH_TypeDef*) FLASH_BASE) 不太好理解
((FLASH_TypeDef*) FLASH_BASE) 替换成 《==》 ( ( int * ) adr )
是不是就容易理解了,其实就类似于一个结构体变量的定义。
理解一下:变量也是存放在内存中的,而把adr替换成具体地址,就是告诉编译器,程序员已经指定好了这个变量的内存地址。一直使用地址去操作,总不太好,所以宏定义一个别名FLASH。
上述操作实现了对地址的写,那怎么去读地址的值呢,如下定义:
#define M32(adr) *( (uint32_t *)adr)
同理 ((uint32_t *)adr) 把adr替换成具体的地址,就实现了具体存放在某一内存地址的指针定义
然后利用 * 取地址值的方式去读地址值 value = M32(0x1FFFFF80) ;
其实这种方式也是可写的 M32(0x1FFFFF80) | = value ;
对于单一地址更方便读写。