一、 STM32头文件中 结构体封装寄存器的方法
typedef struct
{
vu32 CR;
vu32 CFGR;
vu32 CIR;
vu32 APB2RSTR;
vu32 APB1RSTR;
vu32 AHBENR;
vu32 APB2ENR;
vu32 APB1ENR;
vu32 BDCR;
vu32 CSR;
} RCC_TypeDef;
#define PERIPH_BASE((u32)0x40000000)
#define AHBPERIPH_BASE(PERIPH_BASE + 0x20000)
#define RCC_BASE(AHBPERIPH_BASE + 0x1000)
#define RCC((RCC_TypeDef *) RCC_BASE)
在头文件中这样界说后,就能够在程序中以
RCC->CR|=0x00010000;来直接操作某一寄存器了。
二、对这一方法的剖析与总结也便是关于单片机寄存器封装问题:
最近在学习嵌入式linux过程中,看到 DM368寄存器地址映射到结构体封装的寄存器的体系文件。由于嵌入式linux开发没有像单片机相同的编译软件,体系文件不是编译软件自身自带的。嵌入式编程需求自己找到需求用的模块的头文件,来操作相应的寄存器,编写相应的驱动。所以乎,在看他人的程序时,模模糊糊的就从主程序看到了驱动程序,又看到了底层操作寄存器的程。为了完全搞懂嵌入式程序,总算留意到了曾经单片机编程时没怎么留意过的结构体封装寄存器,映射物理地址。看了好半天也没有看理解 宏界说是怎么映射地址的,关键是这样语法的一句话:
#define RCC((RCC_TypeDef *) RCC_BASE)
RCC_BASE的界说是 #define RCC_BASE(AHBPERIPH_BASE + 0x1000) 是物理地址通过代换(AHBPERIPH_BASE + 0x1000)=0x40021000
通过思索和请教,对这种封装寄存器的来龙去脉总算茅塞顿开。
首要,碰到#define一定要紧记C言语教师的教导–‘仅仅是替换’。因此在运用结构体封装的寄存器来操作寄存器时,如RCC->CR =0x00实际上等价于 ((RCC_TypeDef *) RCC_BASE)->CR=0x00。 进一步,将RCC_BASE替换为 (AHBPERIPH_BASE + 0x1000) ,这儿AHBPERIPH_BASE是地址,也是常量。所以整句话就被还原为 ((RCC_TypeDef *)0x40021000)->CR=0x00 。
也便是 先对地址常量 (AHBPERIPH_BASE + 0x1000) 进行强制类型转换为 (RCC_TypeDef )类型的结构体指针。由结构体指针的相关常识可知,将一个地址指向结构体,那么该地址后边的地址会主动按结构体中界说的结构体成员来区分。所以 ,作为该结构体的第一个成员CR,((RCC_TypeDef *)0x40021000)->CR也便是代表 (AHBPERIPH_BASE + 0x1000) 。 以此类推 ,,((RCC_TypeDef *)0x40021000)->CFGR 则代表
RCC_BASE(0x40021000)的下一段地址 即0x40021004 (手册中 RCC_CFGR寄存器的地址)。
能够看到这种结构体封装寄存器方法拜访寄存器的本质仍然是直接对寄存器地点的物理地址操作!!
至于为什么用这种方法来封装结构体。能够参阅51单片机寄存器的界说方法。keil中51单片机每一个寄存器是直接给出对应的存储器地址,而没有用这种结构体方法封装。由于操作寄存器的本质永远都是对寄存器地点的地址操作。 STM32 中寄存器许多,假如像51相同 对每一个寄存器地址给定一个寄存器称号,太冗杂并且没有直观性。结构体封装,能够直观的看出每个模块中有哪些寄存器,便利编程。
图:keil中51寄存器的界说方法
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/dianyuan/258402.html